Skip to content

fix(corekit): export only the sentinel objects, not their types #911

Description

@JarryShaw

Describe the bug

The three sentinel types are exported alongside their objects, against the maintainer's ruling that only the objects should be. Measured on origin/main:

pcapkit.corekit.module.__all__         ['NULL', 'NullType']          <- type exported
pcapkit.corekit.enum.__all__           ['NO_DEFAULT', 'NoDefaultType'] <- type exported
pcapkit.corekit.fields.field.__all__   []                            <- NEITHER exported

The ruling, from #719:

we should ONLY export the objects (like NULL) to __all__, and leave the types (like NullType) out.

Definitions, for reference: NullType at pcapkit/corekit/module.py:31 with NULL at :154; NoDefaultType at pcapkit/corekit/enum.py:104 with NO_DEFAULT at :265; NoValueType at pcapkit/corekit/fields/field.py:27 with NoValue at :36.

Expected behavior

Three edits, and the third is the opposite direction from the other two — worth stating because "remove the types" is only two-thirds of it:

  1. pcapkit/corekit/module.py — remove 'NullType' from __all__.
  2. pcapkit/corekit/enum.py — remove 'NoDefaultType' from __all__.
  3. pcapkit/corekit/fields/field.py — NoValue is not exported at all. The ruling says export the objects, so either it should be added, or it is deliberately internal and the ruling does not reach it. That needs deciding rather than assuming; see below.

This is a breaking change and should be labelled so. Removing a name from __all__ changes what from pcapkit.corekit.module import * yields, which is a public-contract change under this repository's own taxonomy. The classes themselves stay importable by name — only the star-import surface narrows.

One interaction to check before landing

tests/project/test_public_api.py asserts that public packages export everything public they hold, and #904's six red CI legs were caused by exactly that test when a public class was missing from an aggregator. Removing a type from __all__ while the class remains public may trip the same assertion — in which case the test encodes the opposite convention and needs updating alongside, with a comment naming this issue. Establish which before changing either.

Additional context

The maintainer also raised an open design question in the same comment, tracked here rather than lost:

Also considering if we should move all these sentinels to a consolidated module (with multiple sub modules) or a dedicated single file.

There are only three sentinels and they live in the modules that use them — module.py, enum.py, fields/field.py. Consolidating buys one obvious thing (a single place to read the convention, which docs/source/conventions.rst already provides in prose) and costs a re-export shim in each original location, or a breaking import change for any caller. My recommendation is to leave them where they are and revisit at five or more, but it is a judgement call and the needs: decision label is for that half, not for the __all__ fix.

docs/source/conventions.rst documents the <SENTINEL>Type naming rule and the per-sentinel differences in its "Naming a Sentinel" section; whatever is decided here should be reflected there. Note #903 is editing that file right now, so coordinate rather than collide.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)fixPull requests that fix a defect (fix: subject prefix)wipWork in flight - a covering PR is open or an agent is actively on it

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions