Skip to main content

Python bindings for rpmrepo_metadata: create and parse RPM repository metadata

Project description

rpmrepo_metadata

PyPI Python

A Python library for reading, writing, and managing RPM repository metadata. Built on a Rust core for performance.

RPM repository metadata consists of several XML files — primary.xml, filelists.xml, other.xml, repomd.xml, updateinfo.xml, and comps.xml — that together describe the packages available in a repository. This library provides high-level APIs for working with all of these metadata types.

Installation

pip install rpmrepo_metadata

Requires Python >= 3.10. Pre-built wheels are available for Linux, macOS, and Windows.

Examples


Read a repository and iterate packages

Use RepositoryReader to stream through packages without loading everything into memory.

from rpmrepo_metadata import RepositoryReader

reader = RepositoryReader("path/to/repo/")

packages = reader.iter_packages()
print(f"Total packages: {packages.total_packages}")

for pkg in packages:
    print(f"{pkg.nevra()} - {pkg.summary}")
    print(f"  Size: {pkg.size_package} bytes")
    print(f"  Checksum: {pkg.checksum}")
    print(f"  Location: {pkg.location_href}")

Read advisories (updateinfo)

from rpmrepo_metadata import RepositoryReader

reader = RepositoryReader("path/to/repo/")

for advisory in reader.iter_advisories():
    print(f"[{advisory.update_type}] {advisory.id} - {advisory.title}")
    print(f"  Severity: {advisory.severity}")
    print(f"  Issued: {advisory.issued_date}")

    for ref in advisory.references:
        print(f"  {ref.reftype}: {ref.href}")

    for collection in advisory.pkglist:
        for pkg in collection.packages:
            print(f"  Package: {pkg.name}-{pkg.version}-{pkg.release}.{pkg.arch}")

Read comps data (groups, categories, environments)

from rpmrepo_metadata import RepositoryReader

reader = RepositoryReader("path/to/repo/")

comps = reader.read_comps()
if comps is not None:
    for group in comps.groups:
        print(f"Group: {group.name} ({group.id})")
        for pkg_req in group.packages:
            print(f"  {pkg_req.reqtype}: {pkg_req.name}")

    for category in comps.categories:
        print(f"Category: {category.name}")
        for group_id in category.group_ids:
            print(f"  Group: {group_id}")

    for env in comps.environments:
        print(f"Environment: {env.name} ({env.id})")
        for group_id in env.group_ids:
            print(f"  Group: {group_id}")
        for option in env.option_ids:
            print(f"  Optional: {option.group_id} (default={option.default})")

Create and populate a Package

from rpmrepo_metadata import Package

pkg = Package()
pkg.name = "my-package"
pkg.epoch = 0
pkg.version = "1.2.3"
pkg.release = "4.el9"
pkg.arch = "x86_64"

pkg.summary = "An example package"
pkg.description = "A longer description of the package"
pkg.url = "https://example.com"
pkg.rpm_license = "MIT"

pkg.checksum = ("sha256", "a" * 64)
pkg.location_href = "Packages/m/my-package-1.2.3-4.el9.x86_64.rpm"

pkg.size_package = 12345
pkg.size_installed = 67890
pkg.time_build = 1700000000

# Dependencies are tuples of (name, flags, epoch, version, release, preinstall)
pkg.requires = [
    ("glibc", "GE", "0", "2.17", "", False),
    ("bash", None, None, None, None, False),
]
pkg.provides = [("my-package", "EQ", "0", "1.2.3", "4.el9", False)]

# Files are tuples of (type, path) where type is None, "dir", or "ghost"
pkg.files = [
    (None, "/usr/bin/my-package"),
    ("dir", "/etc/my-package"),
]

# Changelogs are tuples of (author, timestamp, description)
pkg.changelogs = [
    ("John Doe <john@example.com>", 1700000000, "- Initial release"),
]

print(pkg.nevra())       # "my-package-0:1.2.3-4.el9.x86_64"
print(pkg.pkgid)          # "aaaa...aaaa"

Read an RPM file directly

Extract metadata from .rpm files on disk.

from rpmrepo_metadata import Package, ChecksumType

# Using defaults (SHA-256 checksum, 10 changelog entries)
pkg = Package.from_file("packages/foo-1.0-1.el9.x86_64.rpm")
print(f"{pkg.nevra()} - {len(pkg.files)} files")

# With custom options
pkg = Package.from_file_with_options(
    "packages/foo-1.0-1.el9.x86_64.rpm",
    checksum_type=ChecksumType.Sha512,
    location_href="Packages/f/foo-1.0-1.el9.x86_64.rpm",
    location_base="https://example.com/repo/",
    changelog_limit=5,
)
print(f"Checksum type: {pkg.checksum_type}")  # "sha512"
print(f"Location: {pkg.location_href}")

Write a repository with RepositoryWriter

Stream packages to disk one at a time, keeping memory usage low.

from rpmrepo_metadata import RepositoryWriter, Package

writer = RepositoryWriter("output/repo/", num_pkgs=100)

# Add packages
for rpm_path in rpm_files:
    pkg = Package.from_file(rpm_path)
    writer.add_package(pkg)

# Add advisories
advisory = UpdateRecord()
advisory.id = "EXAMPLE-2024:001"
advisory.title = "Important security fix"
advisory.update_type = "security"
advisory.severity = "Important"
writer.add_advisory(advisory)

# Finalize — writes repomd.xml and closes all files
writer.finish()

Work with Repository in-memory

Repository loads all metadata into memory, convenient for smaller repositories.

from rpmrepo_metadata import Repository

# Load from disk
repo = Repository.load_from_directory("path/to/repo/")

# Write to a new location
repo.write_to_directory("output/repo/")

Parse and compare EVR version strings

from rpmrepo_metadata import EVR

evr1 = EVR.parse("1:2.3.4-5.el9")
evr2 = EVR.parse("2.3.4-6.el9")

print(f"{evr1} vs {evr2}")
print(f"epoch={evr1.epoch}, version={evr1.version}, release={evr1.release}")

# Comparison operators
assert evr1 > evr2  # epoch 1 beats no epoch
assert EVR.parse("1.0-1") == EVR.parse("0:1.0-1")  # epoch 0 is the default
assert EVR.parse("1.0-2") > EVR.parse("1.0-1")

# Destructure into components
epoch, version, release = evr1.components()

Parse comps XML from a string

from rpmrepo_metadata import CompsData

xml = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
<comps>
  <group>
    <id>core</id>
    <name>Core</name>
    <description>Minimal system</description>
    <packagelist>
      <packagereq type="mandatory">bash</packagereq>
      <packagereq type="mandatory">coreutils</packagereq>
    </packagelist>
  </group>
</comps>"""

comps = CompsData.from_xml(xml)
print(f"{len(comps.groups)} groups")

# Serialize back to XML
output_xml = comps.to_xml()

Work with UpdateRecord (advisories)

from rpmrepo_metadata import (
    UpdateRecord, UpdateReference, UpdateCollection,
    UpdateCollectionPackage,
)

record = UpdateRecord()
record.id = "RHSA-2024:1234"
record.title = "Critical: kernel security update"
record.update_type = "security"
record.severity = "Critical"
record.issued_date = "2024-03-15"
record.summary = "An update for kernel is now available."
record.description = "The kernel packages contain the Linux kernel."

# Add a reference
ref = UpdateReference(
    href="https://bugzilla.redhat.com/show_bug.cgi?id=12345",
    id="12345",
    title="kernel vulnerability",
    reftype="bugzilla",
)
record.references = [ref]

# Add affected packages
pkg = UpdateCollectionPackage()
pkg.name = "kernel"
pkg.version = "5.14.0"
pkg.release = "362.24.1.el9_3"
pkg.arch = "x86_64"
pkg.epoch = "0"
pkg.filename = "kernel-5.14.0-362.24.1.el9_3.x86_64.rpm"

collection = UpdateCollection(name="Red Hat Enterprise Linux 9", shortname="RHEL-9")
collection.packages = [pkg]
record.pkglist = [collection]

Rust library

This package is built on a Rust library of the same name, also available on crates.io. See the Rust README and API documentation for Rust usage.

License

Mozilla Public License 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rpmrepo_metadata-0.5.2.tar.gz (86.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rpmrepo_metadata-0.5.2-cp310-abi3-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.10+Windows x86-64

rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_x86_64.whl (6.6 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_aarch64.whl (6.1 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

rpmrepo_metadata-0.5.2-cp310-abi3-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file rpmrepo_metadata-0.5.2.tar.gz.

File metadata

  • Download URL: rpmrepo_metadata-0.5.2.tar.gz
  • Upload date:
  • Size: 86.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for rpmrepo_metadata-0.5.2.tar.gz
Algorithm Hash digest
SHA256 7da7505cac50a960139ec6802dcdf8c0e959272f3c37ea82d5908cae34977121
MD5 9aae77e4a34b70275a4e9034985252f2
BLAKE2b-256 0124a0d6b5647f2657ba4ea797ff1ab783405243d47bff689879a8463c474dd8

See more details on using hashes here.

File details

Details for the file rpmrepo_metadata-0.5.2-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.5.2-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 946ff7f9cbe4c359c25bbf63b47feeecbb1af6ed5d57380bbbc8759feb58ab18
MD5 103c9e660100e0fd1435f6d48f1182a0
BLAKE2b-256 e18aa6e2ce44d3555a2eb89e02d6ce59277bc69764344509ab958479b52d64f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.5.2-cp310-abi3-win_amd64.whl:

Publisher: release.yml on dralley/rpmrepo_metadata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b365ba568df50f9a6cc740e8e38ad9f91d84eb31e1bb57c5ed0027c67fbf35bd
MD5 a5c66e206a7e0bc2cc6ca62caf246449
BLAKE2b-256 5181799805a69e1b32040ad04933f908484ca1926bb805b162cc8740d57719f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on dralley/rpmrepo_metadata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 279b62bd805e2f4dab9419fe4602b0cdbf6b1d2c72b9631f1b4509bddc9cac65
MD5 8972a4f167e6e0e4fe0744ce097f19e4
BLAKE2b-256 62c08ed2de0037bbce0ec61e6a234cc74af2785ab661c4f4f21cd41892135ff9

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.5.2-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: release.yml on dralley/rpmrepo_metadata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rpmrepo_metadata-0.5.2-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.5.2-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b6c368acfa7b13e723bda89f1f9c070bc47a86078c488a3ca90df87ae83f666c
MD5 bcce8f38a5533397696bc9f1f2bfd253
BLAKE2b-256 3785af86fb455694144bc70b41a3e8d1662c423dad9f034ba6884edfa365b8cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.5.2-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on dralley/rpmrepo_metadata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page