Skip to content

Add py.typed marker to the published distribution (PEP 561) #7

Description

@S2thend

Add py.typed marker to the published distribution (PEP 561)

Problem

loopgraph ships type hints throughout its public API (verified by browsing
loopgraph/persistence/snapshot.py etc.), but the PyPI distribution does
not include a py.typed marker file
at the package root.

Per PEP 561, type checkers (mypy, pyright, pyre) only honor inline type
annotations from a third-party package if either:

  1. The package contains a py.typed file at the top level, AND that file
    is shipped in the published wheel; or
  2. Type stubs are provided in a separate loopgraph-stubs distribution.

Without that marker, type checkers treat every member of loopgraph as
Any. Downstream consumers using strict mode (mypy's strict = true,
pyright's strict, etc.) then get spurious errors any time they touch
loopgraph types.

Concrete consequence we hit

A downstream project subclasses loopgraph.persistence.SnapshotStore
(a typing.Protocol):

from loopgraph.persistence import SnapshotStore

class MyStore(SnapshotStore):
    ...

Under mypy strict (which enables disallow_subclassing_any = True),
this fires:

error: Class cannot subclass "SnapshotStore" (has type "Any")  [misc]

The fix on the consumer side is one of:
- Add # type: ignore[misc] — works locally but CI (running mypy under a
different package-resolution path) then flags it as [unused-ignore].
Tug-of-war.
- Relax disallow_subclassing_any = false for the importing packageloses strict coverage for unrelated subclasses.
- (Best, but not in our control:) loopgraph publishes py.typed.

We've shipped the second workaround for now. We'd love to roll it back
once this issue lands.

Verificationwhat's missing in the wheel

A current wheel inspection:

pip download loopgraph --no-deps -d /tmp/lg-wheel
unzip -l /tmp/lg-wheel/loopgraph-*.whl | grep py.typed
# (no output)

Compare with e.g. requests, which ships requests/py.typed and is
properly typed downstream.

FixPEP 561 distribution config

Three pieces, all in pyproject.toml (or setup.cfg if using setuptools
declarative):

1. Create the marker at loopgraph/py.typedempty file is fine.
(Already exists in the source tree per find . -name py.typed.)
2. Ship it in the wheelfor setuptools-based packaging, add to
pyproject.toml:

[tool.setuptools.package-data]
loopgraph = ["py.typed"]

2. Or if using find: layout with setup.cfg:

[options]
include_package_data = True

[options.package_data]
loopgraph = py.typed

2. For Poetry / Hatch / flit, the equivalent is "include py.typed in
the package payload."
3. Verify in a clean build:

python -m build --wheel
unzip -l dist/loopgraph-*.whl | grep py.typed
# loopgraph/py.typed

Why this is one-line-of-config

The source tree already has the marker (loopgraph/py.typed exists per
the upstream repo). The wheel just doesn't pull it in because
include_package_data defaults differently across build backends. Adding
the explicit package-data entry is the canonical fix.

Optional follow-ups (not blocking)

- Add a CI step that does python -m build --wheel && unzip -l ... | grep py.typed so the marker can't quietly disappear from a future release.
- Consider running mypy --strict against a tiny downstream-style
subclass test in CIcatches regressions in inline-annotation
coverage too.

Version where the fix should land

Any minor release. Downstream pinning to a fixed minor is fine; we just
need to bump our floor when the fix lands.

---

Adjust the maintainer-tone / issue tracker formatting to taste. If their build backend is Hatch or Poetry rather than setuptools, the `package-data`
snippet swaps outquick check of their `pyproject.toml` `[build-system]` block before posting saves a follow-up comment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions