| import csv |
| import sys |
| import tempfile |
| import unittest |
| import zipfile |
| from pathlib import Path |
| from unittest.mock import MagicMock |
|
|
| sys.modules.setdefault("httpx", MagicMock()) |
| import fisheries_hf |
|
|
|
|
| CSV_TEXT = """year,month,lon,lat,effort,flag |
| 2022,12,141,2,9,A |
| 2023,1,141,2,1.5,A |
| 2023,2,142,3,2.5,B |
| 2023,2,142,3,2.5,B |
| 2023,3,150,3,8,C |
| """ |
|
|
|
|
| class FisheriesHFTests(unittest.TestCase): |
| def setUp(self): |
| self.tmp = tempfile.TemporaryDirectory() |
| self.root = Path(self.tmp.name) |
| fisheries_hf.EXPORT_ROOT = self.root / "exports" |
| fisheries_hf.EXPORT_ROOT.mkdir() |
|
|
| def tearDown(self): |
| self.tmp.cleanup() |
|
|
| def _check(self, path: Path): |
| result = fisheries_hf.analyze_and_export( |
| path, |
| dataset_path="current/test" + path.suffix, |
| revision="a" * 40, |
| repository="tuna", |
| year=2023, |
| lon_min=140, |
| lon_max=145, |
| lat_min=0, |
| lat_max=5, |
| ) |
| self.assertEqual(result["status"], "ok") |
| self.assertEqual( |
| result["repository"], |
| "globalsquiddatabase/Tuna-Fisheries-Dataset", |
| ) |
| self.assertEqual(result["scanned_row_count"], 5) |
| self.assertEqual(result["matched_row_count"], 3) |
| self.assertEqual(result["time_range"], {"min_year": 2023, "max_year": 2023}) |
| self.assertEqual(result["exact_duplicate_count"], 1) |
| self.assertEqual(result["missing_values_by_column"]["effort"], 0) |
| self.assertEqual(result["monthly_record_counts"], [ |
| {"month": 1, "record_count": 1}, |
| {"month": 2, "record_count": 2}, |
| ]) |
| self.assertEqual(result["annual_summary"][0]["record_count"], 3) |
| self.assertAlmostEqual(result["annual_summary"][0]["sum_effort"], 6.5) |
| self.assertEqual(result["deduplicated_record_count"], 2) |
| self.assertEqual( |
| [item["kind"] for item in result["exports"]], |
| ["filtered_raw", "deduplicated", "annual_summary"], |
| ) |
| self.assertEqual(len(result["download_urls"]), 3) |
| export = fisheries_hf.EXPORT_ROOT / result["token"] / result["filename"] |
| self.assertTrue(export.is_file()) |
| with export.open(encoding="utf-8-sig", newline="") as stream: |
| rows = list(csv.DictReader(stream)) |
| self.assertEqual(len(rows), 3) |
| for item in result["exports"]: |
| exported = fisheries_hf.EXPORT_ROOT / item["token"] / item["filename"] |
| self.assertTrue(exported.is_file()) |
|
|
| def test_csv_filter_quality_and_export(self): |
| path = self.root / "sample.csv" |
| path.write_text(CSV_TEXT, encoding="utf-8") |
| self._check(path) |
|
|
| def test_zip_csv_member_filter_and_export(self): |
| path = self.root / "sample.zip" |
| with zipfile.ZipFile(path, "w", compression=zipfile.ZIP_DEFLATED) as archive: |
| archive.writestr("monthly_2023.csv", CSV_TEXT) |
| self._check(path) |
|
|
| def test_rejects_invalid_bbox(self): |
| path = self.root / "sample.csv" |
| path.write_text(CSV_TEXT, encoding="utf-8") |
| with self.assertRaisesRegex(ValueError, "lon_min"): |
| fisheries_hf.analyze_and_export( |
| path, |
| dataset_path="current/test.csv", |
| revision="a" * 40, |
| lon_min=181, |
| ) |
|
|
| def test_repository_allowlist(self): |
| self.assertEqual( |
| fisheries_hf.normalize_repository("squid"), |
| "globalsquiddatabase/squid_dataset", |
| ) |
| self.assertEqual( |
| fisheries_hf.normalize_repository("tuna"), |
| "globalsquiddatabase/Tuna-Fisheries-Dataset", |
| ) |
| with self.assertRaisesRegex(ValueError, "repository"): |
| fisheries_hf.normalize_repository("someone/other-dataset") |
|
|
| def test_local_mirror_overrides_only_matching_remote_path(self): |
| local_root = self.root / "local-squid" |
| local_root.mkdir() |
| (local_root / "cached.csv").write_text("year\n2023\n", encoding="utf-8") |
| previous = fisheries_hf.LOCAL_DATA_ROOTS["squid"] |
| fisheries_hf.LOCAL_DATA_ROOTS["squid"] = local_root |
| try: |
| merged = fisheries_hf.merge_local_with_remote_tree( |
| [ |
| {"path": "cached.csv", "type": "file", "size": 999}, |
| {"path": "remote-only.csv", "type": "file", "size": 42}, |
| ], |
| "squid", |
| ) |
| finally: |
| fisheries_hf.LOCAL_DATA_ROOTS["squid"] = previous |
| by_path = {item["path"]: item for item in merged} |
| self.assertEqual(set(by_path), {"cached.csv", "remote-only.csv"}) |
| self.assertEqual(by_path["cached.csv"]["storage_origin"], "school_local_mirror") |
| self.assertEqual(by_path["remote-only.csv"]["storage_origin"], "huggingface") |
|
|
| def test_iccat_yearc_alias(self): |
| path = self.root / "iccat.csv" |
| path.write_text( |
| "YearC,effort\n2023,2\n2023,3\n2024,4\n", |
| encoding="utf-8", |
| ) |
| result = fisheries_hf.analyze_and_export( |
| path, |
| dataset_path="ICCAT/processed/EFFDIS_LL2000-2024.csv", |
| revision="b" * 40, |
| repository="tuna", |
| ) |
| self.assertEqual(result["time_range"], {"min_year": 2023, "max_year": 2024}) |
| self.assertEqual(result["annual_summary"][0]["year"], 2023) |
| self.assertEqual(result["annual_summary"][0]["sum_effort"], 5.0) |
| self.assertEqual(len(result["exports"]), 3) |
|
|
|
|
| if __name__ == "__main__": |
| unittest.main() |
|
|