def to_parquet(
        self,
        path: Union[str, os.PathLike[str], BinaryIO],
        partition_cols: Optional[Sequence[str]] = None,
        chunk_size: int = DEFAULT_PARQUET_CHUNK_SIZE,
        fs_kwargs: Optional[dict[str, Any]] = None,
        **kwargs,
    ) -> None:
        """Save chain to parquet file with SignalSchema metadata.

        Parameters:
            path : Path or a file-like binary object to save the file. This supports
                local paths as well as remote paths, such as s3:// or hf:// with fsspec.
            partition_cols : Column names by which to partition the dataset.
            chunk_size : The chunk size of results to read and convert to columnar
                data, to avoid running out of memory.
            fs_kwargs : Optional kwargs to pass to the fsspec filesystem, used only for
                write, for fsspec-type URLs, such as s3:// or hf:// when
                provided as the destination path.
        """
        import pyarrow as pa
        import pyarrow.parquet as pq

        from datachain.lib.arrow import DATACHAIN_SIGNAL_SCHEMA_PARQUET_KEY

        fsspec_fs = None

        if isinstance(path, str) and "://" in path:
            from datachain.client.fsspec import Client

            fs_kwargs = {
                **self._query.catalog.client_config,
                **(fs_kwargs or {}),
            }

            client = Client.get_implementation(path)

            if path.startswith("file://"):
                # pyarrow does not handle file:// uris, and needs a direct path instead.
                from urllib.parse import urlparse

                path = urlparse(path).path
                if sys.platform == "win32":
                    path = os.path.normpath(path.lstrip("/"))

            fsspec_fs = client.create_fs(**fs_kwargs)

        _partition_cols = list(partition_cols) if partition_cols else None
        signal_schema_metadata = orjson.dumps(
            self._effective_signals_schema.serialize()
        )

        column_names, column_chunks = self.to_columnar_data_with_names(chunk_size)

        parquet_schema = None
        parquet_writer = None
        first_chunk = True

        for chunk in column_chunks:
            # pyarrow infers the best parquet schema from the python types of
            # the input data.
            table = pa.Table.from_pydict(
                dict(zip(column_names, chunk)),
                schema=parquet_schema,
            )

            # Preserve any existing metadata, and add the DataChain SignalSchema.
            existing_metadata = table.schema.metadata or {}
            merged_metadata = {
                **existing_metadata,
                DATACHAIN_SIGNAL_SCHEMA_PARQUET_KEY: signal_schema_metadata,
            }
            table = table.replace_schema_metadata(merged_metadata)
            parquet_schema = table.schema

            if _partition_cols:
                # Write to a partitioned parquet dataset.
                pq.write_to_dataset(
                    table,
                    root_path=path,
                    partition_cols=_partition_cols,
                    filesystem=fsspec_fs,
                    **kwargs,
                )
            else:
                if first_chunk:
                    # Write to a single parquet file.
                    parquet_writer = pq.ParquetWriter(
                        path, parquet_schema, filesystem=fsspec_fs, **kwargs
                    )
                    first_chunk = False

                assert parquet_writer
                parquet_writer.write_table(table)

        if parquet_writer:
            parquet_writer.close()
Save chain to parquet file with SignalSchema metadata.

        Parameters:
            path : Path or a file-like binary object to save the file. This supports
                local paths as well as remote paths, such as s3:// or hf:// with fsspec.
            partition_cols : Column names by which to partition the dataset.
            chunk_size : The chunk size of results to read and convert to columnar
                data, to avoid running out of memory.
            fs_kwargs : Optional kwargs to pass to the fsspec filesystem, used only for
                write, for fsspec-type URLs, such as s3:// or hf:// when
                provided as the destination path.
        
src/datachain/lib/dc/datachain.py