datasets 5.1.0__tar.gz → 5.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datasets-5.1.0/src/datasets.egg-info → datasets-5.2.0}/PKG-INFO +2 -2
- {datasets-5.1.0 → datasets-5.2.0}/setup.py +2 -2
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/__init__.py +1 -1
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/arrow_dataset.py +36 -10
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/builder.py +11 -3
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/combine.py +2 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/audio.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/features.py +17 -3
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/image.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/mesh.py +7 -4
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/nifti.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/video.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/csv.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/json.py +3 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/iterable_dataset.py +126 -42
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/folder_based_builder/folder_based_builder.py +1 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/genbank/genbank.py +20 -7
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/json/json.py +27 -1
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/meshfolder/meshfolder.py +2 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/niftifolder/niftifolder.py +1 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pandas/pandas.py +8 -6
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/webdataset/webdataset.py +4 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/table.py +5 -1
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/file_utils.py +21 -1
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/json.py +32 -6
- {datasets-5.1.0 → datasets-5.2.0/src/datasets.egg-info}/PKG-INFO +2 -2
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/requires.txt +1 -1
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_arrow_dataset.py +127 -2
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_distributed.py +29 -1
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_file_utils.py +40 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_iterable_dataset.py +130 -50
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_load.py +37 -1
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_search.py +18 -1
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_table.py +10 -0
- {datasets-5.1.0 → datasets-5.2.0}/AUTHORS +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/LICENSE +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/README.md +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/pyproject.toml +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/setup.cfg +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/arrow_reader.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/arrow_writer.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/commands/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/commands/datasets_cli.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/commands/delete_from_hub.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/commands/env.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/commands/test.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/config.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/data_files.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/dataset_dict.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/distributed.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/download/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/download/download_config.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/download/download_manager.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/download/streaming_download_manager.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/exceptions.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/_torchcodec.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/bio_sequence.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/bio_structure.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/pdf.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/features/translation.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/filesystems/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/filesystems/compression.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/fingerprint.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/formatting.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/jax_formatter.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/np_formatter.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/polars_formatter.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/tf_formatter.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/formatting/torch_formatter.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/hub.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/info.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/inspect.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/abc.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/generator.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/parquet.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/spark.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/sql.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/io/text.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/load.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/naming.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/arrow/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/arrow/arrow.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/audiofolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/audiofolder/audiofolder.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/cache/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/cache/cache.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/conll/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/conll/conll.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/csv/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/csv/csv.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/eval/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/eval/eval.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/fasta/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/fasta/fasta.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/fastq/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/fastq/fastq.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/folder_based_builder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/genbank/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/generator/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/generator/generator.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/harbor/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/harbor/harbor.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/hdf5/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/hdf5/hdf5.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/iceberg/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/iceberg/iceberg.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/imagefolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/imagefolder/imagefolder.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/json/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/lance/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/lance/lance.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/meshfolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/mmcif/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/mmcif/mmcif.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/niftifolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pandas/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/parquet/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/parquet/parquet.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pdb/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pdb/pdb.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pdffolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/pdffolder/pdffolder.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/spark/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/spark/spark.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/sql/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/sql/sql.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/text/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/text/text.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/tsfile/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/tsfile/tsfile.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/videofolder/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/videofolder/videofolder.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/vortex/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/vortex/vortex.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/webdataset/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/webdataset/_tenbin.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/xml/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/packaged_modules/xml/xml.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/parallel/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/parallel/parallel.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/search.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/splits.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/streaming.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/_dataset_viewer.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/_dill.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/_filelock.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/deprecation_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/doc_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/experimental.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/extract.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/filelock.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/hub.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/info_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/logging.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/metadata.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/patching.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/py_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/__init__.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/creators.json +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/languages.json +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/multilingualities.json +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/readme_structure.yaml +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/resources/size_categories.json +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/sharding.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/stratify.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/tf_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/tqdm.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/track.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/typing.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets/utils/version.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/SOURCES.txt +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/dependency_links.txt +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/entry_points.txt +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/not-zip-safe +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/src/datasets.egg-info/top_level.txt +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_arrow_reader.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_arrow_writer.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_buckets.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_builder.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_data_files.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_dataset_dict.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_dataset_list.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_download_manager.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_exceptions.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_experimental.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_extract.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_filelock.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_filesystem.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_fingerprint.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_fingerprint_tokenizer_stability.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_formatting.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_hub.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_info.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_info_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_inspect.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_metadata_util.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_offline_util.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_parallel.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_patching.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_py_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_sharding_utils.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_splits.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_streaming_download_manager.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_tqdm.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_upstream_hub.py +0 -0
- {datasets-5.1.0 → datasets-5.2.0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datasets
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: HuggingFace community-driven open-source library of datasets
|
|
5
5
|
Home-page: https://github.com/huggingface/datasets
|
|
6
6
|
Download-URL: https://github.com/huggingface/datasets/tags
|
|
@@ -33,7 +33,7 @@ Requires-Dist: pandas
|
|
|
33
33
|
Requires-Dist: tqdm>=4.66.3
|
|
34
34
|
Requires-Dist: xxhash
|
|
35
35
|
Requires-Dist: multiprocess<0.70.20
|
|
36
|
-
Requires-Dist: fsspec
|
|
36
|
+
Requires-Dist: fsspec<=2026.9.0,>=2023.1.0
|
|
37
37
|
Requires-Dist: huggingface-hub<3.0,>=1.31.0
|
|
38
38
|
Requires-Dist: packaging
|
|
39
39
|
Requires-Dist: pyyaml>=5.1
|
|
@@ -124,7 +124,7 @@ REQUIRED_PKGS = [
|
|
|
124
124
|
"multiprocess<0.70.20", # to align with dill<0.3.9 (see above)
|
|
125
125
|
# to save datasets locally or on any filesystem
|
|
126
126
|
# minimum 2023.1.0 to support protocol=kwargs in fsspec's `open`, `get_fs_token_paths`, etc.: see https://github.com/fsspec/filesystem_spec/pull/1143
|
|
127
|
-
"fsspec
|
|
127
|
+
"fsspec>=2023.1.0,<=2026.9.0",
|
|
128
128
|
# To get datasets from the Datasets Hub on huggingface.co
|
|
129
129
|
# (also provides the HTTP client: `from huggingface_hub.utils import httpx`)
|
|
130
130
|
# minimum 1.31.0 for the `huggingface_hub.utils.httpx` re-export
|
|
@@ -252,7 +252,7 @@ EXTRAS_REQUIRE = {
|
|
|
252
252
|
|
|
253
253
|
setup(
|
|
254
254
|
name="datasets",
|
|
255
|
-
version="5.
|
|
255
|
+
version="5.2.0", # expected format is one of x.y.z.dev0, or x.y.z.rc1 or x.y.z (no to dashes, yes to dots)
|
|
256
256
|
description="HuggingFace community-driven open-source library of datasets",
|
|
257
257
|
long_description=open("README.md", encoding="utf-8").read(),
|
|
258
258
|
long_description_content_type="text/markdown",
|
|
@@ -855,7 +855,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
855
855
|
table = InMemoryTable.from_buffer(buffer)
|
|
856
856
|
|
|
857
857
|
if indices_buffer is not None:
|
|
858
|
-
indices_table = InMemoryTable.from_buffer(
|
|
858
|
+
indices_table = InMemoryTable.from_buffer(indices_buffer)
|
|
859
859
|
else:
|
|
860
860
|
indices_table = None
|
|
861
861
|
|
|
@@ -1830,14 +1830,21 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
1830
1830
|
if self.list_indexes():
|
|
1831
1831
|
raise ValueError("please remove all the indexes using `dataset.drop_index` before saving a dataset")
|
|
1832
1832
|
|
|
1833
|
+
from .arrow_writer import get_writer_batch_size_from_data_size
|
|
1834
|
+
|
|
1835
|
+
dataset_nbytes = self._estimate_nbytes()
|
|
1833
1836
|
if num_shards is None:
|
|
1834
|
-
dataset_nbytes = self._estimate_nbytes()
|
|
1835
1837
|
max_shard_size = convert_file_size_to_int(max_shard_size or config.MAX_SHARD_SIZE)
|
|
1836
1838
|
num_shards = int(dataset_nbytes / max_shard_size) + 1
|
|
1837
1839
|
num_shards = max(num_shards, num_proc or 1)
|
|
1838
1840
|
# if we have only a few large samples, we should only create as many shards as samples
|
|
1839
1841
|
num_shards = min(len(self.data), num_shards)
|
|
1840
1842
|
|
|
1843
|
+
# use smaller batches for big samples (e.g. images) to stay below the 2GB limit of arrow binary arrays
|
|
1844
|
+
writer_batch_size = config.DEFAULT_MAX_BATCH_SIZE
|
|
1845
|
+
if dataset_nbytes > 0:
|
|
1846
|
+
writer_batch_size = min(writer_batch_size, get_writer_batch_size_from_data_size(len(self), dataset_nbytes))
|
|
1847
|
+
|
|
1841
1848
|
fs: fsspec.AbstractFileSystem
|
|
1842
1849
|
fs, _ = url_to_fs(dataset_path, **(storage_options or {}))
|
|
1843
1850
|
|
|
@@ -1890,6 +1897,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
1890
1897
|
"shard": self.shard(num_shards=num_shards, index=shard_idx, contiguous=True),
|
|
1891
1898
|
"fpath": posixpath.join(dataset_path, f"data-{shard_idx:05d}-of-{num_shards:05d}.arrow"),
|
|
1892
1899
|
"storage_options": storage_options,
|
|
1900
|
+
"writer_batch_size": writer_batch_size,
|
|
1893
1901
|
}
|
|
1894
1902
|
for shard_idx in range(num_shards)
|
|
1895
1903
|
)
|
|
@@ -1931,9 +1939,13 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
1931
1939
|
json.dump(sorted_keys_dataset_info, dataset_info_file, indent=2)
|
|
1932
1940
|
|
|
1933
1941
|
@staticmethod
|
|
1934
|
-
def _save_to_disk_single(
|
|
1935
|
-
|
|
1936
|
-
|
|
1942
|
+
def _save_to_disk_single(
|
|
1943
|
+
job_id: int,
|
|
1944
|
+
shard: "Dataset",
|
|
1945
|
+
fpath: str,
|
|
1946
|
+
storage_options: Optional[dict],
|
|
1947
|
+
writer_batch_size: int,
|
|
1948
|
+
):
|
|
1937
1949
|
num_examples_progress_update = 0
|
|
1938
1950
|
writer = ArrowWriter(
|
|
1939
1951
|
features=shard.features,
|
|
@@ -1943,7 +1955,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
1943
1955
|
)
|
|
1944
1956
|
try:
|
|
1945
1957
|
_time = time.time()
|
|
1946
|
-
for pa_table in shard.with_format("arrow").iter(
|
|
1958
|
+
for pa_table in shard.with_format("arrow").iter(writer_batch_size):
|
|
1947
1959
|
writer.write_table(pa_table)
|
|
1948
1960
|
num_examples_progress_update += len(pa_table)
|
|
1949
1961
|
if time.time() > _time + config.PBAR_REFRESH_TIME_INTERVAL:
|
|
@@ -3844,7 +3856,14 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
3844
3856
|
processed_inputs.pop(column)
|
|
3845
3857
|
if check_same_num_examples:
|
|
3846
3858
|
input_num_examples = len(pa_inputs)
|
|
3847
|
-
|
|
3859
|
+
if not isinstance(processed_inputs, Mapping):
|
|
3860
|
+
# pa.Table, pd.DataFrame or pl.DataFrame
|
|
3861
|
+
processed_inputs_num_examples = len(processed_inputs)
|
|
3862
|
+
elif processed_inputs:
|
|
3863
|
+
processed_inputs_num_examples = len(next(iter(processed_inputs.values())))
|
|
3864
|
+
else:
|
|
3865
|
+
# an empty dict doesn't update any column
|
|
3866
|
+
processed_inputs_num_examples = input_num_examples
|
|
3848
3867
|
if input_num_examples != processed_inputs_num_examples:
|
|
3849
3868
|
raise DatasetTransformationNotAllowedError(
|
|
3850
3869
|
"Using `.map` in batched mode on a dataset with attached indexes is allowed only if it doesn't create or remove existing examples. You can first run `.drop_index() to remove your index and then re-add it."
|
|
@@ -4690,7 +4709,10 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
4690
4709
|
'text': 'the gorgeously elaborate continuation of " the lord of the rings " trilogy is so huge that a column of words cannot adequately describe co-writer/director peter jackson\'s expanded vision of j . r . r . tolkien\'s middle-earth .'}]
|
|
4691
4710
|
```
|
|
4692
4711
|
"""
|
|
4693
|
-
|
|
4712
|
+
# Clamp `n` to the dataset length so taking more elements than available
|
|
4713
|
+
# returns the whole dataset instead of raising an IndexError, matching
|
|
4714
|
+
# the behavior of `IterableDataset.take`.
|
|
4715
|
+
return self.select(range(min(n, len(self))))
|
|
4694
4716
|
|
|
4695
4717
|
@transmit_format
|
|
4696
4718
|
@fingerprint_transform(inplace=False, ignore_kwargs=["load_from_cache_file", "indices_cache_file_name"])
|
|
@@ -5722,7 +5744,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
5722
5744
|
k for k, v in self._info.features.items() if require_decoding(v, ignore_decode_attribute=True)
|
|
5723
5745
|
]
|
|
5724
5746
|
|
|
5725
|
-
if decodable_columns:
|
|
5747
|
+
if decodable_columns and len(self) > 0:
|
|
5726
5748
|
# Approximate the space needed to store the bytes from the external files by analyzing the first 1000 examples
|
|
5727
5749
|
extra_nbytes = 0
|
|
5728
5750
|
|
|
@@ -6010,12 +6032,14 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
|
|
|
6010
6032
|
logger.warning(
|
|
6011
6033
|
f"Setting num_proc from {num_jobs} back to 1 for the {split} split to disable multiprocessing as it only contains one shard."
|
|
6012
6034
|
)
|
|
6035
|
+
num_proc = None
|
|
6013
6036
|
num_jobs = 1
|
|
6014
6037
|
elif num_shards < num_jobs:
|
|
6015
6038
|
logger.warning(
|
|
6016
6039
|
f"Setting num_proc from {num_jobs} to {num_shards} for the {split} split as it only contains {num_shards} shards."
|
|
6017
6040
|
)
|
|
6018
6041
|
num_proc = num_shards
|
|
6042
|
+
num_jobs = num_shards
|
|
6019
6043
|
kwargs_iterable = [
|
|
6020
6044
|
{
|
|
6021
6045
|
"self": self.shard(num_shards=num_jobs, index=job_id, contiguous=True),
|
|
@@ -7115,7 +7139,9 @@ def _concatenate_map_style_datasets(
|
|
|
7115
7139
|
if info is None:
|
|
7116
7140
|
info = DatasetInfo.from_merge([dset.info for dset in dsets])
|
|
7117
7141
|
fingerprint = update_fingerprint(
|
|
7118
|
-
"".join(dset._fingerprint for dset in dsets),
|
|
7142
|
+
"".join(dset._fingerprint for dset in dsets),
|
|
7143
|
+
_concatenate_map_style_datasets,
|
|
7144
|
+
{"info": info, "split": split, "axis": axis},
|
|
7119
7145
|
)
|
|
7120
7146
|
|
|
7121
7147
|
# Make final concatenated dataset
|
|
@@ -1175,15 +1175,23 @@ class DatasetBuilder:
|
|
|
1175
1175
|
return datasets
|
|
1176
1176
|
|
|
1177
1177
|
def _as_streaming_dataset_single(
|
|
1178
|
-
self,
|
|
1179
|
-
splits_generator,
|
|
1178
|
+
self, splits_generator, decode_num_threads: Optional[int] = None
|
|
1180
1179
|
) -> IterableDataset:
|
|
1181
1180
|
ex_iterable = self._get_examples_iterable_for_split(splits_generator)
|
|
1182
1181
|
# add auth to be able to access and decode audio/image files from private repositories.
|
|
1183
1182
|
token_per_repo_id = {self.repo_id: self.token} if self.repo_id else {}
|
|
1184
|
-
|
|
1183
|
+
ds = IterableDataset(
|
|
1185
1184
|
ex_iterable, info=self.info, split=splits_generator.name, token_per_repo_id=token_per_repo_id
|
|
1186
1185
|
)
|
|
1186
|
+
# Read and decode media examples (Image/Audio/Video/Mesh/...) in worker threads by default: opening and
|
|
1187
|
+
# reading a remote file costs network round trips rather than CPU time, so streaming remote media data is
|
|
1188
|
+
# latency bound without any overlap. Datasets without decodable features (text, tabular, parquet, ...) and
|
|
1189
|
+
# datasets read from the local disk are returned unchanged.
|
|
1190
|
+
if decode_num_threads is None and hasattr(self.config, "decode_num_threads"):
|
|
1191
|
+
decode_num_threads = self.config.decode_num_threads
|
|
1192
|
+
if self.base_path and self.base_path.startswith("hf://") and decode_num_threads:
|
|
1193
|
+
ds = ds.decode(num_threads=decode_num_threads)
|
|
1194
|
+
return ds
|
|
1187
1195
|
|
|
1188
1196
|
@abc.abstractmethod
|
|
1189
1197
|
def _split_generators(self, dl_manager: Union[DownloadManager, StreamingDownloadManager]):
|
|
@@ -180,6 +180,8 @@ def concatenate_datasets(
|
|
|
180
180
|
|
|
181
181
|
* if axis=0, the resulting dataset's `num_shards` is the sum of each dataset's `num_shards`.
|
|
182
182
|
* if axis=1, the resulting dataset has one (1) shard to not misalign data.
|
|
183
|
+
* if the datasets were split with [`datasets.distributed.split_dataset_by_node`], they must all be split the same way,
|
|
184
|
+
and the resulting dataset keeps that split.
|
|
183
185
|
|
|
184
186
|
Args:
|
|
185
187
|
dsets (`List[datasets.Dataset]` or `List[datasets.IterableDataset]`):
|
|
@@ -188,6 +188,9 @@ class Audio:
|
|
|
188
188
|
if not self.decode:
|
|
189
189
|
raise RuntimeError("Decoding is disabled for this feature. Please use Audio(decode=True) instead.")
|
|
190
190
|
|
|
191
|
+
if not isinstance(value, dict):
|
|
192
|
+
return value # decoding is idempotent: a value that is already an audio decoder is returned as is
|
|
193
|
+
|
|
191
194
|
path, bytes = (value["path"], value["bytes"]) if value["bytes"] is not None else (value["path"], None)
|
|
192
195
|
if path is None and bytes is None:
|
|
193
196
|
raise ValueError(f"An audio sample should have one of 'path' or 'bytes' but both are None in {value}.")
|
|
@@ -1234,7 +1234,15 @@ class ClassLabel:
|
|
|
1234
1234
|
raise ValueError(
|
|
1235
1235
|
f"Class label {min_max['max']} greater than configured num_classes {self.num_classes}"
|
|
1236
1236
|
)
|
|
1237
|
-
elif
|
|
1237
|
+
elif (
|
|
1238
|
+
pa.types.is_string(storage.type)
|
|
1239
|
+
or pa.types.is_large_string(storage.type)
|
|
1240
|
+
or pa.types.is_string_view(storage.type)
|
|
1241
|
+
):
|
|
1242
|
+
# Check the Arrow type rather than the array class: `pa.LargeStringArray` and
|
|
1243
|
+
# `pa.StringViewArray` are not subclasses of `pa.StringArray`, and pandas 3
|
|
1244
|
+
# produces `large_string` for plain string columns, so an isinstance check let
|
|
1245
|
+
# those fall through to an int64 cast of the label names.
|
|
1238
1246
|
storage = pa.array(
|
|
1239
1247
|
[self._strval2int(label) if label is not None else None for label in storage.to_pylist()]
|
|
1240
1248
|
)
|
|
@@ -1974,8 +1982,14 @@ class Features(dict):
|
|
|
1974
1982
|
for column_name, feature in self.items():
|
|
1975
1983
|
self[column_name] = _visit(feature, _check_old_list)
|
|
1976
1984
|
|
|
1977
|
-
__setitem__
|
|
1978
|
-
|
|
1985
|
+
def __setitem__(self, column_name: str, feature: FeatureType):
|
|
1986
|
+
super().__setitem__(column_name, feature)
|
|
1987
|
+
self._column_requires_decoding[column_name] = require_decoding(feature)
|
|
1988
|
+
|
|
1989
|
+
def __delitem__(self, column_name: str):
|
|
1990
|
+
super().__delitem__(column_name)
|
|
1991
|
+
self._column_requires_decoding.pop(column_name, None)
|
|
1992
|
+
|
|
1979
1993
|
update = keep_features_dicts_synced(dict.update)
|
|
1980
1994
|
setdefault = keep_features_dicts_synced(dict.setdefault)
|
|
1981
1995
|
pop = keep_features_dicts_synced(dict.pop)
|
|
@@ -166,6 +166,9 @@ class Image:
|
|
|
166
166
|
if token_per_repo_id is None:
|
|
167
167
|
token_per_repo_id = {}
|
|
168
168
|
|
|
169
|
+
if not isinstance(value, (dict, str)):
|
|
170
|
+
return value # decoding is idempotent: a value that is already an image is returned as is
|
|
171
|
+
|
|
169
172
|
path, bytes_ = value["path"], value["bytes"]
|
|
170
173
|
if bytes_ is None:
|
|
171
174
|
if path is None:
|
|
@@ -41,7 +41,7 @@ class Mesh:
|
|
|
41
41
|
decode (`bool`, defaults to `True`):
|
|
42
42
|
Whether to decode the mesh data. If `False`,
|
|
43
43
|
returns the underlying dictionary in the format `{"path": mesh_path, "bytes": mesh_bytes}`.
|
|
44
|
-
Mesh decoding uses `trimesh` and supports `.glb`, `.ply`, and `.stl` files.
|
|
44
|
+
Mesh decoding uses `trimesh` and supports `.glb`, `.gltf`, `.ply`, and `.stl` files.
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
47
|
decode: bool = True
|
|
@@ -116,6 +116,9 @@ class Mesh:
|
|
|
116
116
|
if token_per_repo_id is None:
|
|
117
117
|
token_per_repo_id = {}
|
|
118
118
|
|
|
119
|
+
if not isinstance(value, (dict, str)):
|
|
120
|
+
return value # decoding is idempotent: a value that is already a mesh is returned as is
|
|
121
|
+
|
|
119
122
|
path, bytes_ = value["path"], value["bytes"]
|
|
120
123
|
if bytes_ is None:
|
|
121
124
|
if path is None:
|
|
@@ -123,7 +126,7 @@ class Mesh:
|
|
|
123
126
|
if is_local_path(path):
|
|
124
127
|
file_type = _infer_mesh_file_type(path)
|
|
125
128
|
if file_type is None:
|
|
126
|
-
raise ValueError("A mesh path should have a .glb, .ply, or .stl extension.")
|
|
129
|
+
raise ValueError("A mesh path should have a .glb, .gltf, .ply, or .stl extension.")
|
|
127
130
|
return trimesh.load(path, file_type=file_type)
|
|
128
131
|
source_url = path.split("::")[-1]
|
|
129
132
|
pattern = (
|
|
@@ -138,7 +141,7 @@ class Mesh:
|
|
|
138
141
|
file_type = _infer_mesh_file_type(path)
|
|
139
142
|
if file_type is None:
|
|
140
143
|
raise ValueError(
|
|
141
|
-
"Decoding mesh bytes requires a 'path' value with a .glb, .ply, or .stl extension "
|
|
144
|
+
"Decoding mesh bytes requires a 'path' value with a .glb, .gltf, .ply, or .stl extension "
|
|
142
145
|
"to infer the mesh file type."
|
|
143
146
|
)
|
|
144
147
|
return trimesh.load(BytesIO(bytes_), file_type=file_type)
|
|
@@ -276,7 +279,7 @@ class Mesh:
|
|
|
276
279
|
|
|
277
280
|
|
|
278
281
|
def _infer_mesh_file_type(path: Optional[str]) -> Optional[str]:
|
|
279
|
-
supported_file_types = {"glb", "ply", "stl"}
|
|
282
|
+
supported_file_types = {"glb", "gltf", "ply", "stl"}
|
|
280
283
|
if path is None:
|
|
281
284
|
return None
|
|
282
285
|
path_without_archive = path.split("::", 1)[0]
|
|
@@ -174,6 +174,9 @@ class Nifti:
|
|
|
174
174
|
if token_per_repo_id is None:
|
|
175
175
|
token_per_repo_id = {}
|
|
176
176
|
|
|
177
|
+
if not isinstance(value, (dict, str)):
|
|
178
|
+
return value # decoding is idempotent: a value that is already a NIfTI image is returned as is
|
|
179
|
+
|
|
177
180
|
path, bytes_ = value["path"], value["bytes"]
|
|
178
181
|
if bytes_ is None:
|
|
179
182
|
if path is None:
|
|
@@ -184,6 +184,9 @@ class Video:
|
|
|
184
184
|
if token_per_repo_id is None:
|
|
185
185
|
token_per_repo_id = {}
|
|
186
186
|
|
|
187
|
+
if not isinstance(value, (dict, str)):
|
|
188
|
+
return value # decoding is idempotent: a value that is already a video decoder is returned as is
|
|
189
|
+
|
|
187
190
|
if isinstance(value, str):
|
|
188
191
|
path, bytes_ = value, None
|
|
189
192
|
else:
|
|
@@ -115,6 +115,9 @@ class CsvDatasetWriter:
|
|
|
115
115
|
|
|
116
116
|
Caller is responsible for opening and closing the handle.
|
|
117
117
|
"""
|
|
118
|
+
if len(self.dataset) == 0:
|
|
119
|
+
return file_obj.write(self._batch_csv((0, header, index, to_csv_kwargs)))
|
|
120
|
+
|
|
118
121
|
written = 0
|
|
119
122
|
|
|
120
123
|
if self.num_proc is None or self.num_proc == 1:
|
|
@@ -163,6 +163,9 @@ class JsonDatasetWriter:
|
|
|
163
163
|
|
|
164
164
|
Caller is responsible for opening and closing the handle.
|
|
165
165
|
"""
|
|
166
|
+
if len(self.dataset) == 0 and not lines:
|
|
167
|
+
return file_obj.write(self._batch_json((0, orient, lines, to_json_kwargs)))
|
|
168
|
+
|
|
166
169
|
written = 0
|
|
167
170
|
|
|
168
171
|
if self.num_proc is None or self.num_proc == 1:
|
|
@@ -3,10 +3,10 @@ import concurrent.futures
|
|
|
3
3
|
import contextlib
|
|
4
4
|
import inspect
|
|
5
5
|
import itertools
|
|
6
|
-
import multiprocessing.pool
|
|
7
6
|
import re
|
|
8
7
|
import sys
|
|
9
8
|
import tempfile
|
|
9
|
+
import threading
|
|
10
10
|
import time
|
|
11
11
|
from collections import Counter
|
|
12
12
|
from collections.abc import Iterable, Iterator
|
|
@@ -1407,6 +1407,10 @@ class MappedExamplesIterable(_BaseExamplesIterable):
|
|
|
1407
1407
|
max_num_running_async_map_functions_in_parallel or config.MAX_NUM_RUNNING_ASYNC_MAP_FUNCTIONS_IN_PARALLEL
|
|
1408
1408
|
)
|
|
1409
1409
|
self.is_batch_accumulate_arrow_table_function = is_batch_accumulate_arrow_table_function
|
|
1410
|
+
# Set by IterableDataset.decode when it enables threaded decoding: since examples must be decoded exactly
|
|
1411
|
+
# once, a later `.decode()` call reconfigures decoding from `decoding_dataset` (the dataset `.decode()` was
|
|
1412
|
+
# called on) rather than stacking a second decoding step on top of this one.
|
|
1413
|
+
self.decoding_pool: Optional[_LazyThreadPoolExecutor] = None
|
|
1410
1414
|
# sanity checks
|
|
1411
1415
|
if formatting and formatting.is_table:
|
|
1412
1416
|
# batch_size should match for iter_arrow
|
|
@@ -1604,16 +1608,12 @@ class MappedExamplesIterable(_BaseExamplesIterable):
|
|
|
1604
1608
|
for i, key_example in inputs_iterator:
|
|
1605
1609
|
indices.append(i)
|
|
1606
1610
|
tasks.append(loop.create_task(async_apply_function(key_example, i)))
|
|
1607
|
-
# keep the total active tasks under a certain number
|
|
1611
|
+
# keep the total active tasks under a certain number, waiting for the oldest task to complete.
|
|
1612
|
+
# Polling the whole task list with asyncio.wait can't be used for that: it returns as soon as any
|
|
1613
|
+
# task in the list is done, so as soon as one example is slower than the examples created after it
|
|
1614
|
+
# (e.g. a large remote file), every wait returns instantly and this spins at 100% CPU, taking the
|
|
1615
|
+
# GIL away from the worker threads that were doing the actual work.
|
|
1608
1616
|
if len(tasks) >= self.max_num_running_async_map_functions_in_parallel:
|
|
1609
|
-
done, pending = loop.run_until_complete(
|
|
1610
|
-
asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
|
1611
|
-
)
|
|
1612
|
-
while tasks and len(pending) >= self.max_num_running_async_map_functions_in_parallel:
|
|
1613
|
-
done, pending = loop.run_until_complete(
|
|
1614
|
-
asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
|
1615
|
-
)
|
|
1616
|
-
if len(tasks) >= 10 * self.max_num_running_async_map_functions_in_parallel:
|
|
1617
1617
|
loop.run_until_complete(tasks[0])
|
|
1618
1618
|
# yield finished tasks
|
|
1619
1619
|
while tasks and tasks[0].done():
|
|
@@ -4517,7 +4517,7 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4517
4517
|
token_per_repo_id=self._token_per_repo_id,
|
|
4518
4518
|
)
|
|
4519
4519
|
|
|
4520
|
-
def decode(self, enable: bool = True, num_threads: int =
|
|
4520
|
+
def decode(self, enable: bool = True, num_threads: Optional[int] = None) -> "IterableDataset":
|
|
4521
4521
|
"""
|
|
4522
4522
|
Enable or disable the dataset features decoding for audio, image, video.
|
|
4523
4523
|
|
|
@@ -4527,8 +4527,13 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4527
4527
|
* image -> PIL.Image
|
|
4528
4528
|
* video -> torchcodec.decoders.VideoDecoder
|
|
4529
4529
|
|
|
4530
|
-
|
|
4531
|
-
|
|
4530
|
+
Multithreading can be enabled with `num_threads`: every media file is then read and decoded in a worker
|
|
4531
|
+
thread, so that the network round trips of consecutive examples overlap. This is especially useful to speed
|
|
4532
|
+
up remote data streaming, and [`load_dataset`] already enables it by default when streaming a remote dataset
|
|
4533
|
+
that has decodable features (see `HF_DATASETS_DECODE_NUM_THREADS`). Datasets read from the local disk are
|
|
4534
|
+
streamed with `num_threads=0`, since multithreading can be slower than decoding in the main thread for local
|
|
4535
|
+
data on fast disks. Since examples are decoded in advance, every thread in flight can keep one example in
|
|
4536
|
+
memory: lower `num_threads` to use less memory.
|
|
4532
4537
|
|
|
4533
4538
|
Disabling decoding is useful if you want to iterate on the paths or bytes of the media files
|
|
4534
4539
|
without actually decoding their content. To disable decoding you can use `.decode(False)`, which
|
|
@@ -4538,8 +4543,10 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4538
4543
|
Args:
|
|
4539
4544
|
enable (`bool`, defaults to `True`):
|
|
4540
4545
|
Enable or disable features decoding.
|
|
4541
|
-
num_threads (`int`, defaults to `
|
|
4542
|
-
Enable multithreading for features decoding.
|
|
4546
|
+
num_threads (`int`, *optional*, defaults to `None`):
|
|
4547
|
+
Enable multithreading for features decoding. Note that [`load_dataset`] already uses a few threads
|
|
4548
|
+
by default when streaming a dataset on HF with decodable features.
|
|
4549
|
+
By default, `num_threads` is set to 32 if at least one feature require decoding, and 0 otherwise.
|
|
4543
4550
|
|
|
4544
4551
|
Returns:
|
|
4545
4552
|
`IterableDataset`: A copy of the dataset with casted features.
|
|
@@ -4575,9 +4582,9 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4575
4582
|
>>> from datasets import load_dataset
|
|
4576
4583
|
>>> from tqdm import tqdm
|
|
4577
4584
|
>>> ds = load_dataset("sshh12/planet-textures", split="train", streaming=True)
|
|
4578
|
-
>>>
|
|
4579
|
-
>>> ds = ds.decode(num_threads=
|
|
4580
|
-
>>> for _ in tqdm(ds): #
|
|
4585
|
+
>>> # already threaded by default with 32 threads, but more threads can help going even faster
|
|
4586
|
+
>>> ds = ds.decode(num_threads=64)
|
|
4587
|
+
>>> for _ in tqdm(ds): # 2 times faster !
|
|
4581
4588
|
... ...
|
|
4582
4589
|
```
|
|
4583
4590
|
"""
|
|
@@ -4586,28 +4593,36 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4586
4593
|
"Features decoding is only available for datasets with known features, but features are Unknown. "
|
|
4587
4594
|
"Please set the datasets features with `ds = ds.cast(features)`."
|
|
4588
4595
|
)
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
def set_decoding(decode: bool, feature):
|
|
4592
|
-
if hasattr(feature, "decode"):
|
|
4593
|
-
feature.decode = decode
|
|
4596
|
+
if num_threads is None:
|
|
4597
|
+
num_threads = 32 if require_decoding(self.features) else 0
|
|
4594
4598
|
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4599
|
+
ds = self
|
|
4600
|
+
# If decoding is already configured, start again from the dataset it was configured on: examples must be
|
|
4601
|
+
# decoded exactly once, so `.decode()` replaces the previous decoding step instead of adding a new one.
|
|
4602
|
+
if isinstance(ds._ex_iterable, MappedExamplesIterable) and ds._ex_iterable.decoding_pool is not None:
|
|
4603
|
+
# The original dataset may still have active iterators using its decoding pool.
|
|
4604
|
+
ds = IterableDataset(
|
|
4605
|
+
ds._ex_iterable.ex_iterable,
|
|
4606
|
+
info=ds.info,
|
|
4607
|
+
split=ds.split,
|
|
4608
|
+
formatting=ds._formatting,
|
|
4609
|
+
distributed=ds._distributed,
|
|
4610
|
+
token_per_repo_id=ds._token_per_repo_id,
|
|
4611
|
+
)
|
|
4598
4612
|
|
|
4599
|
-
|
|
4600
|
-
|
|
4613
|
+
if enable and num_threads:
|
|
4614
|
+
disabled_decoding_features = _features_with_decoding(self.features, False)
|
|
4615
|
+
enabled_decoding_features = _features_with_decoding(self.features, True)
|
|
4601
4616
|
ds = ds.cast(disabled_decoding_features)
|
|
4602
|
-
pool =
|
|
4603
|
-
|
|
4617
|
+
pool = _LazyThreadPoolExecutor(num_threads)
|
|
4618
|
+
decode_example = partial(enabled_decoding_features.decode_example, token_per_repo_id=ds._token_per_repo_id)
|
|
4619
|
+
func = partial(_apply_async, pool, decode_example)
|
|
4604
4620
|
ds = ds.map(func, features=enabled_decoding_features)
|
|
4605
4621
|
assert isinstance(ds._ex_iterable, MappedExamplesIterable)
|
|
4622
|
+
ds._ex_iterable.decoding_pool = pool
|
|
4606
4623
|
ds._ex_iterable.max_num_running_async_map_functions_in_parallel = 2 * num_threads
|
|
4607
4624
|
else:
|
|
4608
|
-
|
|
4609
|
-
_visit(features, partial(set_decoding, enable))
|
|
4610
|
-
ds = ds.cast(features)
|
|
4625
|
+
ds = ds.cast(_features_with_decoding(ds.features, enable))
|
|
4611
4626
|
return ds
|
|
4612
4627
|
|
|
4613
4628
|
def _step(self, step: int, offset: int) -> "IterableDataset":
|
|
@@ -4663,10 +4678,20 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4663
4678
|
Whether to drop the last incomplete batch.
|
|
4664
4679
|
|
|
4665
4680
|
Example:
|
|
4681
|
+
|
|
4682
|
+
Fixed batch size:
|
|
4683
|
+
|
|
4666
4684
|
```py
|
|
4667
|
-
>>> ds = load_dataset("some_dataset", streaming=True)
|
|
4685
|
+
>>> ds = load_dataset("some_dataset", streaming=True, split="train")
|
|
4668
4686
|
>>> batched_ds = ds.batch(batch_size=32)
|
|
4669
4687
|
```
|
|
4688
|
+
|
|
4689
|
+
Batches of successive samples with identical value for "my_column":
|
|
4690
|
+
|
|
4691
|
+
```py
|
|
4692
|
+
>>> ds = load_dataset("some_dataset", streaming=True, split="train")
|
|
4693
|
+
>>> batched_ds = ds.batch(by_column="my_column")
|
|
4694
|
+
```
|
|
4670
4695
|
"""
|
|
4671
4696
|
if batch_size is None and by_column is None:
|
|
4672
4697
|
raise ValueError("IterableDataset.batch() misses `batch_size` or `by_column` argument.")
|
|
@@ -4682,7 +4707,7 @@ class IterableDataset(DatasetInfoMixin):
|
|
|
4682
4707
|
partial(_batch_accumulate_arrow_table_by_columns, columns=columns),
|
|
4683
4708
|
with_indices=True,
|
|
4684
4709
|
batched=True,
|
|
4685
|
-
batch_size=batch_size,
|
|
4710
|
+
batch_size=batch_size or config.DEFAULT_MAX_BATCH_SIZE,
|
|
4686
4711
|
drop_last_batch=drop_last_batch,
|
|
4687
4712
|
features=features,
|
|
4688
4713
|
is_batch_accumulate_arrow_table_function=True,
|
|
@@ -5532,6 +5557,11 @@ def _concatenate_iterable_datasets(
|
|
|
5532
5557
|
_check_if_features_can_be_aligned([dset.features for dset in dsets])
|
|
5533
5558
|
else:
|
|
5534
5559
|
_check_column_names([col_name for dset in dsets for col_name in dset.features])
|
|
5560
|
+
for i, dset in enumerate(dsets):
|
|
5561
|
+
if dsets[0]._distributed != dset._distributed:
|
|
5562
|
+
raise ValueError(
|
|
5563
|
+
f"Datasets should be identically split_by_node before concatenating, but got {dsets[0]._distributed}!={dset._distributed} at index 0 and {i}"
|
|
5564
|
+
)
|
|
5535
5565
|
|
|
5536
5566
|
# Check format is consistent; if so, will set format for concatenated dataset
|
|
5537
5567
|
if all(dset._formatting is None for dset in dsets):
|
|
@@ -5586,6 +5616,7 @@ def _concatenate_iterable_datasets(
|
|
|
5586
5616
|
split=split,
|
|
5587
5617
|
token_per_repo_id=token_per_repo_id,
|
|
5588
5618
|
formatting=formatting,
|
|
5619
|
+
distributed=dsets[0]._distributed,
|
|
5589
5620
|
)
|
|
5590
5621
|
|
|
5591
5622
|
|
|
@@ -5729,13 +5760,66 @@ def _split_by_node_iterable_dataset(
|
|
|
5729
5760
|
)
|
|
5730
5761
|
|
|
5731
5762
|
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5763
|
+
def _features_with_decoding(features: Features, decode: bool) -> Features:
|
|
5764
|
+
"""Return a copy of `features` where media features (Image/Audio/Video/Mesh/...) are set to decode or not."""
|
|
5765
|
+
|
|
5766
|
+
def _set_decode_flag(feature):
|
|
5767
|
+
if hasattr(feature, "decode"):
|
|
5768
|
+
feature.decode = decode
|
|
5769
|
+
|
|
5770
|
+
features = features.copy()
|
|
5771
|
+
_visit(features, _set_decode_flag)
|
|
5772
|
+
# Features caches which columns require decoding: re-assign every column to refresh it after the flags change
|
|
5773
|
+
for column_name, feature in list(features.items()):
|
|
5774
|
+
features[column_name] = feature
|
|
5775
|
+
return features
|
|
5776
|
+
|
|
5777
|
+
|
|
5778
|
+
class _LazyThreadPoolExecutor:
|
|
5779
|
+
"""A `concurrent.futures.ThreadPoolExecutor` that is created on first use instead of upfront.
|
|
5780
|
+
|
|
5781
|
+
Threaded decoding holds one of these in the dataset, and datasets get pickled all the time (to send them to
|
|
5782
|
+
`to_torch(num_workers=...)` worker processes for example). Creating the pool when examples are actually read
|
|
5783
|
+
keeps the dataset picklable: every process that iterates it creates its own pool.
|
|
5784
|
+
"""
|
|
5785
|
+
|
|
5786
|
+
def __init__(self, max_workers: int):
|
|
5787
|
+
self.max_workers = max_workers
|
|
5788
|
+
self._pool: Optional[concurrent.futures.ThreadPoolExecutor] = None
|
|
5789
|
+
self._lock = threading.Lock()
|
|
5790
|
+
|
|
5791
|
+
def submit(self, fn, *args, **kwargs):
|
|
5792
|
+
with self._lock:
|
|
5793
|
+
if self._pool is None:
|
|
5794
|
+
self._pool = concurrent.futures.ThreadPoolExecutor(
|
|
5795
|
+
self.max_workers, thread_name_prefix="datasets_decode"
|
|
5796
|
+
)
|
|
5797
|
+
return self._pool.submit(fn, *args, **kwargs)
|
|
5798
|
+
|
|
5799
|
+
def shutdown(self, wait: bool = True, *, cancel_futures: bool = False):
|
|
5800
|
+
with self._lock:
|
|
5801
|
+
pool, self._pool = self._pool, None
|
|
5802
|
+
if pool is not None:
|
|
5803
|
+
pool.shutdown(wait=wait, cancel_futures=cancel_futures)
|
|
5804
|
+
|
|
5805
|
+
def __getstate__(self):
|
|
5806
|
+
return {"max_workers": self.max_workers}
|
|
5807
|
+
|
|
5808
|
+
def __setstate__(self, state):
|
|
5809
|
+
self.max_workers = state["max_workers"]
|
|
5810
|
+
self._pool = None
|
|
5811
|
+
self._lock = threading.Lock()
|
|
5812
|
+
|
|
5813
|
+
|
|
5814
|
+
async def _apply_async(pool: "_LazyThreadPoolExecutor", func, x):
|
|
5815
|
+
"""Run `func(x)` in a worker thread and await its result without blocking the event loop.
|
|
5816
|
+
|
|
5817
|
+
The worker future is wrapped rather than polled in a `while not future.ready(): await asyncio.sleep(0)` loop:
|
|
5818
|
+
spinning wakes up the event loop thousands of times per second, which burns CPU and starves the worker threads
|
|
5819
|
+
that do the actual work (mostly network reads), making threaded decoding slower than plain sequential decoding.
|
|
5820
|
+
"""
|
|
5821
|
+
|
|
5822
|
+
return await asyncio.wrap_future(pool.submit(func, x))
|
|
5739
5823
|
|
|
5740
5824
|
|
|
5741
5825
|
def _batch_fn(unbatched):
|
|
@@ -34,6 +34,7 @@ class FolderBasedBuilderConfig(datasets.BuilderConfig):
|
|
|
34
34
|
drop_metadata: bool = None
|
|
35
35
|
metadata_filenames: list[str] = None
|
|
36
36
|
filters: Optional[Union[ds.Expression, list[tuple], list[list[tuple]]]] = None
|
|
37
|
+
decode_num_threads: int = 32
|
|
37
38
|
|
|
38
39
|
def __post_init__(self):
|
|
39
40
|
super().__post_init__()
|