repomatic.metadata.project module¶
Python-project reading of Metadata.
Everything derived from pyproject.toml and the Sphinx configuration:
project identity, entry points, version state, and tool parameters.
- repomatic.metadata.project.MANPAGES_ASSET_SUFFIX: Final[str] = '-manpages'¶
What the package name takes to name the man-page tarball, by default.
- repomatic.metadata.project.MYPY_VERSION_MIN: Final[tuple[int, int]] = (3, 10)¶
Earliest Python dialect the pinned mypy accepts for
--python-version.Floors the value
ProjectMetadata.mypy_paramsderives from the project’srequires-python, which themypyentry ofTOOL_REGISTRYpasses throughcomputed_params. A project declaring an older floor would otherwise hand mypy a version it refuses with exit code2. Mypy’s ownPYTHON3_VERSION_MINholds the value, in mypy/defaults.py.
- class repomatic.metadata.project.BumpBaseline(current, released)[source]¶
Bases:
NamedTupleThe two versions a version-bump gate compares.
Create new instance of BumpBaseline(current, released)
- classmethod resolve()[source]¶
Read both versions from the working directory and its git history.
The latest release comes from the tags first. When none is found, as on a shallow clone or while the release workflow has not pushed its tag yet, it comes from the most recent release commit message.
- Return type:
- Returns:
The baseline, or
Nonewhen either version is unknown: a gate with nothing to compare against allows the bump.
- allows(part)[source]¶
Whether a bump of part would not increment it twice in one cycle.
Last release
5.0.1, current5.0.2: a minor bump is allowed.Last release
5.0.1, current5.1.0: the minor was already bumped.Last release
5.0.1, current6.0.0: the major was already bumped, which blocks both parts.
- repomatic.metadata.project.is_version_bump_allowed(part)[source]¶
Check if a version bump of the specified part is allowed.
This prevents double version increments within a development cycle. A bump is blocked if the version has already been bumped (but not released) since the last tagged release.
BumpBaseline.allows()holds the rule.- Parameters:
part (
Literal['minor','major']) – The version part to check (minorormajor).- Return type:
- Returns:
Trueif the bump should proceed,Falseif it should be skipped.- Raises:
ValueError – When part is not a bumpable part.
- class repomatic.metadata.project.ProjectMetadata[source]¶
Bases:
objectWhat
pyproject.tomland the Sphinx configuration declare.A concern mixin of
Metadata: never instantiated on its own.- pyproject_path = PosixPath('pyproject.toml')¶
The project file every property here reads.
- sphinx_conf_path = PosixPath('docs/conf.py')¶
The Sphinx configuration file.
- property is_python_project: bool[source]¶
Returns
Trueif repository is a Python project.Presence of a
pyproject.tomlfile that respects the standards is enough to consider the project as a Python one. Delegates torepomatic.pyproject.is_python_project()so the detection rule has a single source of truth.
- property is_python_package: bool[source]¶
Returns
Trueif the repository builds a distributable package.Strictly narrower than
is_python_project: a uv virtual project declares a[project]table to carry its dependencies, then opts out of being built with[tool.uv] package = false. Delegates torepomatic.pyproject.is_python_package(), the same predicatePACKAGE_ONLYresolves against, so the release lane and the checks that police it agree on who publishes.Prefer this over the truthiness of
package_namewhen gating anything about publishing.package_nameonly reports what [project] name says, which a virtual project still declares.
- property changelog_has_entries: bool[source]¶
Whether the changelog section of the current version holds an entry.
The
prepare-releasejob ofchangelog.yamlis gated on it: a release cut from an empty section publishes empty release notes, so the release pull request waits until a bullet names what moved, even on a mechanical cycle.Falsewith no changelog atchangelog.location, no current version, or no section for it.
- property pyproject_toml: dict[str, Any][source]¶
Returns the parsed content of
pyproject.toml.The cached document
read_pyproject_toml()shares with every other reader of the file, so treat it as read-only. Empty when the file does not exist or does not parse.
- property pyproject: StandardMetadata | None[source]¶
Returns metadata stored in the
pyproject.tomlfile.Returns
Noneif thepyproject.tomldoes not exists or does not respects the PEP standards.Warning
Some third-party apps have their configuration saved into
pyproject.tomlfile, but that does not means the project is a Python one. For that, thepyproject.tomlneeds to respect the PEPs.
- property config: Config[source]¶
Returns the
[tool.repomatic]section frompyproject.toml.Merges user configuration with defaults from
Config, throughload_repomatic_config(): for the project in the working directory, the configuration the running command published wins over the file.
- property manpages_asset_name: str | None[source]¶
Filename stem of the man-page tarball attached to a release.
[tool.repomatic] manpages.asset-namewhen set,<package-name>-manpagesotherwise.Nonefor a project with neither.
- property script_entries: list[tuple[str, str, str]][source]¶
The
(name, module, callable)tuple of each console script.Results are derived from the script entries of
pyproject.toml. So that:[project.scripts] mdedup = "mail_deduplicate.cli:mdedup" mpm = "meta_package_manager.__main__:main"
Will yields the following list:
( ("mdedup", "mail_deduplicate.cli", "mdedup"), ("mpm", "meta_package_manager.__main__", "main"), ..., )
Each entry is validated against PEP 621 and PyPI conventions:
The script name (the dict key) must be non-empty, contain at least one non-dot character, and match
[A-Za-z0-9._-]+. This mirrors the rule PyPI enforces on uploaded wheels and the check uv-build performs; rejecting names like../escape,nested/scriptor.here keeps them from flowing into the binary file path template{{cli_id}}-{{current_version}}-{{target}}.{{extension}}and from there into shell-quoted artifact names,chmod, and attestation commands in the release workflow.The script value must split on
:into exactly two non-empty parts (module:object). Malformed values raise a descriptiveValueErrorinstead of crashing with an unpacking error.
- property main_cli_script: str | None[source]¶
The first
[project.scripts]entry, the CLI the self-tests drive.- Returns:
The script name, or
Nonewhen the project declares none.
- property import_name: str | None[source]¶
The top-level package that
python -mruns.Read from the module of
main_cli_script, since the CLI lives in that package:mail_deduplicate.cligivesmail_deduplicate. A project with no script falls back to its package name, with each hyphen turned into an underscore.- Returns:
The import name, or
Nonewhen the project has no name.
- property requires_python_floor: tuple[int, int] | None[source]¶
The project’s
requires-pythonlower bound, as(major, minor).The one reduction of the specifier to a floor, shared by
mypy_paramsand thelint-repoPython-consistency check so the two cannot disagree on which operators count as a bound.- Returns:
The first
>=/>bound’s release pair, orNonewhen the project declares norequires-pythonor no lower bound.
- property mypy_params: list[str] | None[source]¶
Generates
mypyparameters.Mypy needs to be fed with this parameter:
--python-version 3.x.Extracts the minimum Python version from the project’s
requires-pythonspecifier. Only takesmajor.minorinto account.
- property builds_sphinx: bool[source]¶
Whether the Docs workflow builds this repository’s Sphinx site.
The build installs the project to run Sphinx, so it needs a Python project as well as a Sphinx configuration.
- sphinx_conf_strings(name)[source]¶
The strings the Sphinx configuration assigns to the variable name.
Reads every top-level assignment to the bare name: a plain or annotated one sets the list, an augmented one (
+=) extends it. An assignment to anything other than the bare name, like a tuple target or a subscript, is passed over, and so is a value that is not a list or tuple literal.
- property sphinx_extensions: frozenset[str][source]¶
The extensions the Sphinx configuration lists, read once.
sphinx_conf_strings()says which assignments it reads.
