Skip to content

chore(api): freeze 1.0 public surface; fix Fill registry-key collision#27

Merged
frederikbeimgraben merged 1 commit into
mainfrom
chore/public-api-1.0
Jun 4, 2026
Merged

chore(api): freeze 1.0 public surface; fix Fill registry-key collision#27
frederikbeimgraben merged 1 commit into
mainfrom
chore/public-api-1.0

Conversation

@frederikbeimgraben
Copy link
Copy Markdown
Owner

1.0 prep: public-API freeze + Fill registry collision fix

Fill registry-key collision — chosen approach

pytex.commands.lengths.Fill (the rubber length \fill) and pytex_tikz.Fill
(the TikZ \fill path command) both registered under the single registry key
"Fill". Effects:

  • import-order-dependent reverse lookup (tex2py / Registry.get),
  • the \iffalse{pytex(...)}\fi eval namespace resolved bare Fill to whichever
    module imported last,
  • importing both logged Duplicate key in registry (overwritten): Fill.

Fix: rename the length factory FillFill_len (option b — rename one
symbol + deprecation alias).

Why not option (a) namespaced keys: the pytex(...) eval namespace is a flat
dict keyed by bare name. Two distinct public callables both named Fill cannot
coexist there unambiguously regardless of the registry-key scheme — qualifying
keys only fixes the duplicate-warning/reverse-lookup, the bare-name eval stays
ambiguous. Renaming is the only fix that makes the lookup deterministic.

Why _len: the package already uses this exact convention — Arraystretch_len
exists precisely because Arraystretch (the tables command) holds that key.
Following the established convention keeps the bare Fill key with the TikZ
command (parallel to Draw), and is self-justifying. A deprecated
pytex.commands.lengths.Fill module-level alias keeps importing and emits a
DeprecationWarning (mirrors the pytex_protocol shim). The TikZ Fill is
untouched.

Public-API freeze

Every package already declares an explicit __all__, and basedpyright validates
the entries (reportUnsupportedDunderAll), so the surface was already disciplined
— no churn was needed. Added a concise Stability section to the README
stating the 1.0 SemVer contract:

  • Public: names a package exports via __all__, plus the registry keys
    reachable from pytex(...) markers (renaming a registered factory is breaking).
  • Internal: leading-underscore names, underscore-prefixed modules
    (pytex_api._policy, pytex_api._compile), anything outside __all__.
  • Deprecated shims (pytex_protocol, the lengths.Fill alias) warn and may be
    removed in the next major.

Tests

  • registry keys for Fill / Fill_len are disjoint and deterministic,
  • a fresh dual import logs no duplicate-key warning (subprocess),
  • the deprecated lengths.Fill alias emits a DeprecationWarning.

Status

  • ruff format --check src tests ✅ · ruff check src tests
  • basedpyright src ✅ 0 errors (0/0 on CI's Python 3.13; locally 1 warning is a
    3.14-only artifact of the existing \fill-3.14 reportUnreachable ignore — not
    touched by this PR)
  • pytest -q ✅ 910 passed, 2 skipped

🤖 Generated with Claude Code

The `\fill` length factory (`pytex.commands.lengths.Fill`) and the TikZ `\fill`
path command (`pytex_tikz.Fill`) both registered under the single registry key
`"Fill"`. The reverse lookup and the `pytex(...)` eval namespace therefore
resolved to whichever module imported last (import-order-dependent), and
importing both logged a "Duplicate key in registry (overwritten): Fill" warning.

Rename the length factory `Fill` -> `Fill_len`, mirroring the existing
`Arraystretch_len` which already dodges the `Arraystretch` table command the
same way. This leaves the bare `Fill` key to the TikZ command (parallel to
`Draw`) and is the least-surprising option: the in-package `_len` convention
already exists, and a flat eval namespace cannot disambiguate two bare `Fill`
names regardless of registry-key scheme, so renaming is the only fix that makes
the lookup deterministic. A deprecated `pytex.commands.lengths.Fill` alias keeps
importing and emits a DeprecationWarning. The TikZ `Fill` is unchanged.

API freeze: every package already declares an explicit `__all__` (pyright
validates the entries). Document the 1.0 stability contract in a README
`Stability` section — the names a package exports plus the registry keys
reachable from `pytex(...)`, with leading-underscore names and underscore-prefixed
modules (`pytex_api._policy`, `pytex_api._compile`) marked internal.

Tests: registry keys are disjoint and deterministic, a fresh dual import logs no
duplicate-key warning, and the deprecated alias warns.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@frederikbeimgraben frederikbeimgraben merged commit 7545651 into main Jun 4, 2026
1 check passed
@frederikbeimgraben frederikbeimgraben deleted the chore/public-api-1.0 branch June 4, 2026 14:45
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