datasets 4.6.0__tar.gz → 4.7.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.
Files changed (185) hide show
  1. {datasets-4.6.0/src/datasets.egg-info → datasets-4.7.0}/PKG-INFO +2 -2
  2. {datasets-4.6.0 → datasets-4.7.0}/README.md +1 -1
  3. {datasets-4.6.0 → datasets-4.7.0}/setup.py +1 -1
  4. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/__init__.py +1 -1
  5. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/arrow_dataset.py +240 -3
  6. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/arrow_writer.py +92 -7
  7. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/dataset_dict.py +12 -1
  8. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/__init__.py +2 -1
  9. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/features.py +113 -4
  10. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/iterable_dataset.py +16 -14
  11. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/__init__.py +1 -1
  12. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/json/json.py +91 -30
  13. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/_dill.py +40 -3
  14. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/extract.py +119 -7
  15. datasets-4.7.0/src/datasets/utils/json.py +119 -0
  16. {datasets-4.6.0 → datasets-4.7.0/src/datasets.egg-info}/PKG-INFO +2 -2
  17. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/SOURCES.txt +2 -0
  18. {datasets-4.6.0 → datasets-4.7.0}/tests/test_arrow_dataset.py +58 -0
  19. datasets-4.7.0/tests/test_fingerprint_tokenizer_stability.py +45 -0
  20. {datasets-4.6.0 → datasets-4.7.0}/tests/test_iterable_dataset.py +28 -0
  21. {datasets-4.6.0 → datasets-4.7.0}/AUTHORS +0 -0
  22. {datasets-4.6.0 → datasets-4.7.0}/LICENSE +0 -0
  23. {datasets-4.6.0 → datasets-4.7.0}/pyproject.toml +0 -0
  24. {datasets-4.6.0 → datasets-4.7.0}/setup.cfg +0 -0
  25. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/arrow_reader.py +0 -0
  26. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/builder.py +0 -0
  27. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/combine.py +0 -0
  28. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/commands/__init__.py +0 -0
  29. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/commands/datasets_cli.py +0 -0
  30. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/commands/delete_from_hub.py +0 -0
  31. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/commands/env.py +0 -0
  32. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/commands/test.py +0 -0
  33. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/config.py +0 -0
  34. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/data_files.py +0 -0
  35. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/distributed.py +0 -0
  36. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/download/__init__.py +0 -0
  37. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/download/download_config.py +0 -0
  38. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/download/download_manager.py +0 -0
  39. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/download/streaming_download_manager.py +0 -0
  40. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/exceptions.py +0 -0
  41. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/_torchcodec.py +0 -0
  42. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/audio.py +0 -0
  43. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/image.py +0 -0
  44. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/nifti.py +0 -0
  45. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/pdf.py +0 -0
  46. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/translation.py +0 -0
  47. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/features/video.py +0 -0
  48. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/filesystems/__init__.py +0 -0
  49. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/filesystems/compression.py +0 -0
  50. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/fingerprint.py +0 -0
  51. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/__init__.py +0 -0
  52. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/formatting.py +0 -0
  53. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/jax_formatter.py +0 -0
  54. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/np_formatter.py +0 -0
  55. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/polars_formatter.py +0 -0
  56. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/tf_formatter.py +0 -0
  57. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/formatting/torch_formatter.py +0 -0
  58. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/hub.py +0 -0
  59. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/info.py +0 -0
  60. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/inspect.py +0 -0
  61. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/__init__.py +0 -0
  62. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/abc.py +0 -0
  63. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/csv.py +0 -0
  64. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/generator.py +0 -0
  65. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/json.py +0 -0
  66. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/parquet.py +0 -0
  67. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/spark.py +0 -0
  68. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/sql.py +0 -0
  69. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/io/text.py +0 -0
  70. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/load.py +0 -0
  71. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/naming.py +0 -0
  72. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/arrow/__init__.py +0 -0
  73. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/arrow/arrow.py +0 -0
  74. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/audiofolder/__init__.py +0 -0
  75. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/audiofolder/audiofolder.py +0 -0
  76. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/cache/__init__.py +0 -0
  77. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/cache/cache.py +0 -0
  78. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/csv/__init__.py +0 -0
  79. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/csv/csv.py +0 -0
  80. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/eval/__init__.py +0 -0
  81. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/eval/eval.py +0 -0
  82. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/folder_based_builder/__init__.py +0 -0
  83. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/folder_based_builder/folder_based_builder.py +0 -0
  84. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/generator/__init__.py +0 -0
  85. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/generator/generator.py +0 -0
  86. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/hdf5/__init__.py +0 -0
  87. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/hdf5/hdf5.py +0 -0
  88. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/imagefolder/__init__.py +0 -0
  89. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/imagefolder/imagefolder.py +0 -0
  90. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/json/__init__.py +0 -0
  91. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/lance/__init__.py +0 -0
  92. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/lance/lance.py +0 -0
  93. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/niftifolder/__init__.py +0 -0
  94. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/niftifolder/niftifolder.py +0 -0
  95. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/pandas/__init__.py +0 -0
  96. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/pandas/pandas.py +0 -0
  97. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/parquet/__init__.py +0 -0
  98. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/parquet/parquet.py +0 -0
  99. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/pdffolder/__init__.py +0 -0
  100. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/pdffolder/pdffolder.py +0 -0
  101. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/spark/__init__.py +0 -0
  102. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/spark/spark.py +0 -0
  103. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/sql/__init__.py +0 -0
  104. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/sql/sql.py +0 -0
  105. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/text/__init__.py +0 -0
  106. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/text/text.py +0 -0
  107. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/videofolder/__init__.py +0 -0
  108. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/videofolder/videofolder.py +0 -0
  109. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/webdataset/__init__.py +0 -0
  110. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/webdataset/_tenbin.py +0 -0
  111. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/webdataset/webdataset.py +0 -0
  112. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/xml/__init__.py +0 -0
  113. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/packaged_modules/xml/xml.py +0 -0
  114. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/parallel/__init__.py +0 -0
  115. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/parallel/parallel.py +0 -0
  116. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/search.py +0 -0
  117. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/splits.py +0 -0
  118. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/streaming.py +0 -0
  119. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/table.py +0 -0
  120. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/__init__.py +0 -0
  121. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/_dataset_viewer.py +0 -0
  122. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/_filelock.py +0 -0
  123. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/deprecation_utils.py +0 -0
  124. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/doc_utils.py +0 -0
  125. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/experimental.py +0 -0
  126. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/file_utils.py +0 -0
  127. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/filelock.py +0 -0
  128. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/hub.py +0 -0
  129. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/info_utils.py +0 -0
  130. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/logging.py +0 -0
  131. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/metadata.py +0 -0
  132. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/patching.py +0 -0
  133. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/py_utils.py +0 -0
  134. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/__init__.py +0 -0
  135. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/creators.json +0 -0
  136. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/languages.json +0 -0
  137. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/multilingualities.json +0 -0
  138. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/readme_structure.yaml +0 -0
  139. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/resources/size_categories.json +0 -0
  140. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/sharding.py +0 -0
  141. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/stratify.py +0 -0
  142. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/tf_utils.py +0 -0
  143. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/tqdm.py +0 -0
  144. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/track.py +0 -0
  145. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/typing.py +0 -0
  146. {datasets-4.6.0 → datasets-4.7.0}/src/datasets/utils/version.py +0 -0
  147. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/dependency_links.txt +0 -0
  148. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/entry_points.txt +0 -0
  149. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/not-zip-safe +0 -0
  150. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/requires.txt +0 -0
  151. {datasets-4.6.0 → datasets-4.7.0}/src/datasets.egg-info/top_level.txt +0 -0
  152. {datasets-4.6.0 → datasets-4.7.0}/tests/test_arrow_reader.py +0 -0
  153. {datasets-4.6.0 → datasets-4.7.0}/tests/test_arrow_writer.py +0 -0
  154. {datasets-4.6.0 → datasets-4.7.0}/tests/test_builder.py +0 -0
  155. {datasets-4.6.0 → datasets-4.7.0}/tests/test_data_files.py +0 -0
  156. {datasets-4.6.0 → datasets-4.7.0}/tests/test_dataset_dict.py +0 -0
  157. {datasets-4.6.0 → datasets-4.7.0}/tests/test_dataset_list.py +0 -0
  158. {datasets-4.6.0 → datasets-4.7.0}/tests/test_distributed.py +0 -0
  159. {datasets-4.6.0 → datasets-4.7.0}/tests/test_download_manager.py +0 -0
  160. {datasets-4.6.0 → datasets-4.7.0}/tests/test_exceptions.py +0 -0
  161. {datasets-4.6.0 → datasets-4.7.0}/tests/test_experimental.py +0 -0
  162. {datasets-4.6.0 → datasets-4.7.0}/tests/test_extract.py +0 -0
  163. {datasets-4.6.0 → datasets-4.7.0}/tests/test_file_utils.py +0 -0
  164. {datasets-4.6.0 → datasets-4.7.0}/tests/test_filelock.py +0 -0
  165. {datasets-4.6.0 → datasets-4.7.0}/tests/test_filesystem.py +0 -0
  166. {datasets-4.6.0 → datasets-4.7.0}/tests/test_fingerprint.py +0 -0
  167. {datasets-4.6.0 → datasets-4.7.0}/tests/test_formatting.py +0 -0
  168. {datasets-4.6.0 → datasets-4.7.0}/tests/test_hub.py +0 -0
  169. {datasets-4.6.0 → datasets-4.7.0}/tests/test_info.py +0 -0
  170. {datasets-4.6.0 → datasets-4.7.0}/tests/test_info_utils.py +0 -0
  171. {datasets-4.6.0 → datasets-4.7.0}/tests/test_inspect.py +0 -0
  172. {datasets-4.6.0 → datasets-4.7.0}/tests/test_load.py +0 -0
  173. {datasets-4.6.0 → datasets-4.7.0}/tests/test_metadata_util.py +0 -0
  174. {datasets-4.6.0 → datasets-4.7.0}/tests/test_offline_util.py +0 -0
  175. {datasets-4.6.0 → datasets-4.7.0}/tests/test_parallel.py +0 -0
  176. {datasets-4.6.0 → datasets-4.7.0}/tests/test_patching.py +0 -0
  177. {datasets-4.6.0 → datasets-4.7.0}/tests/test_py_utils.py +0 -0
  178. {datasets-4.6.0 → datasets-4.7.0}/tests/test_search.py +0 -0
  179. {datasets-4.6.0 → datasets-4.7.0}/tests/test_sharding_utils.py +0 -0
  180. {datasets-4.6.0 → datasets-4.7.0}/tests/test_splits.py +0 -0
  181. {datasets-4.6.0 → datasets-4.7.0}/tests/test_streaming_download_manager.py +0 -0
  182. {datasets-4.6.0 → datasets-4.7.0}/tests/test_table.py +0 -0
  183. {datasets-4.6.0 → datasets-4.7.0}/tests/test_tqdm.py +0 -0
  184. {datasets-4.6.0 → datasets-4.7.0}/tests/test_upstream_hub.py +0 -0
  185. {datasets-4.6.0 → datasets-4.7.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: datasets
3
- Version: 4.6.0
3
+ Version: 4.7.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
@@ -272,7 +272,7 @@ from datasets import load_dataset
272
272
 
273
273
  # Print all the available datasets
274
274
  from huggingface_hub import list_datasets
275
- print([dataset.id for dataset in list_datasets()])
275
+ print([dataset.id for dataset in list_datasets(limit=20)])
276
276
 
277
277
  # Load a dataset and print the first example in the training set
278
278
  squad_dataset = load_dataset('rajpurkar/squad')
@@ -84,7 +84,7 @@ from datasets import load_dataset
84
84
 
85
85
  # Print all the available datasets
86
86
  from huggingface_hub import list_datasets
87
- print([dataset.id for dataset in list_datasets()])
87
+ print([dataset.id for dataset in list_datasets(limit=20)])
88
88
 
89
89
  # Load a dataset and print the first example in the training set
90
90
  squad_dataset = load_dataset('rajpurkar/squad')
@@ -233,7 +233,7 @@ EXTRAS_REQUIRE = {
233
233
 
234
234
  setup(
235
235
  name="datasets",
236
- version="4.6.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)
236
+ version="4.7.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)
237
237
  description="HuggingFace community-driven open-source library of datasets",
238
238
  long_description=open("README.md", encoding="utf-8").read(),
239
239
  long_description_content_type="text/markdown",
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "4.6.0"
15
+ __version__ = "4.7.0"
16
16
 
17
17
  from .arrow_dataset import Column, Dataset
18
18
  from .arrow_reader import ReadInstruction
@@ -981,6 +981,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
981
981
  features: Optional[Features] = None,
982
982
  info: Optional[DatasetInfo] = None,
983
983
  split: Optional[NamedSplit] = None,
984
+ on_mixed_types: Optional[Literal["use_json"]] = None,
984
985
  ) -> "Dataset":
985
986
  """
986
987
  Convert `dict` to a `pyarrow.Table` to create a [`Dataset`].
@@ -1000,9 +1001,109 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
1000
1001
  Dataset information, like description, citation, etc.
1001
1002
  split (`NamedSplit`, *optional*):
1002
1003
  Name of the dataset split.
1004
+ on_mixed_types (`Literal["use_json"]`, *optional*, defaults to `None`):
1005
+ If "use_json", use the Json() type for mixed-types fields,
1006
+ i.e. unstructured fields that contain data without a predefined schema.
1007
+ In this case, a field with mixed type is set to Json().
1008
+
1009
+ This allow loading lists with a mix of strings/integers/floats
1010
+ for example, or dictionaries with arbitrary value types.
1011
+
1012
+ <Added version="4.7.0"/>
1003
1013
 
1004
1014
  Returns:
1005
1015
  [`Dataset`]
1016
+
1017
+ Examples:
1018
+
1019
+ Get a Dataset from a dictionary containing one list per column:
1020
+
1021
+ ```py
1022
+ >>> ds = Dataset.from_dict({"text": ["hello there !", "general kenobi !"]})
1023
+ ```
1024
+
1025
+ Pass features to set the column types, e.g. for an image dataset:
1026
+
1027
+ ```py
1028
+ >>> features = Features({"image": Image()})
1029
+ >>> ds = Dataset.from_dict({"image": ["path/to/image.png"]}, features=features)
1030
+ ```
1031
+
1032
+ Datasets are based on Arrow which is a columnar format, and therefore they expect every example to have the same
1033
+ type and subtypes, and dictionaries to have the same keys and values types.
1034
+ Loading a dataset errors out when fields have mismatching types, and fills missing fields in dictionaries with None so all dictionaries have the same keys and value types.
1035
+
1036
+ To avoid this and allow mixed-types without errors, you can use `on_mixed_types="use_json"` or specify `features=` with a [`Json`] type:
1037
+
1038
+ ```py
1039
+ >>> ds = Dataset.from_dict({"a": [0, "foo", {"subfield": "bar"}]})
1040
+ Traceback (most recent call last):
1041
+ ...
1042
+ File "pyarrow/error.pxi", line 92, in pyarrow.lib.check_status
1043
+ pyarrow.lib.ArrowInvalid: Could not convert 'foo' with type str: tried to convert to int64
1044
+
1045
+ >>> ds = Dataset.from_dict({"a": [0, "foo", {"subfield": "bar"}]}, on_mixed_types="use_json")
1046
+ >>> ds.features
1047
+ {'a': Json()}
1048
+ >>> list(ds["a"])
1049
+ [0, "foo", {"subfield": "bar"}]
1050
+
1051
+ >>> features = Features({"a": Json()})
1052
+ >>> ds = Dataset.from_dict({"a": [0, "foo", {"subfield": "bar"}]}, features=features)
1053
+ >>> ds.features
1054
+ {'a': Json()}
1055
+ >>> list(ds["a"])
1056
+ [0, "foo", {"subfield": "bar"}]
1057
+ ```
1058
+
1059
+ This is also useful for lists of dictionaries with arbitrary keys and values, to avoid filling missing fields with None:
1060
+
1061
+ ```py
1062
+ >>> ds = Dataset.from_dict({"a": [[{"b": 0}, {"c": 0}]]})
1063
+ >>> ds.features
1064
+ {'a': List({'b': Value('int64'), 'c': Value('int64')})}
1065
+ >>> list(ds["a"])
1066
+ [[{'b': 0, 'c': None}, {'b': None, 'c': 0}]] # missing fields are filled with None
1067
+
1068
+ >>> features = Features({"a": List(Json())})
1069
+ >>> ds = Dataset.from_dict({"a": [[{"b": 0}, {"c": 0}]]}, features=features)
1070
+ >>> ds.features
1071
+ {'a': List(Json())}
1072
+ >>> list(ds["a"])
1073
+ [[{'b': 0}, {'c': 0}]] # OK
1074
+
1075
+ >>> ds = Dataset.from_dict({"a": [[{"b": 0}, {"c": 0}]]}, on_mixed_types="use_json")
1076
+ >>> ds.features
1077
+ {'a': List(Json())}
1078
+ >>> list(ds["a"])
1079
+ [[{'b': 0}, {'c': 0}]] # OK
1080
+ ```
1081
+
1082
+ Another example with tool calling data:
1083
+
1084
+ ```py
1085
+ >>> messages = [
1086
+ ... {"role": "user", "content": "Turn on the living room lights and play my electronic music playlist."},
1087
+ ... {"role": "assistant", "tool_calls": [
1088
+ ... {"type": "function", "function": {
1089
+ ... "name": "control_light",
1090
+ ... "arguments": {"room": "living room", "state": "on"}
1091
+ ... }},
1092
+ ... {"type": "function", "function": {
1093
+ ... "name": "play_music",
1094
+ ... "arguments": {"playlist": "electronic"} # mixed-type here since keys ["playlist"] and ["room", "state"] are different
1095
+ ... }}]
1096
+ ... },
1097
+ ... {"role": "tool", "name": "control_light", "content": "The lights in the living room are now on."},
1098
+ ... {"role": "tool", "name": "play_music", "content": "The music is now playing."},
1099
+ ... {"role": "assistant", "content": "Done!"}
1100
+ ... ]
1101
+ >>> ds = Dataset.from_dict({"messages": [messages]}, on_mixed_types="use_json")
1102
+ >>> ds.features
1103
+ {'messages': List({'role': Value('string'), 'content': Value('string'), 'tool_calls': List(Json()), 'name': Value('string')})}
1104
+ >>> ds[0]["messages"][1]["tool_calls"][0]["function"]["arguments"]
1105
+ {"room": "living room", "state": "on"}
1106
+ ```
1006
1107
  """
1007
1108
  if info is not None and features is not None and info.features != features:
1008
1109
  raise ValueError(
@@ -1020,6 +1121,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
1020
1121
  features.encode_column(data, col) if features is not None else data,
1021
1122
  type=features[col] if features is not None else None,
1022
1123
  col=col,
1124
+ on_mixed_types=on_mixed_types,
1023
1125
  )
1024
1126
  arrow_typed_mapping[col] = data
1025
1127
  mapping = arrow_typed_mapping
@@ -1045,6 +1147,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
1045
1147
  features: Optional[Features] = None,
1046
1148
  info: Optional[DatasetInfo] = None,
1047
1149
  split: Optional[NamedSplit] = None,
1150
+ on_mixed_types: Optional[Literal["use_json"]] = None,
1048
1151
  ) -> "Dataset":
1049
1152
  """
1050
1153
  Convert a list of dicts to a `pyarrow.Table` to create a [`Dataset`]`.
@@ -1063,13 +1166,113 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
1063
1166
  features (`Features`, optional): Dataset features.
1064
1167
  info (`DatasetInfo`, optional): Dataset information, like description, citation, etc.
1065
1168
  split (`NamedSplit`, optional): Name of the dataset split.
1169
+ on_mixed_types (`Literal["use_json"]`, *optional*, defaults to `None`):
1170
+ If "use_json", use the Json() type for mixed-types fields,
1171
+ i.e. unstructured fields that contain data without a predefined schema.
1172
+ In this case, a field with mixed type is set to Json().
1173
+
1174
+ This allow loading lists with a mix of strings/integers/floats
1175
+ for example, or dictionaries with arbitrary value types.
1176
+
1177
+ <Added version="4.7.0"/>
1066
1178
 
1067
1179
  Returns:
1068
1180
  [`Dataset`]
1181
+
1182
+ Examples:
1183
+
1184
+ Get a Dataset from a list containing the examples:
1185
+
1186
+ ```py
1187
+ >>> ds = Dataset.from_list([{"text": "hello there !"}, {"text": "general kenobi !"}]})
1188
+ ```
1189
+
1190
+ Pass features to set the column types, e.g. for an image dataset:
1191
+
1192
+ ```py
1193
+ >>> features = Features({"image": Image()})
1194
+ >>> ds = Dataset.from_list([{"image": "path/to/image.png"}], features=features)
1195
+ ```
1196
+
1197
+ Datasets are based on Arrow which is a columnar format, and therefore they expect every example to have the same
1198
+ type and subtypes, and dictionaries to have the same keys and values types.
1199
+ Loading a dataset errors out when fields have mismatching types, and fills missing fields in dictionaries with None so all dictionaries have the same keys and value types.
1200
+
1201
+ To avoid this and allow mixed-types without errors, you can use `on_mixed_types="use_json"` or specify `features=` with a [`Json`] type:
1202
+
1203
+ ```py
1204
+ >>> ds = Dataset.from_list([{"a": 0}, {"a": "foo"}, {"a": {"subfield": "bar"}}])
1205
+ Traceback (most recent call last):
1206
+ ...
1207
+ File "pyarrow/error.pxi", line 92, in pyarrow.lib.check_status
1208
+ pyarrow.lib.ArrowInvalid: Could not convert 'foo' with type str: tried to convert to int64
1209
+
1210
+ >>> ds = Dataset.from_list([{"a": 0}, {"a": "foo"}, {"a": {"subfield": "bar"}}], on_mixed_types="use_json")
1211
+ >>> ds.features
1212
+ {'a': Json()}
1213
+ >>> list(ds["a"])
1214
+ [0, "foo", {"subfield": "bar"}]
1215
+
1216
+ >>> features = Features({"a": Json()})
1217
+ >>> ds = Dataset.from_list([{"a": 0}, {"a": "foo"}, {"a": {"subfield": "bar"}}], features=features)
1218
+ >>> ds.features
1219
+ {'a': Json()}
1220
+ >>> list(ds["a"])
1221
+ [0, "foo", {"subfield": "bar"}]
1222
+ ```
1223
+
1224
+ This is also useful for lists of dictionaries with arbitrary keys and values, to avoid filling missing fields with None:
1225
+
1226
+ ```py
1227
+ >>> ds = Dataset.from_list([{"a": [{"b": 0}, {"c": 0}]}])
1228
+ >>> ds.features
1229
+ {'a': List({'b': Value('int64'), 'c': Value('int64')})}
1230
+ >>> list(ds["a"])
1231
+ [[{'b': 0, 'c': None}, {'b': None, 'c': 0}]] # missing fields are filled with None
1232
+
1233
+ >>> features = Features({"a": List(Json())})
1234
+ >>> ds = Dataset.from_list([{"a": [{"b": 0}, {"c": 0}]}], features=features)
1235
+ >>> ds.features
1236
+ {'a': List(Json())}
1237
+ >>> list(ds["a"])
1238
+ [[{'b': 0}, {'c': 0}]] # OK
1239
+
1240
+ >>> ds = Dataset.from_list([{"a": [{"b": 0}, {"c": 0}]}], on_mixed_types="use_json")
1241
+ >>> ds.features
1242
+ {'a': List(Json())}
1243
+ >>> list(ds["a"])
1244
+ [[{'b': 0}, {'c': 0}]] # OK
1245
+ ```
1246
+
1247
+ Another example with tool calling data:
1248
+
1249
+ ```py
1250
+ >>> messages = [
1251
+ ... {"role": "user", "content": "Turn on the living room lights and play my electronic music playlist."},
1252
+ ... {"role": "assistant", "tool_calls": [
1253
+ ... {"type": "function", "function": {
1254
+ ... "name": "control_light",
1255
+ ... "arguments": {"room": "living room", "state": "on"}
1256
+ ... }},
1257
+ ... {"type": "function", "function": {
1258
+ ... "name": "play_music",
1259
+ ... "arguments": {"playlist": "electronic"} # mixed-type here since keys ["playlist"] and ["room", "state"] are different
1260
+ ... }}]
1261
+ ... },
1262
+ ... {"role": "tool", "name": "control_light", "content": "The lights in the living room are now on."},
1263
+ ... {"role": "tool", "name": "play_music", "content": "The music is now playing."},
1264
+ ... {"role": "assistant", "content": "Done!"}
1265
+ ... ]
1266
+ >>> ds = Dataset.from_list([{"messages": messages}], on_mixed_types="use_json")
1267
+ >>> ds.features
1268
+ {'messages': List({'role': Value('string'), 'content': Value('string'), 'tool_calls': List(Json()), 'name': Value('string')})}
1269
+ >>> ds[0]["messages"][1]["tool_calls"][0]["function"]["arguments"]
1270
+ {"room": "living room", "state": "on"}
1271
+ ```
1069
1272
  """
1070
1273
  # for simplicity and consistency wrt OptimizedTypedSequence we do not use InMemoryTable.from_pylist here
1071
1274
  mapping = {k: [r.get(k) for r in mapping] for k in mapping[0]} if mapping else {}
1072
- return cls.from_dict(mapping, features, info, split)
1275
+ return cls.from_dict(mapping, features, info, split, on_mixed_types=on_mixed_types)
1073
1276
 
1074
1277
  @staticmethod
1075
1278
  def from_csv(
@@ -3016,6 +3219,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3016
3219
  new_fingerprint: Optional[str] = None,
3017
3220
  desc: Optional[str] = None,
3018
3221
  try_original_type: Optional[bool] = True,
3222
+ on_mixed_types: Optional[Literal["use_json"]] = "use_json",
3019
3223
  ) -> "Dataset":
3020
3224
  """
3021
3225
  Apply a function to all the examples in the table (individually or in batches) and update the table.
@@ -3104,6 +3308,15 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3104
3308
  try_original_type (`Optional[bool]`, defaults to `True`):
3105
3309
  Try to keep the types of the original columns (e.g. int32 -> int32).
3106
3310
  Set to False if you want to always infer new types.
3311
+ on_mixed_types (`Literal["use_json"]`, *optional*, defaults to `None`):
3312
+ If "use_json", use the Json() type for mixed-types fields,
3313
+ i.e. unstructured fields that contain data without a predefined schema.
3314
+ In this case, a field with mixed type is set to Json().
3315
+
3316
+ This allow loading lists with a mix of strings/integers/floats
3317
+ for example, or dictionaries with arbitrary value types.
3318
+
3319
+ <Added version="4.7.0"/>
3107
3320
 
3108
3321
  Example:
3109
3322
 
@@ -3205,6 +3418,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3205
3418
  "disable_nullable": disable_nullable,
3206
3419
  "fn_kwargs": fn_kwargs,
3207
3420
  "try_original_type": try_original_type,
3421
+ "on_mixed_types": on_mixed_types,
3208
3422
  }
3209
3423
 
3210
3424
  if new_fingerprint is None:
@@ -3459,6 +3673,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3459
3673
  rank: Optional[int] = None,
3460
3674
  offset: int = 0,
3461
3675
  try_original_type: Optional[bool] = True,
3676
+ on_mixed_types: Optional[Literal["use_json"]] = "use_json",
3462
3677
  ) -> Iterable[tuple[Optional[int], bool, Union[int, "Dataset"]]]:
3463
3678
  """Apply a function to all the elements in the table (individually or in batches)
3464
3679
  and update the table (if function does update examples).
@@ -3503,6 +3718,15 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3503
3718
  try_original_type: (`Optional[bool]`, defaults to `True`):
3504
3719
  Try to keep the types of the original columns (e.g. int32 -> int32).
3505
3720
  Set to False if you want to always infer new types.
3721
+ on_mixed_types (`Literal["use_json"]`, *optional*, defaults to `None`):
3722
+ If "use_json", use the Json() type for mixed-types fields,
3723
+ i.e. unstructured fields that contain data without a predefined schema.
3724
+ In this case, a field with mixed type is set to Json().
3725
+
3726
+ This allow loading lists with a mix of strings/integers/floats
3727
+ for example, or dictionaries with arbitrary value types.
3728
+
3729
+ <Added version="4.7.0"/>
3506
3730
  """
3507
3731
  if fn_kwargs is None:
3508
3732
  fn_kwargs = {}
@@ -3659,6 +3883,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3659
3883
  update_features=update_features,
3660
3884
  fingerprint=new_fingerprint,
3661
3885
  disable_nullable=disable_nullable,
3886
+ on_mixed_types=on_mixed_types,
3662
3887
  )
3663
3888
  else:
3664
3889
  buf_writer = None
@@ -3673,6 +3898,7 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
3673
3898
  update_features=update_features,
3674
3899
  fingerprint=new_fingerprint,
3675
3900
  disable_nullable=disable_nullable,
3901
+ on_mixed_types=on_mixed_types,
3676
3902
  )
3677
3903
  return buf_writer, writer, tmp_file
3678
3904
 
@@ -5628,9 +5854,10 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
5628
5854
  )
5629
5855
  except (Exception, KeyboardInterrupt):
5630
5856
  tmp_file.close()
5631
- if Path(tmp_file.name).exists():
5632
- Path(tmp_file.name).unlink()
5857
+ Path(tmp_file.name).unlink()
5633
5858
  raise
5859
+ tmp_file.close()
5860
+ Path(tmp_file.name).unlink()
5634
5861
  additions.append(shard_addition)
5635
5862
  yield job_id, False, 1
5636
5863
 
@@ -5680,6 +5907,16 @@ class Dataset(DatasetInfoMixin, IndexableMixin, TensorflowDatasetMixin):
5680
5907
  additions: list[CommitOperationAdd] = []
5681
5908
 
5682
5909
  num_jobs = num_proc or 1
5910
+ if num_shards <= 1:
5911
+ logger.warning(
5912
+ f"Setting num_proc from {num_jobs} back to 1 for the {split} split to disable multiprocessing as it only contains one shard."
5913
+ )
5914
+ num_jobs = 1
5915
+ elif num_shards < num_jobs:
5916
+ logger.warning(
5917
+ f"Setting num_proc from {num_jobs} to {num_shards} for the {split} split as it only contains {num_shards} shards."
5918
+ )
5919
+ num_proc = num_shards
5683
5920
  kwargs_iterable = [
5684
5921
  {
5685
5922
  "self": self.shard(num_shards=num_jobs, index=job_id, contiguous=True),
@@ -13,14 +13,16 @@
13
13
  # Lint as: python3
14
14
  """To write records into Parquet files."""
15
15
 
16
+ import io
16
17
  import json
17
18
  import sys
18
19
  from collections.abc import Iterable
19
- from typing import Any, Optional
20
+ from typing import Any, Literal, Optional
20
21
 
21
22
  import fsspec
22
23
  import numpy as np
23
24
  import pyarrow as pa
25
+ import pyarrow.json as paj
24
26
  import pyarrow.parquet as pq
25
27
  from fsspec.core import url_to_fs
26
28
 
@@ -43,6 +45,16 @@ from .filesystems import is_remote_filesystem
43
45
  from .info import DatasetInfo
44
46
  from .table import array_cast, cast_array_to_feature, embed_table_storage, table_cast
45
47
  from .utils import logging
48
+ from .utils.json import (
49
+ find_mixed_struct_types_field_paths,
50
+ get_json_field_path_from_pyarrow_json_error,
51
+ get_json_field_paths_from_feature,
52
+ insert_json_field_path,
53
+ json_encode_field,
54
+ json_encode_fields_in_json_lines,
55
+ set_json_types_in_feature,
56
+ ujson_dumps,
57
+ )
46
58
  from .utils.py_utils import asdict, convert_file_size_to_int, first_non_null_non_empty_value
47
59
 
48
60
 
@@ -204,6 +216,7 @@ class TypedSequence:
204
216
  type: Optional[FeatureType] = None,
205
217
  try_type: Optional[FeatureType] = None,
206
218
  optimized_int_type: Optional[FeatureType] = None,
219
+ on_mixed_types: Optional[Literal["use_json"]] = None,
207
220
  ):
208
221
  # assert type is None or try_type is None,
209
222
  if type is not None and try_type is not None:
@@ -213,6 +226,7 @@ class TypedSequence:
213
226
  self.type = type
214
227
  self.try_type = try_type # is ignored if it doesn't match the data
215
228
  self.optimized_int_type = optimized_int_type
229
+ self.on_mixed_types = on_mixed_types
216
230
  # when trying a type (is ignored if data is not compatible)
217
231
  self.trying_type = self.try_type is not None
218
232
  self.trying_int_optimization = optimized_int_type is not None and type is None and try_type is None
@@ -231,7 +245,7 @@ class TypedSequence:
231
245
  FeatureType: inferred feature type of the sequence.
232
246
  """
233
247
  if self._inferred_type is None:
234
- self._inferred_type = generate_from_arrow_type(pa.array(self).type)
248
+ pa.array(self)
235
249
  return self._inferred_type
236
250
 
237
251
  @staticmethod
@@ -274,6 +288,12 @@ class TypedSequence:
274
288
  return data, None
275
289
 
276
290
  def __arrow_array__(self, type: Optional[pa.DataType] = None):
291
+ out = self._arrow_array(type=type)
292
+ if self._inferred_type is None:
293
+ self._inferred_type = generate_from_arrow_type(out.type)
294
+ return out
295
+
296
+ def _arrow_array(self, type: Optional[pa.DataType] = None):
277
297
  """This function is called when calling pa.array(typed_sequence)"""
278
298
 
279
299
  if type is not None:
@@ -292,6 +312,7 @@ class TypedSequence:
292
312
  get_nested_type(self.optimized_int_type) if self.optimized_int_type is not None else None
293
313
  )
294
314
  trying_cast_to_python_objects = False
315
+ json_field_paths = []
295
316
  try:
296
317
  # custom pyarrow types
297
318
  if isinstance(pa_type, _ArrayXDExtensionType):
@@ -305,7 +326,25 @@ class TypedSequence:
305
326
  out = list_of_np_array_to_pyarrow_listarray(data)
306
327
  else:
307
328
  trying_cast_to_python_objects = True
308
- out = pa.array(cast_to_python_objects(data, only_1d_for_numpy=True))
329
+ examples = data
330
+ # find fields to json-encode
331
+ if self.on_mixed_types == "use_json" and type is None:
332
+ json_field_paths = find_mixed_struct_types_field_paths(examples, allow_root=True)
333
+ elif type is not None:
334
+ json_field_paths = get_json_field_paths_from_feature(type)
335
+ # json encode if needed
336
+ if json_field_paths:
337
+ for json_field_path in json_field_paths:
338
+ examples = [json_encode_field(examples, json_field_path) for examples in examples]
339
+ # to arrow array
340
+ out = pa.array(cast_to_python_objects(examples, only_1d_for_numpy=True))
341
+ # cast to json type if needed
342
+ if json_field_paths:
343
+ pa_table = pa.Table.from_arrays([out], names=["obj"])
344
+ features = Features.from_arrow_schema(pa_table.schema)
345
+ feature = set_json_types_in_feature(features["obj"], json_field_paths)
346
+ pa_table = table_cast(pa_table, Features({"obj": feature}).arrow_schema)
347
+ out = pa_table[0] # get the "obj" column
309
348
  # use smaller integer precisions if possible
310
349
  if self.trying_int_optimization:
311
350
  if pa.types.is_int64(out.type):
@@ -326,6 +365,7 @@ class TypedSequence:
326
365
  return out
327
366
  except (
328
367
  TypeError,
368
+ pa.lib.ArrowTypeError,
329
369
  pa.lib.ArrowInvalid,
330
370
  pa.lib.ArrowNotImplementedError,
331
371
  ) as e: # handle type errors and overflows
@@ -372,8 +412,46 @@ class TypedSequence:
372
412
  optimized_int_pa_type_str = np.dtype(optimized_int_pa_type.to_pandas_dtype()).name
373
413
  logger.info(f"Failed to cast a sequence to {optimized_int_pa_type_str}. Falling back to int64.")
374
414
  return out
375
- elif trying_cast_to_python_objects and "Could not convert" in str(e):
376
- out = pa.array(cast_to_python_objects(data, only_1d_for_numpy=True, optimize_list_casting=False))
415
+ elif trying_cast_to_python_objects and (
416
+ "Could not convert" in str(e) or "cannot mix struct and non-struct" in str(e) or "Expected " in str(e)
417
+ ):
418
+ try: # third chance
419
+ out = pa.array(cast_to_python_objects(data, only_1d_for_numpy=True, optimize_list_casting=False))
420
+ except (pa.ArrowInvalid, pa.ArrowTypeError) as ee:
421
+ # in case of mixed types, we use the JSON Lines reader in pyarrow to locate them and set them to json fields
422
+ if self.on_mixed_types == "use_json" and (
423
+ "Could not convert " in str(ee)
424
+ or "cannot mix struct and non-struct" in str(ee)
425
+ or "Expected " in str(ee)
426
+ ):
427
+ # we use "obj" to have valid JSON Lines since data may contain lists
428
+ original_batch = "\n".join([ujson_dumps({"obj": example}) for example in data]).encode()
429
+ json_field_paths = [["obj"] + json_field_path for json_field_path in json_field_paths]
430
+ batch = json_encode_fields_in_json_lines(original_batch, json_field_paths)
431
+ pa_table = None
432
+ while True:
433
+ try: # fourth chance
434
+ pa_table = paj.read_json(
435
+ io.BytesIO(batch), read_options=paj.ReadOptions(use_threads=False)
436
+ )
437
+ break
438
+ except pa.ArrowInvalid as eee:
439
+ if "JSON parse error: Column(" in str(eee) and ") changed from" in str(eee):
440
+ json_field_path = get_json_field_path_from_pyarrow_json_error(str(eee))
441
+ insert_json_field_path(json_field_paths, json_field_path)
442
+ batch = json_encode_fields_in_json_lines(original_batch, json_field_paths)
443
+ else:
444
+ break
445
+ if pa_table is not None:
446
+ features = Features.from_arrow_schema(pa_table.schema)
447
+ features = set_json_types_in_feature(features, json_field_paths)
448
+ pa_table = table_cast(pa_table, features.arrow_schema)
449
+ out = pa_table[0] # get the "obj" column
450
+ return out
451
+ else:
452
+ raise
453
+ else:
454
+ raise
377
455
  if type is not None:
378
456
  out = cast_array_to_feature(out, type, allow_primitive_to_str=True, allow_decimal_to_str=True)
379
457
  return out
@@ -389,6 +467,7 @@ class OptimizedTypedSequence(TypedSequence):
389
467
  try_type: Optional[FeatureType] = None,
390
468
  col: Optional[str] = None,
391
469
  optimized_int_type: Optional[FeatureType] = None,
470
+ on_mixed_types: Optional[Literal["use_json"]] = None,
392
471
  ):
393
472
  optimized_int_type_by_col = {
394
473
  "attention_mask": Value("int8"), # binary tensor
@@ -400,7 +479,9 @@ class OptimizedTypedSequence(TypedSequence):
400
479
  }
401
480
  if type is None and try_type is None:
402
481
  optimized_int_type = optimized_int_type_by_col.get(col, None)
403
- super().__init__(data, type=type, try_type=try_type, optimized_int_type=optimized_int_type)
482
+ super().__init__(
483
+ data, type=type, try_type=try_type, optimized_int_type=optimized_int_type, on_mixed_types=on_mixed_types
484
+ )
404
485
 
405
486
 
406
487
  class ArrowWriter:
@@ -416,6 +497,7 @@ class ArrowWriter:
416
497
  writer_batch_size: Optional[int] = None,
417
498
  disable_nullable: bool = False,
418
499
  update_features: bool = False,
500
+ on_mixed_types: Optional[Literal["use_json"]] = "use_json",
419
501
  with_metadata: bool = True,
420
502
  unit: str = "examples",
421
503
  embed_local_files: bool = False,
@@ -455,6 +537,7 @@ class ArrowWriter:
455
537
  or config.DEFAULT_MAX_BATCH_SIZE
456
538
  )
457
539
  self.update_features = update_features
540
+ self.on_mixed_types = on_mixed_types
458
541
  self.with_metadata = with_metadata
459
542
  self.unit = unit
460
543
  self.embed_local_files = embed_local_files
@@ -654,7 +737,9 @@ class ArrowWriter:
654
737
  if try_features is not None and col in try_features and try_original_type
655
738
  else None
656
739
  )
657
- typed_sequence = OptimizedTypedSequence(col_values, type=col_type, try_type=col_try_type, col=col)
740
+ typed_sequence = OptimizedTypedSequence(
741
+ col_values, type=col_type, try_type=col_try_type, col=col, on_mixed_types=self.on_mixed_types
742
+ )
658
743
  arrays.append(pa.array(typed_sequence))
659
744
  inferred_features[col] = typed_sequence.get_inferred_type()
660
745
  schema = inferred_features.arrow_schema if self.pa_writer is None else self.schema
@@ -11,7 +11,7 @@ import time
11
11
  from collections.abc import Sequence
12
12
  from functools import partial
13
13
  from pathlib import Path
14
- from typing import Callable, Optional, Union
14
+ from typing import Callable, Literal, Optional, Union
15
15
 
16
16
  import fsspec
17
17
  import numpy as np
@@ -836,6 +836,7 @@ class DatasetDict(dict[Union[str, NamedSplit], "Dataset"]):
836
836
  num_proc: Optional[int] = None,
837
837
  desc: Optional[str] = None,
838
838
  try_original_type: Optional[bool] = True,
839
+ on_mixed_types: Optional[Literal["use_json"]] = None,
839
840
  ) -> "DatasetDict":
840
841
  """
841
842
  Apply a function to all the examples in the table (individually or in batches) and update the table.
@@ -920,6 +921,15 @@ class DatasetDict(dict[Union[str, NamedSplit], "Dataset"]):
920
921
  try_original_type (`Optional[bool]`, defaults to `True`):
921
922
  Try to keep the types of the original columns (e.g. int32 -> int32).
922
923
  Set to False if you want to always infer new types.
924
+ on_mixed_types (`Literal["use_json"]`, *optional*, defaults to `None`):
925
+ If "use_json", use the Json() type for mixed-types fields,
926
+ i.e. unstructured fields that contain data without a predefined schema.
927
+ In this case, a field with mixed type is set to Json().
928
+
929
+ This allow loading lists with a mix of strings/integers/floats
930
+ for example, or dictionaries with arbitrary value types.
931
+
932
+ <Added version="4.7.0"/>
923
933
 
924
934
  Example:
925
935
 
@@ -969,6 +979,7 @@ class DatasetDict(dict[Union[str, NamedSplit], "Dataset"]):
969
979
  num_proc=num_proc,
970
980
  desc=desc,
971
981
  try_original_type=try_original_type,
982
+ on_mixed_types=on_mixed_types,
972
983
  )
973
984
 
974
985
  if with_split:
@@ -6,6 +6,7 @@ __all__ = [
6
6
  "Array5D",
7
7
  "ClassLabel",
8
8
  "Features",
9
+ "Json",
9
10
  "LargeList",
10
11
  "List",
11
12
  "Sequence",
@@ -18,7 +19,7 @@ __all__ = [
18
19
  "Nifti",
19
20
  ]
20
21
  from .audio import Audio
21
- from .features import Array2D, Array3D, Array4D, Array5D, ClassLabel, Features, LargeList, List, Sequence, Value
22
+ from .features import Array2D, Array3D, Array4D, Array5D, ClassLabel, Features, Json, LargeList, List, Sequence, Value
22
23
  from .image import Image
23
24
  from .nifti import Nifti
24
25
  from .pdf import Pdf