Skip to content

Conversation

@cottsay
Copy link
Member

@cottsay cottsay commented Oct 6, 2025

This change introduces some basic Python bindings for createrepo-agent.

The module itself

  • Some constants in createrepo_agent.*
  • A createrepo_agent.Server type, which creates a creatrepo-agent Assuan server for the given repository cluster. If there is already a server running, an error occurs.
  • A createrepo_agent.Client type, which connects to an already running server. It does not automatically spawn a server if one is not already running.

Example for how these could be used is in the tests:

with createrepo_agent.Server(str(tmp_path)):
with createrepo_agent.Client(str(tmp_path)) as c:
with pytest.raises(TypeError):
c.add(str(rpm_path), 1)
with pytest.raises(TypeError):
c.add(str(rpm_path), (1,))
c.set_invalidate_dependants(True)
c.set_invalidate_family(True)
c.add(str(rpm_path), ('x86_64',))
c.commit()

Building with vanilla CMake

During a normal CMake build, if a sufficient Python version is found or WITH_PYTHON=ON is specifically specified, the Python module will be built and a dist-info directory will be installed. There aren't a lot of great ways to generate the metadata from CMake, so I elected to do it manually. It's just a handful of files with mostly static content. This is how source builds from colcon, RPM, and debian packaging will build and install the module. The only additional dependency is Python itself.

Building with scikit-build

A top-level pyproject.toml is present so that createrepo-agent can be built as a standards-based Python package. A build backend is available for scikit-build, which chains to CMake to build the module and results in a usable wheel. The shared object library is linked against system dependencies at this stage, so the wheel isn't appropriate for widespread distribution, but it should function fine on the platform it was built. For now, I elected to omit the createrepo-agent executable from the wheel, so it only contains the Python bindings.

Combining scikit-build with cibuildwheel and manylinux

The pypa/cibuildwheel action can build a Python package against various manylinux targets and automatically audit the resulting wheel files to include the necessary shared object library files. The resulting wheels are appropriate for upload to PyPI and should cover the vast majority Linux platforms.

The action will run for each tag and can be dispatched manually as necessary. It builds the python distribution artifacts (sdist and binary wheels) and makes them available to download. At this time, it does not automatically upload the artifacts to PyPI. When a release occurs, this should be done manually and the resulting artifacts published with twine.

Future work

Another type, possibly createrepo_agent.Agent, which combines the Server and Client and auto-spawns, similar to how the createrepo-agent executable behaves. Also, introduce higher-level workflows for concepts like "import" (again, provided by the executable) which combine multiple client calls.

Important

This PR depends on #16 and is opened in a draft state until that upstream change merges.

@cottsay cottsay self-assigned this Oct 6, 2025
@cottsay cottsay added the enhancement New feature or request label Oct 6, 2025
@codecov-commenter
Copy link

codecov-commenter commented Oct 6, 2025

Codecov Report

❌ Patch coverage is 65.72770% with 73 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.67%. Comparing base (691d41d) to head (a466ce9).

Files with missing lines Patch % Lines
src/python/client.c 62.50% 25 Missing and 17 partials ⚠️
src/python/server.c 67.53% 16 Missing and 9 partials ⚠️
src/python/init.c 75.00% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@                      Coverage Diff                       @@
##           cottsay/cmake-find-modules      #18      +/-   ##
==============================================================
+ Coverage                       38.74%   42.67%   +3.93%     
==============================================================
  Files                              17       20       +3     
  Lines                            2403     2615     +212     
  Branches                          494      532      +38     
==============================================================
+ Hits                              931     1116     +185     
+ Misses                           1259     1244      -15     
- Partials                          213      255      +42     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nuclearsandwich
Copy link
Member

Attempting to run the Python tests locally I encountered this problem naively installing python test dependencies:

❯ pip install . -e .[test]
Processing /home/steven/osrf/createrepo-agent
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... done
Obtaining file:///home/steven/osrf/createrepo-agent
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Installing backend dependencies ... done
  Preparing editable metadata (pyproject.toml) ... done
ERROR: Cannot install createrepo-agent 0.4.2 (from /home/steven/osrf/createrepo-agent) because these package versions have conflicting dependencies.

The conflict is caused by:
    The user requested createrepo-agent 0.4.2 (from /home/steven/osrf/createrepo-agent)
    The user requested createrepo-agent 0.4.2 (from /home/steven/osrf/createrepo-agent)

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip to attempt to solve the dependency conflict

ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts

@cottsay
Copy link
Member Author

cottsay commented Oct 11, 2025

I hadn't actually tried installing the package that way, but it should work.

I think you specified the target twice (. and .[test]):

- > pip install . -e .[test]
+ > pip install -e .[test]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants