Repository navigation
feat: spec 004, the source toolkit (benchcommons-tools-dataset 0.1.0) - #7
Merged
Merged
Conversation
Spec 004 moves the generic source code of dataset-names (download cache, spreadsheet reader, adapter base, source registry, file helpers) into an installable package. ADRs record the package name, how dataset repos depend on it (uv git source pinned to a tag), the runtime dependencies and the per-dataset list of accepted licences. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The plan fixes the public API of v0.1.0, how dataset-names maps onto the registry schema, the port map of dataset-names tests, the CI jobs and the release tag step. Spec 001's skeleton task now points to spec 004. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
pyproject (Python 3.12, hatchling, pinned pyyaml and xlrd), uv.lock, Apache-2.0 LICENSE, the datasettool package, the local HTTP test server and CI jobs that run the tests and install the package from a git URL. The docs CI job is kept. Local test server ported from BenchCommons/dataset-names@e7e8405 tests/conftest.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Resource, SourceFiles, FormatError, AdapterError, the URL and file name checks, check_adapter and load_adapter (absent versus broken), and parse_count/parse_code. The adapter package is chosen by the dataset and the record type is the dataset's own; optional protocol functions such as dataset-names' links are checked when declared. Messages are in English; test vectors are unchanged. ported from BenchCommons/dataset-names@e7e8405 src/namescommons/adapters/__init__.py tests ported from BenchCommons/dataset-names@e7e8405 tests/test_adapters.py, tests/test_contrato_adaptador.py, tests/adaptadores/exemplo.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cache/<source_id>/<file> with .meta.json, User-Agent, retries with doubling backoff, no retry on 4xx except 408 and 429, atomic writes, Content-Length check, BlockedError for text/html, the 403 manual download hint and the offline/refresh rules. The User-Agent defaults to dataset-tool's and a dataset passes its own; parameters are renamed to attempts, backoff and sleep. Test vectors unchanged. ported from BenchCommons/dataset-names@e7e8405 src/namescommons/cache.py tests ported from BenchCommons/dataset-names@e7e8405 tests/test_cache.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Streaming XLSX reader on the standard library with DTD, ZIP bomb, column and row guards; XLS through xlrd 2.0.2; same value types in both formats; cell_count. The synthetic types.xls fixture is a byte-identical copy of dataset-names' tipos.xls. The INE sample test stays in dataset-names. Messages in English; test vectors unchanged. ported from BenchCommons/dataset-names@e7e8405 src/namescommons/spreadsheet.py tests ported from BenchCommons/dataset-names@e7e8405 tests/test_spreadsheet.py and tests/fixtures/planilhas/tipos.xls Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The repo is now BenchCommons/tools-dataset (.product ADR 0005). URLs, the distribution name (benchcommons-tools-dataset) and the default User-Agent follow it; the import package datasettool is unchanged. ADR 0003 and the plan record why the toolkit stays here rather than in tools-commons. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generic fields (id, name, url, license, attribution, retrieved, adapter) with the id, url, licence and date rules; datasets add their own fields, accepted licences, policy text, cross-entry checks and source factory. ATTRIBUTION_ONLY_LICENSES is the shared starting set (ADR 0006). The dataset-names registry tests run through a test schema that rebuilds its rules (country, count_type, primary, suppression, uniform_case, one primary) from the public API. ported from BenchCommons/dataset-names@e7e8405 src/namescommons/sources.py tests ported from BenchCommons/dataset-names@e7e8405 tests/test_sources.py and tests/test_sources_extensoes.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… expat level The DTD pre-scan read members as UTF-8 or UTF-16, while expat honours the encoding named in the XML declaration. Members must now be valid UTF-8 or UTF-16 and declare no other encoding, and expat is used directly with ElementTree.TreeBuilder so DOCTYPE and ENTITY declarations are refused by the parser itself, independently of the pre-scan, while streaming. Spec R3.4 and ADR 0005 list the new guards. ported from BenchCommons/dataset-names@eaaa4d1 (PR #39) src/namescommons/spreadsheet.py tests ported from BenchCommons/dataset-names@eaaa4d1 tests/test_spreadsheet.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sha256_file, count_csv_records (CSV reader, not physical lines) and describe_files, the file loop of dataset-names' manifest with a row counter per suffix registered by the dataset; files without a counter are refused. The names manifest itself stays in dataset-names. The CI install job now imports every module. ported from BenchCommons/dataset-names@e7e8405 src/namescommons/manifest.py tests ported from BenchCommons/dataset-names@e7e8405 tests/test_manifest.py and tests/test_robustez.py Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Tasks T1 to T8 done; the plan and spec name dataset-names PR #39 as the origin of the spreadsheet reader's encoding and expat-level DTD guards. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cached_path, and so fetch_resource, now validate the source id against the registry id format and the file name against the adapter rule, and check that the resolved path stays under the cache directory. Before, fetch_resource(cache, '..', ...) read outside the cache and a file name '/etc/passwd' escaped it. ID_PATTERN moves to the adapters module and the registry re-exports it. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A str licence list turned the licence check into a substring test ('BY'
accepted for 'CC-BY-4.0'), and optional='links' in check_adapter was
iterated character by character. RegistrySchema now refuses str for
accepted_licenses, fields and checks, coerces them to frozenset and
tuples and checks their item types; check_adapter and load_adapter refuse
a str optional.
Refs #4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A bad CRC, bad deflate data or a truncated member raised BadZipFile, zlib.error or EOFError from inside the reader. Opening and reading a member now turns them into FormatError naming the file and member. The module docstring names both dataset-names origins (e7e8405 and eaaa4d1). Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An autouse fixture patches socket connect, connect_ex and getaddrinfo so any test that reaches a host other than 127.0.0.1, ::1 or localhost fails, enforcing spec R7.3 instead of relying on review. Also makes the default Source hashable: extra, a read-only MappingProxyType, is left out of the hash but kept in equality. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The build backend is pinned to hatchling 1.32.4. CI now also runs on v* tag pushes and fails when the tag differs from v<pyproject version>, as ADR 0004 requires. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…est adapter Plan 2.4 now states the real validation order and how it differs from dataset-names (only the order of lines in a multi-error message), for the adoption in #5. The decision to keep the toolkit in tools-dataset rather than tools-commons moves to its own ADR 0007. Spec 001's plan uses a placeholder tag, since v0.1.0 ships no CLI. The test-only example adapter is renamed to English. Refs #4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Spec 004, the source toolkit: the generic parts of dataset-names that download, read and register upstream sources move here as the installable package
benchcommons-tools-dataset(importdatasettool), per the owner decision of 2026-10-12.docs/specs/004-source-toolkit/; roadmap row 4 (no dependency on 001).pyyaml==6.0.3,xlrd==2.0.2), 0006 accepted licences per dataset (links .product ADR 0003), 0007 the toolkit lives in tools-dataset rather than tools-commons. 0001 and 0002 stay reserved for spec 001's T1.datasettool.sources.cache,.spreadsheet,.adapters,.registryanddatasettool.files, each ported with its tests (origin in each commit message:ported from BenchCommons/dataset-names@e7e8405 ...; the spreadsheet DTD and encoding guards from dataset-names@eaaa4d1, PR #39).LICENSE,pyproject.toml,uv.lock,AGENTS.mdandREADME.mdwith stack and commands.tests(uv sync --locked,uv run pytest -q) andinstall-from-git(fresh uv project installs the commit under test from this repo's git URL and imports every module).Acceptance criteria and evidence
uv run pytest -q). Port map in plan section 3; not ported (names-specific) is listed there: the INE sample test,RawRecordparse, the names default adapter package, pipeline tests.tests/conftest.pyrefuses every non-loopbackconnectand name lookup in every test (tests/test_no_network.pyproves it).tests/names_registry.py) passes every test of dataset-names'test_sources.pyandtest_sources_extensoes.py.uv init --bareproject,uv add "benchcommons-tools-dataset @ git+https://github.com/BenchCommons/tools-dataset@41e563c"installs and every module imports; the ADR 0004 form ([tool.uv.sources]git source) also syncs (checked with the branch, since the tag comes after merge). The CI job repeats this on the PR head.Review fix round
cached_path/fetch_resourcenow refuse a source id outside the registry id format, an unsafe file name, and any path resolving outside the cache (ValueError), with tests (..,/etc/passwd, symlinked source directory).strgiven foraccepted_licenses,fields,checksoroptionalis refused (TypeError); collections are coerced tofrozenset/tuples (a str licence list made"BY"pass for"CC-BY-4.0").FormatError, with tests.Sourceis hashable (extraleft out of the hash).hatchling==1.32.4pinned; CI runs onv*tags and fails when the tag differs from the package version.Release step (maintainer, after merge)
Decisions taken alone (cost if wrong)
benchcommons-tools-datasetafter the repo rename, importdatasettoolkept from spec 001's plan. Cost: renaming after v0.1.0 breaks every consumer's imports and lock file; before the tag it is a find-and-replace.ATTRIBUTION_ONLY_LICENSESis a shared starting set withoutstatcan-open-licence(dataset-names adds it). Cost: if .product ADR 0003 sets an org-wide list, it becomes one more constant.Fieldlist, cross-entry checks and a factory rather than subclassing or JSON Schema. Cost: an API change in a 0.x minor release.describe_filesrefuses files with no registered row counter instead of counting them as CSV (dataset-names' fallback). Cost: none for dataset-names, which only has CSV and Parquet.types.xlsmoved. Cost: one real-file test less here.LICENSEadded; the owner confirmed tools-dataset keeps Apache-2.0.Closes #4
🤖 Generated with Claude Code