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.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.

For example: - Last release: v5.0.1, current: 5.0.2 → minor bump allowed - Last release: v5.0.1, current: 5.1.0 → minor bump NOT allowed (bumped) - Last release: v5.0.1, current: 6.0.0 → major bump NOT allowed (bumped)

Note

When tags are not available (e.g., due to race conditions between workflows), this function falls back to parsing version from recent commit messages.

Parameters:

part (Literal['minor', 'major']) – The version part to check (minor or major).

Return type:

bool

Returns:

True if the bump should proceed, False if it should be skipped.

class repomatic.metadata.project.ProjectMetadata[source]

Bases: object

What pyproject.toml and the Sphinx configuration declare.

A concern mixin of Metadata: never instantiated on its own, and reads sibling concerns through self.

pyproject_path: Path
sphinx_conf_path: Path
property is_python_project: bool[source]

Returns True if repository is a Python project.

Presence of a pyproject.toml file that respects the standards is enough to consider the project as a Python one. Delegates to repomatic.pyproject.is_python_project() so the detection rule has a single source of truth.

property is_python_package: bool[source]

Returns True if 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 to repomatic.pyproject.is_python_package(), the same predicate PACKAGE_ONLY resolves against, so the release lane and the checks that police it agree on who publishes.

Prefer this over the truthiness of package_name when gating anything about publishing. package_name only reports what [project] name says, which a virtual project still declares.

property pyproject_toml: dict[str, Any][source]

Returns the raw parsed content of pyproject.toml.

Returns an empty dict if the file does not exist.

property pyproject: StandardMetadata | None[source]

Returns metadata stored in the pyproject.toml file.

Returns None if the pyproject.toml does not exists or does not respects the PEP standards.

Warning

Some third-party apps have their configuration saved into pyproject.toml file, but that does not means the project is a Python one. For that, the pyproject.toml needs to respect the PEPs.

property config: Config[source]

Returns the [tool.repomatic] section from pyproject.toml.

Merges user configuration with defaults from Config.

property nuitka_entry_points: list[str][source]

Entry points selected for Nuitka binary compilation.

Reads [tool.repomatic].nuitka.entry-points from pyproject.toml. When empty (the default), deduplicates by callable target: keeps the first entry point for each unique module:callable pair, so alias entry points (like both mpm and meta-package-manager pointing to the same function) don’t produce duplicate binaries. Unrecognized CLI IDs are logged as warnings and discarded.

property dev_targets: set[str][source]

Nuitka build targets compiled on ordinary (non-release) pushes.

Reads [tool.repomatic].nuitka.dev-targets from pyproject.toml. An empty list disables dev builds entirely. See nuitka_dev_targets for the default and the canary rationale.

Unrecognized target names are logged as warnings and discarded.

property unstable_targets: set[str][source]

Nuitka build targets allowed to fail without blocking the release.

Reads [tool.repomatic].nuitka.unstable-targets from pyproject.toml. Defaults to an empty set.

Unrecognized target names are logged as warnings and discarded.

property package_name: str | None[source]

Returns package name as published on PyPI.

property project_description: str | None[source]

Returns project description from pyproject.toml.

property script_entries: list[tuple[str, str, str]][source]

Returns a list of tuples containing the script name, its module and callable.

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/script or . 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 descriptive ValueError instead of crashing with an unpacking error.

property requires_python_floor: tuple[int, int] | None[source]

The project’s requires-python lower bound, as (major, minor).

The one reduction of the specifier to a floor, shared by mypy_params and the lint-repo Python-consistency check so the two cannot disagree on which operators count as a bound.

Returns:

The first >=/> bound’s release pair, or None when the project declares no requires-python or no lower bound.

property mypy_params: list[str] | None[source]

Generates mypy parameters.

Mypy needs to be fed with this parameter: --python-version 3.x.

Extracts the minimum Python version from the project’s requires-python specifier. Only takes major.minor into account.

static get_current_version()[source]

Returns the current version as managed by bump-my-version.

Same as calling the CLI:

$ bump-my-version show current_version

Reads current_version from the first TOML file found in the current working directory: .bumpversion.toml (top-level table) or pyproject.toml ([tool.bumpversion]).

Return type:

str | None

property current_version: str | None[source]

Returns the current version.

Current version is fetched from the bump-my-version configuration file.

During a release, two commits are bundled into a single push event:

  1. [changelog] Release vX.Y.Z — freezes the version to the release number

  2. [changelog] Post-release bump vX.Y.Z vX.Y.Z — bumps to the next dev version

In this situation, the current version returned is the one from the most recent commit (the post-release bump), which represents the next development version. Use released_version to get the version from the release commit.

property released_version: str | None[source]

Returns the version of the release commit.

During a release push event, this extracts the version from the [changelog] Release vX.Y.Z commit, which is distinct from current_version (the post-release bump version). This is used for tagging, PyPI publishing, and GitHub release creation.

Returns None if no release commit is found in the current event.

property is_sphinx: bool[source]

Returns True if the Sphinx config file is present.

property minor_bump_allowed: bool[source]

Check if a minor version bump is allowed.

This prevents double version increments within a development cycle.

property major_bump_allowed: bool[source]

Check if a major version bump is allowed.

This prevents double version increments within a development cycle.

property active_autodoc: bool[source]

Returns True if Sphinx autodoc is active.

property uses_myst: bool[source]

Returns True if MyST-Parser is active in Sphinx.