Repository navigation
refactor!: rename the import package to targetprocess_py - #18
Conversation
BREAKING CHANGE: the import package is now targetprocess_py. Replace every `import targetprocess` / `from targetprocess…` with `targetprocess_py`. The distribution stays `targetprocess-py` on PyPI, and the repository keeps its name. The import name did not match the distribution name, and a tool that infers a dependency from a top-level import therefore asked PyPI for a package called `targetprocess`, which does not exist. Windmill is the case in hand: a script importing this library had to carry inline metadata purely to override that bad inference, and the same trap waits for every consumer that resolves imports this way. `targetprocess_py` is the PEP 503 normalisation of `targetprocess-py`, so the inference now resolves the real distribution with no override. `src/targetprocess/` moves to `src/targetprocess_py/` and every module reference follows it: the imports, the `:mod:`/`:class:`/`:func:` docstring references, the `__module__` prefix test that discovers the entity tree, the coverage target, the built-wheel smoke import, and the package paths in pyproject.toml, .coderabbit.yaml and CODEOWNERS' commented example. Four spellings of the token are deliberately unchanged, because they do not name the import package: - the distribution name `targetprocess-py`, everywhere it appears; - the credential directory `~/.config/targetprocess/.env`, a canonical on-disk path shared with tooling outside this repository, whose rename would break credential resolution for every consumer of it while passing every test here; - the vendor's own domains and documentation URLs; - prose and identifiers naming the product rather than this package: the PyPI search keyword, the correlation-ID ContextVar label, and two test names that read against TargetProcess's own behaviour and error family. No compatibility shim. A `targetprocess` module re-exporting the new package would keep alive exactly the import that cannot be resolved, which is the defect this change removes. The recorded cassettes carry no occurrence of the token, so none needed changing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bump `__version__` to 0.3.0 and cut the CHANGELOG section for it. The 0.3.0 heading absorbs the entries that were sitting under `[Unreleased]` — the ignored-filter guard's four further collections and the eight dropped read-model range bounds — and adds the import-package rename above them with its migration line. A minor bump retires the previous minor, so `SECURITY.md`'s supported-versions table moves with it, as CONTRIBUTING's release procedure requires. The development-status classifier stays `4 - Beta`: 0.3.0 is still a beta release and the public surface may still change between 0.x minors. The logger-namespace rename lands in the commit after this one, together with its own CHANGELOG entry, so that reverting it takes the entry with it. This commit is therefore deliberately not the branch tip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BREAKING CHANGE: the library's logger namespace is now `targetprocess_py`.
Logging configuration that names `targetprocess` — a handler, a level, a filter,
a `dictConfig` entry — stops matching and goes silent; rename it to
`targetprocess_py`.
Python's convention is that a library's root logger carries its top-level package
name, which is what `logging.getLogger(__name__)` yields. After the package
rename that name is `targetprocess_py`, so `getLogger("targetprocess")` named
something no module in this distribution produces: a consumer configuring the
logger they would derive from their own import got nothing, while the library
logged to a namespace they never referenced.
The failure mode differs from the import rename, which is why it is called out
separately and carries its own CHANGELOG entry: an import that no longer resolves
raises at startup, while logging configuration that no longer matches simply stops
producing output, with nothing raised and nothing logged to say so.
`logging.getLogger("targetprocess")` and the child construction in `get_logger()`
move, together with the docstrings that tell a consumer which logger to attach a
handler to, the normative description in SPEC.md, and the record names the
observability tests assert on.
This commit is deliberately last, and carries the CHANGELOG entry for its own
change rather than leaving it in the release commit: the namespace rename is a
judgement separable from the package rename, and a single `git revert` of this
commit must take its documentation with it. A revert that left the entry standing
would tell a consumer to rename logging configuration that had not moved, which
is the silent-logging failure the entry itself warns about.
The correlation-ID ContextVar's label is left as it is. It is module-private and
absent from `__all__`, ContextVar lookup is by object identity rather than by
name, and the emitted log field is `request_id`, so the string surfaces only in a
`repr` or a debugger and names nothing a consumer can configure.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedToo many files! This PR contains 171 files, which is 71 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Repository: man8/targetprocess-py/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (171)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai full review |
|
Summary
Renames the import package from
targetprocesstotargetprocess_py, the PEP 503normalisation of the distribution name, and ships it as 0.3.0. The distribution
stays
targetprocess-pyon PyPI and the repository keeps its name; only the importname changes.
The import name did not match the distribution name, so every tool that infers a
dependency from a top-level import asked PyPI for a package called
targetprocess,which does not exist. Such a consumer needed a hand-written metadata override to
install this library at all. With the import spelt
targetprocess_pythe inferenceresolves the real distribution unaided.
There is no compatibility shim, deliberately: a
targetprocessmodulere-exporting the new package would keep alive exactly the import that cannot be
resolved, and would let adopters postpone the migration indefinitely. The library is
0.x, where a breaking change is acceptable, and this is much cheaper now than after
1.0.0.
No GitHub issue; this change is tracked outside this repository.
Changes
Three commits. The order is deliberate — see The logger rename is separable below.
1.
refactor!: rename the import package to targetprocess_pysrc/targetprocess/→src/targetprocess_py/(56 files,py.typedincluded).import targetprocess/from targetprocess…lines across 152 files, the:mod:/:class:/:func:docstring references, the coverage target in CI and
CONTRIBUTING.md, thebuilt-wheel smoke import in CI, and the package paths in
pyproject.toml(hatch version path, wheel packages, the
N802per-file ignore),.coderabbit.yaml's path instruction andCODEOWNERS' commented example.tests/test_entity_extras.pydiscovers the entity tree bysubclass.__module__.startswith("targetprocess."), a runtime string testagainst the package name rather than an import; and the
N802per-file ignorein
pyproject.toml, which is the reference a sweep would most plausibly miss.Both are covered by the mutation tests below.
2.
chore(release): prepare 0.3.0__version__0.2.1 → 0.3.0; the## [0.3.0] - 2026-09-20heading absorbs theentries that were under
[Unreleased]and adds the import-rename entry above them;link references updated;
SECURITY.md's supported-versions table moves with theminor, as
CONTRIBUTING.md§ Releasing requires, and to the state that file's ownpolicy prescribes (0.3.x supported, 0.2.x not).
3.
refactor!: rename the logger namespace to targetprocess_pyPython's convention is that a library's root logger carries its top-level package
name — what
logging.getLogger(__name__)yields. After commit 1 that name istargetprocess_py, sogetLogger("targetprocess")named something no module inthis distribution produces: a consumer configuring the logger they would derive
from their own import got nothing, while the library logged to a namespace they
never referenced.
It carries its own CHANGELOG entry, with its own migration line, because it fails
differently from the import rename: an import that no longer resolves raises at
startup, while logging configuration that no longer matches simply stops producing
output, with nothing raised and nothing logged to say so.
The logger rename is separable — and the CHANGELOG entry goes with it
The namespace rename is a judgement that can be dropped without touching the
package rename, so it must be revertable in one command including its
documentation. A revert that left the entry standing would tell a consumer to
rename logging configuration that had not moved — the silent-logging failure the
entry itself warns about, and nothing in this repository would detect it.
That is why the logger commit is last and carries the CHANGELOG entry for its
own change. Verified rather than asserted:
The reverted tree keeps the import-rename entry and
__version__ = "0.3.0", losesthe logger entry entirely, and is green:
ruff checkclean,ruff format --checkclean,
mypy --strict srcclean, 1450 passed, 99.23%.Two other commit orders were tried and rejected: with the logger commit second and
its entry under
[Unreleased], the release commit relocates those lines and therevert conflicts; with the entry in the release commit, the revert is clean but
silently leaves the entry behind.
Deliberately unchanged
The token appears in five distinct roles in this tree and only two of them are the
package. Left alone:
targetprocess-py, everywhere;~/.config/targetprocess/.env— a canonical on-diskpath shared with tooling outside this repository, whose rename would break
credential resolution for every consumer of it while passing every test here
(9 occurrences, verified byte-identical to the base revision);
not merely cosmetic:
targetprocess.comappears inside the cassette-sanitiserregexes (
tests/integration/conftest.py:126,tests/test_cassette_guard.py:121), so renaming it would quietly weakensanitisation of recorded traffic;
search keyword (the term a user actually types to find this library), the
correlation-ID
ContextVarlabel, and two test names that read againstTargetProcess's own hierarchy and error family;
CHANGELOG.md's historical entry for 0.1.0, which describes what shipped then.A note on the recorded cassettes
The acceptance criteria this change was written against list the cassettes among
the files whose imports need updating. They carry none — a case-insensitive
search over all 23 files under
tests/integration/cassettes/returns nothing, withpositive controls (
tpondemand: 23/23 files;UserStor: 17) confirming the searchdoes read those files, and with
-aand default modes returning identical counts sonothing was skipped as binary. The distribution name a cassette might carry is
unchanged. No cassette was touched, and none needed to be.
Testing
Run against the head commit:
uv run ruff check .uv run ruff format --check .uv run mypy --strict srcuv run pytest -q --cov=targetprocess_py --cov-fail-under=90uv run pre-commit run --all-files --hook-stage pre-commituv run pre-commit run --all-files --hook-stage pre-pushuv build+uvx twine check --strict dist/*A green suite is real evidence here rather than ceremony: a rename that misses one
occurrence fails at import time.
The renames are load-bearing
Four mutation tests, each restoring the actual base-revision value rather than
deleting part of the new code, so each measures the real counterfactual:
per-file-ignorespath →src/targetprocess/_base.pyruff check→ 6N802errors__module__.startswith("targetprocess.")test_all_entity_types_list_is_completefails--cov=targetprocess--cov-fail-under=90tripstargetprocess, tests left newNone of the renamed assertions has been weakened into a tautology.
The built artefacts, read from the artefacts themselves
Neither artefact contains a bare
targetprocess/path;py.typedships insidetargetprocess_py/.The import checks, in a clean virtualenv
The virtualenv was created outside the worktree and outside any directory
containing
src/, only the built wheel was installed into it, and the checks ranfrom an empty directory, so
import targetprocesscould not resolve from theworking directory.
A positive control first, because the negative assertion is the load-bearing
one and an assertion that cannot fail is not evidence. With a throwaway
targetprocess/package in the working directory, the very same interpreterinvocation finds it:
So the check can see a reachable bare
targetprocess. Removing it and running fromthe empty directory:
sys.pathduring those checks was['', <stdlib>, <venv site-packages>]— nothingfrom this repository, and
''(the empty working directory) present, which is whatmakes the negative result meaningful rather than an artefact of an isolated
interpreter.
The public surface is unchanged
__all__carries 107 names both before and after, the two sets identical, andevery one resolves on the package installed from the built wheel. The rename is a
relocation and nothing else.
Context
import targetprocessasimport targetprocess_py(andfrom targetprocess.<module>likewise), and renametargetprocesstotargetprocess_pyin any logging configuration that names this library's logger.git log --followneeds-M10%on two files. 54 of the 56src/files arerecorded as renames.
models.pyandresources/__init__.pyare recorded asdelete+add, because both are almost entirely import lines, so every line changed
and similarity falls below git's default 50% threshold.
git log --followreturns1 commit for each;
git log --follow -M10%returns 2 and 3 respectively. Gitcomputes similarity at read time, so this is not fixable in the commit — it just
needs the flag.
CODEOWNERS:12is a commented-out example of a per-path rule, not a liverule. It was updated anyway: one token, and leaving it would cite a directory
that no longer exists.
4 - Beta— 0.3.0 is still a betarelease and the public surface may still change between 0.x minors.
SPEC.md(maintainer-facing) and the CHANGELOG.README.mdanddocs/USAGE.mdhave no logging section, so a consumer who skims past the CHANGELOG line has no
second chance to discover the silent-failure change. This is pre-existing — there
was nothing to rename — and a follow-up rather than a reason to grow this diff.
targetprocessname is unregistered on PyPI(
/pypi/targetprocess/json→ 404), which is why the bad inference failed ratherthan installing something. That leaves the name available to a third party while
0.2.x consumers' tooling still asks for it. A registration question, separate from
the settled no-shim decision.
to move to
targetprocess_pyand bump their pin; those are tracked separately.Checklist
uv run ruff check .anduv run ruff format --check .passuv run mypy --strict srcpassesuv run pytest -qpasses and coverage stays at or above 90%uv run pre-commit run --all-files --hook-stage pre-commitpassesuv run pre-commit run --all-files --hook-stage pre-pushpassesAPI; every moved docstring is preserved
TODO/FIXME/HACK/XXXmarkers name an issue — none added🤖 Generated with Claude Code