Skip to content

Migrate all modules off docval + real signatures for generated classes (Phases 3-4 of #1129)#1527

Draft
bendichter wants to merge 5 commits into
typing-compat-layerfrom
typing-phase3-core
Draft

Migrate all modules off docval + real signatures for generated classes (Phases 3-4 of #1129)#1527
bendichter wants to merge 5 commits into
typing-compat-layerfrom
typing-phase3-core

Conversation

@bendichter

Copy link
Copy Markdown
Contributor

Stacked on #1526. Migrates the highest-risk modules for downstream compatibility — the classes PyNWB subclasses and splices most heavily:

  • common/table.py: VectorData, VectorIndex, ElementIdentifiers, DynamicTable, DynamicTableRegion, EnumData, MeaningsTable — all 22 @docval sites now type-hinted signatures with @validated
  • common/alignedtable.py: all literal sites migrated; the three methods that splice parent specs via @docval(*get_docval(DynamicTable...)) intentionally remain on @docval and consume specs synthesized from the migrated parents
  • common/multi.py: SimpleMultiContainer

Notable hand-work (patterns for reviewers to check):

  • mutable list() defaults → = None + body guard (VectorData.data etc.); synthesized specs report default: None, and constructors behave identically when the arg is omitted
  • allow_extra functions: docval's kwargs held ALL parsed args, real **kwargs holds only extras — add_column's column-constructor kwargs, from_dataframe, and MeaningsTable.add_row were rewritten accordingly (the migrate tool now flags this pattern)

Verification: full hdmf suite green (1985); full PyNWB dev suite green (804 tests + 6581 subtests) against this branch.

Remaining Phase 3 (follow-ups): container.py, spec/, build/, backends/hdf5/.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.05391% with 148 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.09%. Comparing base (7cb9cec) to head (a255543).

Files with missing lines Patch % Lines
src/hdmf/common/table.py 65.27% 25 Missing ⚠️
src/hdmf/typing/_build.py 73.07% 11 Missing and 10 partials ⚠️
src/hdmf/container.py 66.66% 18 Missing ⚠️
src/hdmf/typing/migrate.py 0.00% 16 Missing ⚠️
src/hdmf/validate/errors.py 63.33% 11 Missing ⚠️
src/hdmf/backends/hdf5/h5_utils.py 58.33% 10 Missing ⚠️
src/hdmf/backends/hdf5/h5tools.py 84.78% 7 Missing ⚠️
src/hdmf/spec/spec.py 92.78% 7 Missing ⚠️
src/hdmf/term_set.py 68.75% 4 Missing and 1 partial ⚠️
src/hdmf/build/builders.py 86.66% 2 Missing and 2 partials ⚠️
... and 10 more

❗ There is a different number of reports uploaded between BASE (7cb9cec) and HEAD (a255543). Click for more details.

HEAD has 4 uploads less than BASE
Flag BASE (7cb9cec) HEAD (a255543)
5 1
Additional details and impacted files
@@                   Coverage Diff                    @@
##           typing-compat-layer    #1527       +/-   ##
========================================================
- Coverage                91.79%   38.09%   -53.70%     
========================================================
  Files                       50       51        +1     
  Lines                    11027    10952       -75     
  Branches                  2302     2337       +35     
========================================================
- Hits                     10122     4172     -5950     
- Misses                     558     6365     +5807     
- Partials                   347      415       +68     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bendichter
bendichter force-pushed the typing-phase3-core branch from cae43d7 to eff3bae Compare July 4, 2026 16:23
@bendichter bendichter changed the title Migrate common table stack off docval (Phase 3 batch 1 of #1129) Migrate common table stack + spec subsystem off docval (Phase 3 of #1129) Jul 4, 2026
bendichter and others added 2 commits July 4, 2026 12:34
Migrates all @DocVal sites in common/table.py (VectorData, VectorIndex,
ElementIdentifiers, DynamicTable, DynamicTableRegion, EnumData,
MeaningsTable), common/alignedtable.py, and common/multi.py to
type-hinted signatures with @validated. The three AlignedDynamicTable
methods that splice parent specs via @DocVal(*get_docval(...))
intentionally stay on @DocVal and now consume synthesized specs from
the migrated DynamicTable parents.

Hand-work beyond the tool: mutable list() defaults -> None-guards
(VectorData.data and friends), super().__init__(**kwargs) -> explicit
keywords, and the allow_extra kwargs-meaning change (docval's kwargs
held ALL parsed args; the real **kwargs holds only extras) in
add_column, from_dataframe, and MeaningsTable.add_row. The migrate tool
now flags kwargs uses in allow_extra bodies with a dedicated warning.

Verified: full hdmf suite green (1985); full pynwb dev suite green
(804 tests + 6581 subtests) against this branch — DynamicTable and
VectorData are pynwb's most-subclassed classes and its get_docval
splices now run entirely on synthesized specs for these types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Migrates all @DocVal sites in spec/spec.py, spec/namespace.py,
spec/catalog.py, and spec/write.py to type-hinted signatures with
@validated. The shared module-level spec-argument lists (_attr_args,
_group_args, _dataset_args, ...) are inlined into signatures and
removed; the migrate tool learned to resolve such module-level literal
list splices automatically (36/39 spec.py sites auto-converted).

Hand-work: the three _target_type_key sites (RefSpec, LinkSpec,
GroupSpec.add_link), explicit super()/constructor forwarding in
DatasetSpec/GroupSpec and the deprecated add_* wrappers, list()
default guards, and within-module forward refs as whole-string
annotations ("BaseStorageSpec | None") instead of TypeName, which
static checkers can resolve.

Behavior note: missing/extra-argument errors on migrated functions use
Python's native message wording; one hdmf test updated accordingly.
Runtime spec introspection (Spec.build_spec, build_namespace) is
unchanged — it reads get_docval(cls.__init__), served by the shim.

Verified: full hdmf suite green (1985); full pynwb dev suite green
(804 + 6581 subtests) — pynwb/spec.py builds its NWB spec classes by
introspecting these constructors via get_docval.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bendichter
bendichter force-pushed the typing-phase3-core branch from 8c866c0 to 40a1d5f Compare July 4, 2026 16:34
bendichter and others added 2 commits July 4, 2026 12:50
Migrates the 11 static @DocVal sites in container.py (AbstractContainer,
Container, Data, DataRegion, Table.__init__ and methods) to type-hinted
signatures with @validated. The 8 dynamically composed decorators (the
MultiContainerInterface __make_* factories and the Row/Table row-class
machinery, which compute docs/types/func_name at class-generation time)
intentionally stay on @DocVal and are annotated as such; they migrate
with docval removal (#1129 Phase 4).

The AbstractContainer metaclass field-docs machinery
(get_docval(cls.__init__) at class definition) now reads synthesized
specs for migrated classes.

Verified: full hdmf suite green (1985); full pynwb dev suite green
(804 + 6581 subtests) — every pynwb container class roots its
get_docval splice chain in these constructors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… 4-5)

Migrates all remaining static @DocVal sites: build/builders.py,
build/manager.py, build/objectmapper.py, build/errors.py, backends/io.py,
backends/utils.py, backends/hdf5/h5_utils.py (incl. H5DataIO),
backends/hdf5/h5tools.py (incl. HDF5IO write/export/export_io),
common/__init__.py, common/io/table.py, validate/errors.py, and
term_set.py.

Remaining @DocVal uses are exclusively: the spec-splicing composition
sites (@DocVal(*get_docval(...)), annotated as intentional, consuming
synthesized specs) and build/classgenerator.py (generates constructors
for schema-derived classes; migrates in Phase 4).

Notable hand-work: H5DataIO.__init__'s kwargs-partitioning body rebuilt
around named parameters; HDF5IO.export/export_io given real signatures
(the class-level _export_args tuple is gone); write/write_builder/
write_group forwarding dicts rebuilt from named params. Reverted the
whole-string forward-ref annotations introduced in the spec batch back
to TypeName[...] — string annotations naming later-defined classes do
not resolve at decoration time; hdmf.typing now warns if a compound
string annotation cannot be resolved instead of silently never matching.

Verified: full hdmf suite green (1985); docs build zero-warning; full
pynwb dev suite green (804 + 6581 subtests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bendichter bendichter changed the title Migrate common table stack + spec subsystem off docval (Phase 3 of #1129) Migrate all runtime modules off docval (Phase 3 of #1129) Jul 4, 2026
Adds hdmf.typing.signature_function, a runtime builder that converts
docval-style argument spec dicts into functions with real type-hinted
signatures (exec-built like dataclasses), Google-style docstrings, and
@validated runtime checking. Mutable defaults keep docval's per-call
deepcopy semantics; non-identifier argument names (exercised by tests)
fall back to legacy @DocVal.

Used everywhere functions are composed at runtime:
- build/classgenerator.py: schema-generated __init__ (both
  CustomClassGenerator and MCIClassGenerator) — get_class() classes now
  show real constructor signatures in IDEs and help()
- container.py MultiContainerInterface __make_get/__make_getitem/
  __make_add/__make_create/__make_constructor
- container.py Row/Table dynamic __init__ and add_row

With this, the only remaining @DocVal decorators in hdmf are the eight
@DocVal(*get_docval(...)) splice sites, which migrate with docval
removal. Also adds the py.typed marker.

Test updates: docval's synthetic signature line is gone from generated
docstrings (real signatures replace it); 'bool' string vs bool class in
one generated spec (validates identically); native missing-argument
message wording.

Verified: full hdmf suite green (1994); docs zero-warning; full pynwb
dev suite green (804 + 6581 subtests) — pynwb's extension classes are
generated through this exact machinery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bendichter bendichter changed the title Migrate all runtime modules off docval (Phase 3 of #1129) Migrate all modules off docval + real signatures for generated classes (Phases 3-4 of #1129) Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant