python

package
v0.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package python implements omnibump support for Python projects.

It supports both manifest mode (editing pyproject.toml, requirements.txt, setup.cfg, or Pipfile in-place) and venv mode (upgrading packages directly in a staged Python virtualenv).

Build tool detection

Manifest mode auto-detects build tools from the [build-system].build-backend field in pyproject.toml and can be overridden with the --tool flag. Supported build tools:

  • pip / uv — requirements.txt or PEP 621 pyproject.toml
  • poetry — [tool.poetry.dependencies] in pyproject.toml
  • hatch — PEP 621 [project].dependencies via hatchling backend
  • pdm — PEP 621 [project].dependencies; detected by pdm.lock
  • flit — PEP 621 [project].dependencies via flit_core backend
  • setuptools — PEP 621 pyproject.toml, setup.cfg, or setup.py
  • maturin — PEP 621 [project].dependencies for Rust+Python (PyO3) projects; used by polars, pydantic-core, orjson, ruff, and other performance-critical packages
  • scikit-build-core — PEP 621 [project].dependencies for C/C++ extension modules

All PEP 621 backends (hatch, flit, pdm, maturin, scikit-build-core, setuptools) share the same parsing path since they use the standard [project].dependencies array. Only Poetry requires a separate parser for its [tool.poetry.dependencies] section.

Manifest files

Supported manifest file formats, checked in priority order: pyproject.toml, requirements.txt, setup.cfg, setup.py (read-only), Pipfile.

Lockfile handling

For uv and pdm projects, omnibump updates pyproject.toml directly. The user must re-run `uv lock` or `pdm lock` afterwards to regenerate the lockfile from the updated constraints. Lockfile detection (uv.lock, pdm.lock) is used to identify the build tool, but lockfiles themselves are not modified.

Venv mode

Venv mode is designed for application/leaf packages that bundle dependencies in a staged virtualenv. It validates strict == pinning, rejects downgrades, and verifies environment consistency with pip check. It supports both uv pip and standard pip installers.

Both modes integrate with omnibump's language interface for unified dependency version bumping across multiple ecosystems.

Package python implements omnibump support for Python projects. Supports multiple build tools (pip, uv, hatch, poetry, pdm, maturin, scikit-build-core, setuptools) through a unified interface.

Example
package main

import (
	"fmt"

	"github.com/chainguard-dev/omnibump/pkg/languages"
)

func main() {
	// Get the Python language from the registry.
	lang, err := languages.Get("python")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("Language:", lang.Name())
}
Output:
Language: python

Index

Examples

Constants

View Source
const (
	// LanguagePython is the language identifier for Python.
	LanguagePython = "python"

	// UVCommand is the uv package manager command.
	UVCommand = "uv"
	// PipCommand is the pip package manager command.
	PipCommand = "pip"

	// ManifestPyprojectTOML is the pyproject.toml manifest type.
	ManifestPyprojectTOML = "pyproject.toml"
	// ManifestRequirementsTxt is the requirements.txt manifest type.
	ManifestRequirementsTxt = "requirements.txt"
	// ManifestSetupCfg is the setup.cfg manifest type.
	ManifestSetupCfg = "setup.cfg"
	// ManifestSetupPy is the setup.py manifest type.
	ManifestSetupPy = "setup.py"
	// ManifestPipfile is the Pipfile manifest type.
	ManifestPipfile = "Pipfile"
	// ManifestRequirementsPinnedTxt is a pinned variant of requirements.txt
	// used by some projects (e.g. in-toto).
	ManifestRequirementsPinnedTxt = "requirements-pinned.txt"
)

Manifest file type constants.

Variables

View Source
var (
	// ErrManifestNotFound is returned when no Python manifest is found.
	ErrManifestNotFound = errors.New("no Python manifest file found")

	// ErrPackageNotFound is returned when the target package is not in the manifest.
	ErrPackageNotFound = errors.New("package not found in manifest")

	// ErrInvalidVersion is returned when a version string fails validation.
	ErrInvalidVersion = errors.New("invalid version string")

	// ErrVersionResolverUnavailable is returned when no registry can resolve a version.
	ErrVersionResolverUnavailable = errors.New("version resolver unavailable")

	// ErrUnsupportedManifestType is returned for unsupported manifest types.
	ErrUnsupportedManifestType = errors.New("unsupported manifest type")

	// ErrVenvDowngrade is returned when a version downgrade is attempted.
	ErrVenvDowngrade = errors.New("downgrade rejected")

	// ErrVenvEmptyVersion is returned when a version is empty.
	ErrVenvEmptyVersion = errors.New("empty version for package")

	// ErrVenvInvalidPackageName is returned when a package name is invalid (e.g., starts with '-').
	ErrVenvInvalidPackageName = errors.New("invalid package name")

	// ErrVenvInvalidVersionFormat is returned when a version format is invalid.
	ErrVenvInvalidVersionFormat = errors.New("invalid version format")

	// ErrPipInstallFailed is returned when pip install fails.
	ErrPipInstallFailed = errors.New("pip install failed")

	// ErrPipCheckFailed is returned when pip check fails.
	ErrPipCheckFailed = errors.New("pip check failed")

	// ErrSetupPyReadOnly is returned when attempting to modify setup.py.
	ErrSetupPyReadOnly = errors.New("setup.py is read-only: omnibump cannot safely update setup.py; migrate to setup.cfg or pyproject.toml")

	// ErrVersionNotFound is returned when no versions are found in registry.
	ErrVersionNotFound = errors.New("no versions found in registry")

	// ErrInvalidVersionResponse is returned when version response is invalid.
	ErrInvalidVersionResponse = errors.New("invalid version in response")

	// ErrHTTPNotFound is returned for 404 HTTP responses.
	ErrHTTPNotFound = errors.New("not found")

	// ErrUnexpectedHTTPStatus is returned for unexpected HTTP status codes.
	ErrUnexpectedHTTPStatus = errors.New("unexpected HTTP status")

	// ErrInvalidPath is returned when a manifest path is not absolute.
	ErrInvalidPath = errors.New("invalid path")

	// ErrInvalidPathAfterClean is returned when a path is still invalid after filepath.Clean.
	ErrInvalidPathAfterClean = errors.New("invalid path after clean")

	// ErrInvalidManifestFile is returned when the file is not a known manifest type.
	ErrInvalidManifestFile = errors.New("invalid manifest file")
)

Functions

func HasPDMLock

func HasPDMLock(dir string) bool

HasPDMLock returns true when a pdm.lock file exists in dir.

func HasUVLock

func HasUVLock(dir string) bool

HasUVLock returns true when a uv.lock file exists in dir.

func UpdatePipfile

func UpdatePipfile(path, packageName, newVersion string) error

UpdatePipfile updates the version of a named package in a Pipfile. The existing operator is preserved. newVersion is a bare version number.

func UpdatePyprojectDep

func UpdatePyprojectDep(path, packageName, newVersion string) error

UpdatePyprojectDep updates the version of a named dependency in pyproject.toml. It preserves comments and formatting by operating on the raw file text. newVersion should be just the version number (e.g. "2.32.0"), not include an operator. The existing operator is preserved.

func UpdateRequirement

func UpdateRequirement(path, packageName, newVersion string) error

UpdateRequirement updates the version of the named package in a requirements.txt file. The existing version operator is preserved (==, >=, ~=, etc.). newVersion is the bare version number without an operator.

func UpdateSetupCfg

func UpdateSetupCfg(path, packageName, newVersion string) error

UpdateSetupCfg updates the version of a package in the install_requires section of a setup.cfg file. The existing operator is preserved.

Types

type Analyzer

type Analyzer struct{}

Analyzer implements analyzer.Analyzer for Python projects.

func (*Analyzer) Analyze

func (a *Analyzer) Analyze(_ context.Context, projectPath string) (*analyzer.AnalysisResult, error)

Analyze parses all manifest files in projectPath and returns a dependency map.

func (*Analyzer) AnalyzeRemote

func (a *Analyzer) AnalyzeRemote(_ context.Context, files map[string][]byte) (*analyzer.RemoteAnalysisResult, error)

AnalyzeRemote analyzes manifest files provided as raw bytes. files is a map of filename to content (e.g. "pyproject.toml" -> bytes).

func (*Analyzer) RecommendStrategy

func (a *Analyzer) RecommendStrategy(_ context.Context, _ *analyzer.AnalysisResult, deps []analyzer.Dependency) (*analyzer.Strategy, error)

RecommendStrategy always recommends direct updates for Python deps. Python doesn't have a "property" abstraction like Maven.

type BuildTool

type BuildTool string

BuildTool identifies the Python build system in use.

const (
	// BuildToolPip indicates the pip build tool.
	BuildToolPip BuildTool = "pip"
	// BuildToolUV indicates the uv build tool.
	BuildToolUV BuildTool = "uv"
	// BuildToolHatch indicates the hatch build tool.
	BuildToolHatch BuildTool = "hatch"
	// BuildToolPoetry indicates the poetry build tool.
	BuildToolPoetry BuildTool = "poetry"
	// BuildToolPDM indicates the pdm build tool.
	BuildToolPDM BuildTool = "pdm"
	// BuildToolMaturin indicates the maturin build tool.
	BuildToolMaturin BuildTool = "maturin"
	// BuildToolSetuptools indicates the setuptools build tool.
	BuildToolSetuptools BuildTool = "setuptools"
	// BuildToolScikitBuild indicates the scikit-build tool.
	BuildToolScikitBuild BuildTool = "scikit-build"
	// BuildToolScikitBuildCore indicates the scikit-build-core tool.
	BuildToolScikitBuildCore BuildTool = "scikit-build-core"
	// BuildToolFlit indicates the flit build tool.
	// Flit uses PEP 621 [project].dependencies, same as hatch/setuptools.
	BuildToolFlit BuildTool = "flit"
	// BuildToolUnknown indicates an unknown build tool.
	BuildToolUnknown BuildTool = "unknown"
)

func DetectBuildToolFromBytes

func DetectBuildToolFromBytes(data []byte) (BuildTool, error)

DetectBuildToolFromBytes reads [build-system].build-backend from raw pyproject.toml bytes.

func DetectBuildToolFromPyproject

func DetectBuildToolFromPyproject(path string) (BuildTool, error)

DetectBuildToolFromPyproject reads [build-system].build-backend from a pyproject.toml file on disk.

type ManifestInfo

type ManifestInfo struct {
	// Path is the absolute path to the manifest file.
	Path string
	// Type is the manifest filename (e.g. "pyproject.toml", "requirements.txt").
	Type string
	// BuildTool is the detected build backend.
	BuildTool BuildTool
}

ManifestInfo describes a detected Python manifest file.

func DetectManifest

func DetectManifest(dir string) (*ManifestInfo, error)

DetectManifest returns the highest-priority manifest file found in dir. The returned ManifestInfo includes the build tool inferred from the file.

func DetectManifestWithHint

func DetectManifestWithHint(dir, toolHint string) (*ManifestInfo, error)

DetectManifestWithHint returns a manifest file with optional tool preference. If toolHint is non-empty, it reorders the priority to check the preferred manifest for that tool first, then falls back to the standard order. toolHint examples: "pip" → requirements.txt, "poetry" → pyproject.toml, etc.

type Python

type Python struct{}

Python implements the Language interface for Python projects. It auto-detects the build tool and delegates updates to the appropriate handler.

func (*Python) Detect

func (p *Python) Detect(_ context.Context, dir string) (bool, error)

Detect checks whether a Python manifest file exists in dir.

Example
package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"github.com/chainguard-dev/omnibump/pkg/languages/python"
)

func main() {
	// Create a temporary directory with a pyproject.toml to simulate a Python project.
	dir, err := os.MkdirTemp("", "python-example-*")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	defer func() { _ = os.RemoveAll(dir) }()

	pyproject := filepath.Join(dir, "pyproject.toml")
	if err := os.WriteFile(pyproject, []byte("[project]\nname = \"example\"\ndependencies = [\"requests>=2.28.0\"]\n"), 0o644); err != nil {
		fmt.Println("error:", err)
		return
	}

	p := &python.Python{}
	detected, err := p.Detect(context.Background(), dir)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("Detected:", detected)
}
Output:
Detected: true

func (*Python) GetManifestFiles

func (p *Python) GetManifestFiles() []string

GetManifestFiles returns all Python manifest filenames omnibump can process.

Example
package main

import (
	"fmt"

	"github.com/chainguard-dev/omnibump/pkg/languages/python"
)

func main() {
	p := &python.Python{}
	files := p.GetManifestFiles()
	for _, f := range files {
		fmt.Println(f)
	}
}
Output:
pyproject.toml
requirements.txt
setup.cfg
setup.py
Pipfile

func (*Python) Name

func (p *Python) Name() string

Name returns the language identifier.

func (*Python) SupportsAnalysis

func (p *Python) SupportsAnalysis() bool

SupportsAnalysis returns true since Python has full analysis capabilities.

func (*Python) Update

func (p *Python) Update(ctx context.Context, cfg *languages.UpdateConfig) error

Update performs dependency version updates on a Python project. For each dependency in cfg.Dependencies, it locates the highest-priority manifest and updates the version in-place. If Options["venv"] is set, uses venv mode (uv/pip install into a staged venv). Otherwise uses manifest mode (edit pyproject.toml, requirements.txt, etc. in-place).

func (*Python) Validate

func (p *Python) Validate(ctx context.Context, cfg *languages.UpdateConfig) error

Validate checks that each dependency was updated to the expected version. If Options["venv"] is set, validates versions in the venv. Otherwise validates versions in the manifest file.

type VersionResolver

type VersionResolver struct {
	// contains filtered or unexported fields
}

VersionResolver resolves Python package versions. It checks the Chainguard GAR-backed registry first, then falls back to PyPI.

func NewVersionResolver

func NewVersionResolver() *VersionResolver

NewVersionResolver creates a VersionResolver from environment variables.

func (*VersionResolver) GetLatestVersion

func (r *VersionResolver) GetLatestVersion(ctx context.Context, pkg string) (string, error)

GetLatestVersion returns the latest available version of a Python package. Checks the Chainguard registry first; falls back to PyPI.

func (*VersionResolver) VersionExists

func (r *VersionResolver) VersionExists(ctx context.Context, pkg, version string) (bool, error)

VersionExists checks whether a specific version of a package is available.

type VersionSpec

type VersionSpec struct {
	// Package is the normalized package name.
	Package string
	// Specifier is the version operator(s), e.g. ">=", "==", "~=", "^".
	Specifier string
	// Version is the version string without the operator.
	Version string
	// RawLine is the original unparsed line from the manifest.
	RawLine string
}

VersionSpec represents a single parsed dependency entry.

func ParsePipfile

func ParsePipfile(data []byte) ([]VersionSpec, error)

ParsePipfile parses [packages] and [dev-packages] from a Pipfile.

func ParsePyprojectDeps

func ParsePyprojectDeps(data []byte, buildTool BuildTool) ([]VersionSpec, error)

ParsePyprojectDeps parses dependencies from pyproject.toml content. For Poetry projects, it reads [tool.poetry.dependencies]. For all others (PEP 621), it reads [project].dependencies plus [project.optional-dependencies] and [dependency-groups] (PEP 735). Optional and group dependencies are included in the result with their source annotated in RawLine for informational purposes.

func ParseRequirements

func ParseRequirements(data []byte) []VersionSpec

ParseRequirements parses a requirements.txt byte slice and returns dependency specs. Comment lines, blank lines, and option flags (-r, -c, -e, -i, --index-url) are skipped.

func ParseSetupCfg

func ParseSetupCfg(data []byte) []VersionSpec

ParseSetupCfg parses install_requires from a setup.cfg file.

func ParseSetupPy

func ParseSetupPy(data []byte) []VersionSpec

ParseSetupPy extracts install_requires entries from setup.py using regex. This handles the common pattern: install_requires=["pkg>=1.0", ...] or install_requires=[ ... ] across multiple lines.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL