Skip to main content

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

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.7.0.tar.gz (100.8 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.7.0-cp310-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10+Windows x86-64

rpmrepo_metadata-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl (6.9 MB view details)

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

rpmrepo_metadata-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl (6.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

rpmrepo_metadata-0.7.0-cp310-abi3-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: rpmrepo_metadata-0.7.0.tar.gz
  • Upload date:
  • Size: 100.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rpmrepo_metadata-0.7.0.tar.gz
Algorithm Hash digest
SHA256 b72535256eae70bb82cbb03c7d71c8179ddb3de6afa7efdfaa60db61854d44e1
MD5 c7e8d317230731e6b2482a1d2570638c
BLAKE2b-256 596980d40c698d3193eb40c58b9530eb19ab38073c23d7c0bb958809e9212570

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.7.0.tar.gz:

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.7.0-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.7.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 461139658e1b955cccfab96a69ce13d1ef05a6eadfc6ceeaeb26d20d39cbe4c4
MD5 e7cd8af94ca5b0bc0a9f74a27c51c1f6
BLAKE2b-256 8ed80b66271ae0eaad9163a2c075f5b887a232a145e141ac5e87f71c2b56a2e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.7.0-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.7.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ee1245d69980933863356e3e0fc31d20cf74c68bbefb6457ab84b17302d84d8a
MD5 4b0c9292df8c91f30958433268ae1071
BLAKE2b-256 9ff52460eff04f3b4ce0a3e9f8808b9a56a050cf55447bf6b4b17753e48a185e

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.7.0-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.7.0-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e8c7cb3c70b606ccb46f437909bd3cbe9dd220072c7ddcef18802f445b7de9be
MD5 e51d5025070a3816962506ee7bb89531
BLAKE2b-256 7874804bfc42ed3133c55ee7363cdcd2d5ca21394347f7247b7e363a56a42b79

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.7.0-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.7.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rpmrepo_metadata-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e73ed5be1400e5a4ae691400d06624adf1c68994697cf6049cced6109879e242
MD5 5d8bf7049afe05311cb719d29ac210cc
BLAKE2b-256 008b4097c053fdda8446eff30beaead7e392b4db6662e0c54cf9aead07c3ab0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpmrepo_metadata-0.7.0-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.

Release history Release notifications | RSS feed

This release

0.7.0 This release

5 files

0.6.1

5 files

0.6.0

5 files

0.5.3

5 files

0.5.2

5 files

0.1.0.post3

1 file

0.1.0.post2

1 file

0.1.0.post1

1 file

0.1.0

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page