Skip to content

Add a page for RPM Python API#55

Open
FrostyX wants to merge 2 commits intorpm-software-management:masterfrom
FrostyX:python-documentation
Open

Add a page for RPM Python API#55
FrostyX wants to merge 2 commits intorpm-software-management:masterfrom
FrostyX:python-documentation

Conversation

@FrostyX
Copy link
Copy Markdown
Member

@FrostyX FrostyX commented Sep 18, 2024

We agreed that having examples as scripts in the RPM git repository would be ideal (syntax highlighting, the possibility to run them, etc) but for better discoverability, I would like to mention them even from the RPM website. This way they may be easier to find for people searching on Google or the website itself.

@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Sep 18, 2024

I couldn't figure out how to build the website locally so I am not sure if the render will look pretty. But the markdown is IMHO valid.

@FrostyX FrostyX force-pushed the python-documentation branch from 10456db to bf5da15 Compare September 18, 2024 19:06
@pmatilai pmatilai requested review from a team and pmatilai and removed request for a team September 25, 2024 08:46
@pmatilai
Copy link
Copy Markdown
Member

Having a separate page of our own for Python and linking to the examples is fine, but showing output of those examples there makes no sense - somebody looking for rpm python API docs isn't interested in example program output but actual API documentation, and its examples.

@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Oct 22, 2024

Thank you for the review @pmatilai,

somebody looking for rpm python API docs isn't interested in example program output but actual API documentation, and its examples.

I agree, that's why my original idea was to put those examples directly into the documentation website. But I only partially agree with the "not being interested in the example program output" ... If I am completely new, I want to know what the API can do and seeing what kinds of information can be printed by the API and how it looks like before diving into reading any code is definitely helpful.

Almost all my usages of the RPM Python API went the same way.

  1. I have a package name and I need to print its summary
  2. I know it is possible because rpm -qi hello can show it
  3. How do I get the same value in Python

Easily finding in the documentation that there is an example Python script, which prints the same information as rpm -qi is IMHO very helpful.

Having a separate page of our own for Python and linking to the examples is fine

But the examples aside, I talked with @xsuchy and we agreed that those web archive links used to be useful back in the day when they were up-to-date. What if took them, fixed any outdated information and put hem into the python.md page?

@pmatilai
Copy link
Copy Markdown
Member

Sample output is meaningful when it's next to the actual code, but it doesn't work when linking to some far-away thing.

The problem here starts right at the bottom: API documentation needs to be where the code is, otherwise it'll fall out of sync. That's one of the reasons I prefer examples in the codebase itself too. I think what you're making here is more like a tutorial, which is a little different again. What the Python API really needs is

  • export rpm module pydoc on the web
  • make the module documentation meaningful (as in, add relevant usage examples)
  • add a tutorial that refers the actual API docs

I'm certainly not expecting you to do all that, just thinking out loud as to what sort of structure we'd want/need here.
I think we'd want that one top-level python.md page just for general info and place to add links to, and then a separate subdirectory for the tutorial part, named thus.

@FrostyX FrostyX requested a review from a team as a code owner January 12, 2025 13:16
@FrostyX FrostyX requested review from ffesti and removed request for a team January 12, 2025 13:16
@FrostyX FrostyX force-pushed the python-documentation branch from a68348d to 80e84f9 Compare January 12, 2025 13:18
@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Jan 12, 2025

I converted the whole "Chapter 16. Programming RPM with Python" from this archive
https://web.archive.org/web/20220628164347/https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-rpm-programming-python.html
into markdown. The text is unchanged. Now I want to go through it and modernize the outdated parts.

Can you please let me know how to build the rpm.org page locally? I want to make sure the markdown renders as expected.

@ffesti
Copy link
Copy Markdown
Contributor

ffesti commented Jan 21, 2025

OK, this is only mentioned in the main RPM repository: https://github.com/rpm-software-management/rpm/tree/master/docs

https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/testing-your-github-pages-site-locally-with-jekyll explains how to do that. On Fedora I use rubygem-jekyll and friends to limit the amounts of gem downloaded directly.

@ffesti
Copy link
Copy Markdown
Contributor

ffesti commented Jan 21, 2025

OK; added a README file for this repo.

@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Jan 21, 2025

@ffesti thank you very much. I did not realize that this is a jekyll project. I successfully built it through jekyll serve.

@ffesti
Copy link
Copy Markdown
Contributor

ffesti commented Jan 21, 2025

Well, it is and it isn't. It's a GitHub pages project. GH pages uses something not completely unlike Jekyll - maybe.

This is almost unchanged text from the "Programming RPM with Python
from Fedora RPM Guide" archive. I only did some formatting changes
such as displaying some symbols as code.
At the time of this update, we have F41, Python 3.13, and RPM 4.20
@FrostyX FrostyX force-pushed the python-documentation branch from 7196b0b to 28c0195 Compare February 2, 2025 21:25
@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Feb 2, 2025

I did my best to modernize the original "Chapter 16. Programming RPM with Python" documentation from
https://web.archive.org/web/20220628164347/https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-rpm-programming-python.html

It's not perfect but IMHO it is good enough. There are two FIXME entries that I would like to fix before merging but I couldn't figure out how it should be done. Can you please take a look?

Comment thread python.md

## Dependency Comparisons

FIXME code examples in this chapter are outdated
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code uses file_h.dsOfHeader(), I don't know what should be done instead. I know a syntax like rpm.ds(h, rpm.RPMTAG_PROVIDENAME) but it takes an argument, the original example doesn't. I was thinking of rpm.ds(h, rpm.RPMTAG_EVR) but then .EVR() on it returns nothing. So I don't know.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dsOfHeader() is equivalent to rpm.ds(h, rpm.RPMTAG_NEVR)

And yeah, it's all pretty arbitrary.

Comment thread python.md
# FIXME
# if resolved:
# # ts.addIntall(h, h, 'i')
# return -1
Copy link
Copy Markdown
Member Author

@FrostyX FrostyX Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original example used this undefined resolved variable. I have no clue how it should be set so that the example makes sense.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just delete the example. I don't think anythink has used this interface in 15 years or longer, whether it functions at all is an unknown.

Comment thread python.md
# FIXME
# if resolved:
# # ts.addIntall(h, h, 'i')
# return -1
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same undefined resolved variable but in a full script example

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just drop, it refers to a long, long dead thing.

@FrostyX
Copy link
Copy Markdown
Member Author

FrostyX commented Apr 23, 2025

bump

@pmatilai
Copy link
Copy Markdown
Member

Uff, sorry this has gone under the radar entirely 😢

Comment thread python.md
file_h = ts.hdrFromFdno(fd)
file_ds = file_h.dsOfHeader()
inst_ds = inst_h.dsOfHeader()
if file_ds.EVR() >= inst_ds.EVR():
Copy link
Copy Markdown
Member

@pmatilai pmatilai Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, this is just plain wrong. EVR() returns a plain old string, and one can't compare EVR strings with Python's string comparison and expect anything resembling relevant results. You'll need to use rpm.labelCompare() to compare EVRs, and then you don't need a DS to get the EVR of a header. And in fact you don't need to extract the EVR either, you can just use rpm.versionCompare(file_h, inst_h).

Dependency set comparisons are strange beasts that have their uses but I have no nice examples to give, better to leave them out than give wrong examples.

Comment thread python.md

for inst_h in ts.dbMatch('name', h['name']):
inst_ds = inst_h.dsOfHeader()
if pkg_ds.EVR() >= inst_ds.EVR():
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, this is wrong and wont produce meaningful results.

Comment thread python.md
def read_rpm_header(ts, filename):
fd = os.open(filename, os.O_RDONLY)
try:
h = ts.hdrFromFdno(fd)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also just pass a file name directly to hdrFromFdno():

>>> h = ts.hdrFromFdno('/tmp/setup-2.15.0-8.fc41.noarch.rpm')
>>> h['name']
'setup'

...or a Python file object...

Comment thread python.md
`rpm.RPMSENSE_GREATER`, and `rpm.RPMSENSE_LESS`. This tells you if the
dependency is for a version of a package greater than 4.1, for example.

The `suggestedPackage` names a package that solves the dependency. The
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rpm will only suggest packages if there's a suggestion rpmdb available and enabled, which is ... never.

Comment thread python.md
You can add packages to a transaction set in any order. The `order` method
reorders the transaction set to ensure that packages get installed or removed in
the right order. The order method orders by a topological sort using the
dependencies relations between objects with dependency comparisons.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not about reordering a transaction, a transaction is unordered before .order() is called and will miserably fail in any non-trivial case. So this needs a bit of emphasis: it's in practise mandatory to call .order() before calling .run().

Comment thread python.md
| rpm.RPMCALLBACK_UNINST_STOP | Uninstallation stop |
| rpm.RPMCALLBACK_REPACKAGE_PROGRESS | Repackaging progress |
| rpm.RPMCALLBACK_REPACKAGE_START | Repackaging start |
| rpm.RPMCALLBACK_REPACKAGE_STOP | Repackaging stop |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just drop these REPACKAGE items, no rpm in the last 15+ years has supported that.

Comment thread python.md
| rpm.RPMCALLBACK_REPACKAGE_START | Repackaging start |
| rpm.RPMCALLBACK_REPACKAGE_STOP | Repackaging stop |
| rpm.RPMCALLBACK_UNPACK_ERROR | Error unpacking package file |
| rpm.RPMCALLBACK_CPIO_ERROR | cpio error getting package payload |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And OTOH this is missing a lot of newer items:

REGISTER_ENUM(RPMCALLBACK_SCRIPT_ERROR);
REGISTER_ENUM(RPMCALLBACK_SCRIPT_START);
REGISTER_ENUM(RPMCALLBACK_SCRIPT_STOP);
REGISTER_ENUM(RPMCALLBACK_INST_STOP);
REGISTER_ENUM(RPMCALLBACK_ELEM_PROGRESS);
REGISTER_ENUM(RPMCALLBACK_VERIFY_PROGRESS);
REGISTER_ENUM(RPMCALLBACK_VERIFY_START);
REGISTER_ENUM(RPMCALLBACK_VERIFY_STOP);

Comment thread python.md

ts = rpm.TransactionSet()

# Set to not verify DSA signatures.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does a whole lot more than just disable DSA - DSA which is no longer used anywhere.

@pmatilai
Copy link
Copy Markdown
Member

Having quickly skimmed through this, I'm more than a little doubtful on the usefulness of these old examples. They are sooooooooooo outdated that it'd really require going through them with a fine comb one by one.

@pmatilai pmatilai closed this Jun 13, 2025
@github-project-automation github-project-automation Bot moved this from Backlog to Done in RPM Jun 13, 2025
@pmatilai pmatilai reopened this Jun 13, 2025
@github-project-automation github-project-automation Bot moved this from Done to Todo in RPM Jun 13, 2025
@pmatilai
Copy link
Copy Markdown
Member

Eh, sorry, didn't intend to close, just comment. The GH button ordering catches me every now and then 🤪

@xsuchy
Copy link
Copy Markdown
Member

xsuchy commented Jun 13, 2025

I'm more than a little doubtful on the usefulness of these old examples.

Do we have better ones?

@pmatilai
Copy link
Copy Markdown
Member

There are newer examples in the main rpm repo: https://github.com/rpm-software-management/rpm/tree/master/python/examples

A bad example on the official site is worse than a non-existant one because it tells you "this is how its done". And these ancient examples are so outdated to be dangerous.

Let's go back to a state without them, and get the body of newer work merged. We can then look at bringing what's still relevant in those old examples in a more curated and gradual manner.

We simply do not have the cycles to review the whole pile of those old examples with the care that it requires.

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

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants