| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| import json |
| import pathlib |
| |
| import lancedb |
| import numpy as np |
| from datasets import Dataset, DatasetDict |
| |
| from hamilton.plugins import huggingface_extensions |
| |
| |
| def _normalize_for_comparison(d): |
| """Normalize dictionary/list for order-independent comparison using JSON serialization.""" |
| return json.loads(json.dumps(d, sort_keys=True, default=str)) |
| |
| |
| def test_hfds_loader(): |
| path_to_test = "tests/resources/hf_datasets" |
| reader = huggingface_extensions.HuggingFaceDSLoader(path_to_test) |
| ds, metadata = reader.load_data(DatasetDict) |
| |
| assert huggingface_extensions.HuggingFaceDSLoader.applicable_types() == list( |
| huggingface_extensions.HF_types |
| ) |
| assert reader.applies_to(DatasetDict) |
| assert reader.applies_to(Dataset) |
| assert ds.shape == {"train": (1, 3)} |
| |
| |
| def test_hfds_parquet_saver(tmp_path: pathlib.Path): |
| file_path = tmp_path / "testhf.parquet" |
| saver = huggingface_extensions.HuggingFaceDSParquetSaver(file_path) |
| ds = Dataset.from_dict({"a": [1, 2, 3]}) |
| metadata = saver.save_data(ds) |
| assert file_path.exists() |
| assert metadata["dataset_metadata"] == { |
| "columns": ["a"], |
| "features": {"a": {"_type": "Value", "dtype": "int64"}}, |
| "rows": 3, |
| "size_in_bytes": None, |
| } |
| assert "file_metadata" in metadata |
| assert huggingface_extensions.HuggingFaceDSParquetSaver.applicable_types() == list( |
| huggingface_extensions.HF_types |
| ) |
| assert saver.applies_to(DatasetDict) |
| assert saver.applies_to(Dataset) |
| |
| |
| def test_hfds_lancedb_saver(tmp_path: pathlib.Path): |
| db_client = lancedb.connect(tmp_path / "lancedb") |
| saver = huggingface_extensions.HuggingFaceDSLanceDBSaver(db_client, "test_table") |
| ds = Dataset.from_dict({"vector": [np.array([1.0, 2.0, 3.0])], "named_entities": ["a"]}) |
| metadata = saver.save_data(ds) |
| |
| # Different versions of HuggingFace datasets use either 'Sequence' or 'List' for array types |
| # Both are semantically equivalent, so we normalize this for comparison |
| expected_metadata = { |
| "db_meta": {"table_name": "test_table"}, |
| "dataset_metadata": { |
| "columns": ["vector", "named_entities"], |
| "features": { |
| "vector": {"_type": "Sequence", "feature": {"_type": "Value", "dtype": "float64"}}, |
| "named_entities": {"_type": "Value", "dtype": "string"}, |
| }, |
| "rows": 1, |
| "size_in_bytes": None, |
| }, |
| } |
| |
| # Normalize _type values: 'List' and 'Sequence' are equivalent |
| def normalize_feature_types(d): |
| if isinstance(d, dict): |
| result = {} |
| for k, v in d.items(): |
| if k == "_type" and v in ("List", "Sequence"): |
| result[k] = "Sequence" # Normalize to Sequence |
| else: |
| result[k] = normalize_feature_types(v) |
| return result |
| elif isinstance(d, list): |
| return [normalize_feature_types(item) for item in d] |
| return d |
| |
| # Normalize both dictionaries for order-independent comparison and feature type equivalence |
| normalized_metadata = normalize_feature_types(metadata) |
| normalized_expected = normalize_feature_types(expected_metadata) |
| assert _normalize_for_comparison(normalized_metadata) == _normalize_for_comparison( |
| normalized_expected |
| ) |
| |
| assert db_client.open_table("test_table").search().to_list() == [ |
| {"named_entities": "a", "vector": [1.0, 2.0, 3.0]} |
| ] |