Skip to content

Split csfield into csfield, csfield_noinit, csfield_const and csfield_default#41

Merged
timrid merged 9 commits into
mainfrom
split-csfield-in-multiple-csfields
Jul 20, 2026
Merged

Split csfield into csfield, csfield_noinit, csfield_const and csfield_default#41
timrid merged 9 commits into
mainfrom
split-csfield-in-multiple-csfields

Conversation

@timrid

@timrid timrid commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Problem

Previously, there was only a single csfield method to define dataclass fields for DataclassStruct. This led to ambiguity and potentially incorrect behavior:

  • It wasn't clear whether a field required a constructor parameter, had a fixed default value, should be excluded from the constructor entirely, or represented a constant value.
  • Constructs that are computed dynamically at parse/build time (e.g. Computed, Rebuild, Tell, Const) had to be declared via csfield, even though they can't provide a meaningful value when the instance is created — this resulted in unnecessary or incorrectly typed constructor parameters.

Solution

csfield has been split into four specialized methods that make the intended behavior explicit:

  • csfield – still used for constructs that cannot build from None (the default case, generates a required constructor parameter).
  • csfield_noinit – for fields excluded from the constructor (e.g. Computed, Rebuild, Tell); the value is automatically set to None on construction, so the field type must be T | None.
  • csfield_const – automatically wraps the value in cs.Const and sets it directly, without a constructor parameter:
    signature: bytes = csfield_const(Bytes(3), b"BMP")
  • csfield_default – wraps the value in cs.Default and generates a constructor parameter with a default value (all following fields must be kw_only):
    signature: bytes = csfield_default(Bytes(3), default=b"BMP")

Additional changes

  • Type stubs for Checksum were optimized to correctly reflect whether the respective construct can build from None.

Breaking Changes

  • csfield should now only be used for constructs that cannot build from None. For every other case, use csfield_noinit, csfield_const or csfield_default.

(This pull request replaces #38)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes DataclassStruct dataclass field intent explicit by splitting the former single csfield helper into four dedicated field specifiers (csfield, csfield_noinit, csfield_const, csfield_default), improving runtime behavior clarity and enabling more accurate static type checking (notably with Pyright). It also updates tests, documentation, and stubs to reflect the new APIs and correct build-from-None semantics.

Changes:

  • Introduces new field-specifier helpers and applies @dataclass_transform to improve type-checker understanding of generated dataclass constructors.
  • Expands/adjusts tests (including a new Pyright-focused test module) to validate constructor parameter behavior and validation errors.
  • Updates README/CHANGELOG and improves stubs (notably Checksum) to reflect build(None) capability.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
construct_typed/dataclass_struct.py Splits field creation into four helpers + adds dataclass_transform field specifiers.
construct_typed/__init__.py Exports the new field helpers from the package API surface.
construct-stubs/core.pyi Adjusts Checksum build typing to allow None builds.
tests/test_typed.py Updates/extends runtime tests for the new field behaviors and validation.
tests/test_typed_pyright.py Adds Pyright regression tests for missing/extraneous dataclass constructor parameters.
README.md Updates examples and adds new sections documenting the new helpers.
pyproject.toml Excludes the Pyright-specific test from mypy to avoid intentional error noise.
CHANGELOG.md Documents breaking changes and new helper APIs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread tests/test_typed.py Outdated
Comment thread construct_typed/dataclass_struct.py Outdated
Comment thread construct_typed/dataclass_struct.py Outdated
Comment thread construct_typed/dataclass_struct.py Outdated
Comment thread construct_typed/dataclass_struct.py Outdated
Comment thread construct_typed/dataclass_struct.py
Comment thread tests/test_typed.py
Comment thread construct-stubs/core.pyi
Comment thread tests/test_typed.py
Comment thread pyproject.toml
@timrid
timrid merged commit f2c0d19 into main Jul 20, 2026
22 checks passed
@timrid
timrid deleted the split-csfield-in-multiple-csfields branch July 20, 2026 10:59
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.

3 participants