Thanks, I appreciate it.
Ranjan
_______________________________________________
Rpm-list mailing list
Rpm-...@redhat.com
https://listman.redhat.com/mailman/listinfo/rpm-list
The "actual module" is in the rpm source tree, see the python sub-directory for
sources or the rpm-python binary package for the python bindings.
73 de Jeff
--
Jeff Johnson ARS N3NPQ
j...@jbj.org (j...@redhat.com)
Chapel Hill, NC
The module is in the rpm source file, and in the rpm source rpm.
Unfortunately, without a decent knowledge of librpm, it can be
a bit difficult to dive into. About the only docs is the "testit"
file include, and its not all that useful.
The module is all c actually. Looking though the anaconda source
code is probabaly about the best place to look for hints on how
to use it.
Adrian
Thanks once again.
Ranjan
-----Original Message-----
From: Jeff Johnson [mailto:j...@JBJ.ORG]
Sent: Monday, August 14, 2000 5:12 PM
To: rpm-...@redhat.com
Subject: Re: Python RPM modules
On Mon, Aug 14, 2000 at 01:07:02PM -0400, Kohli, Ranjan wrote:
> All,
> I have looking all over for documentation/examples of how I can use
> Python to install apps that are packed in a RPM. I find bits and pieces
> and passing references to a rpm module in rpmlint/anaconda/up2date, but
> am having a hard time finding what the API looks like. I would
> appreciate it if some one could point me in the right direction. The
> actual module would be perfect.
>
The "actual module" is in the rpm source tree, see the python sub-directory
for
sources or the rpm-python binary package for the python bindings.
73 de Jeff
--
Jeff Johnson ARS N3NPQ
j...@jbj.org (j...@redhat.com)
Chapel Hill, NC
_______________________________________________
Matt
RPM binding for Python
-----------------------
The RPM bindings for Python present an object oriented approach to
using the RPM Package Manager. The main object types are:
Class "header" - represents a RPM package header
All RPM packages have headers that provide metadata for the package.
Header objects can be returned by database queries or loaded from a
binary package on disk.
The headerFromPackage function loads the package header from a
package on disk. It returns a tuple of a "isSource" flag and the
header object. The "isSource" flag is set to 1 if the package
header was read from a source rpm or to 0 if the package header was
read from a binary rpm. For example:
import os, rpm
fd = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY)
(isSource, header) = rpm.headerFromPackage(fd)
fd.close()
The Python interface to the header data is quite elegant. It
presents the data in a dictionary form. We'll take the header we
just loaded and access the data within it:
print header[rpm.RPMTAG_NAME]
print header[rpm.RPMTAG_VERSION]
print header[rpm.RPMTAG_RELEASE]
in the case of our "foor-1.0-1.i386.rpm" package, this code would
output:
foo
1.0
1
You make also access the header data by string name:
print header['name']
This method of access is a bit slower because the name must be
translated into the tag number dynamically.
Class "rpmdb" - represents a RPM database.
Instances of the rpmdb object provide access to the records of a
RPM database. The records are accessed by index number. To
retrieve the header data in the RPM database, the rpmdb object is
subscripted as you would access members of a list.
The rpmdb class contains the following methods:
firstkey() - returns the index of the first record in the database
(will be deprecated in RPM 4.0)
nextkey(index) - returns the index of the next record after
"index" in the database.
findbyfile(file) - returns a list of the indexes to records that
own file "file".
findbyname(name) - returns a list of the indexes to records for
packages named "name".
findbyprovides(provides) - returns a list of the indexes to records for
packages that provide "provides".
To obtain a rpmdb object, the opendb function in the rpm module
must be called. The opendb function takes two optional arguments.
The first optional argument is a boolean flag that specifies if the
database is to be opened for read/write access or read-only access.
The second argument specifies an alternate root directory for RPM
to use.
An example of opening a database and retrieving the first header in
the database, then printing the name of the package that the header
represents:
import rpm
db = rpm.opendb()
index = db.firstkey()
header = db[index]
print header[rpm.RPMTAG_NAME]
To print all of the packages in the database that match a package
name, the code will look like this:
import rpm
db = rpm.opendb()
indexes = db.findbyname("foo")
for index in indexes:
header = db[index]
print "%s-%s-%s" % (header[rpm.RPMTAG_NAME],
header[rpm.RPMTAG_VERSION],
header[rpm.RPMTAG_RELEASE])
Class rpmtrans - represents a RPM transaction set.
The transaction set is the workhorse of RPM. It performs the
installation and upgrade of packages. The rpmtrans object is
instantiated by the TransactionSet function in the rpm module.
The TransactionSet function takes two optional arguments. The first
argument is the root path, the second is an open database to perform
the transaction set upon.
A rpmtrans object has the following methods:
add(header, data, mode) - adds a binary package to the transaction set
header - the header of the binary package to be added to the
transaction set
data - user data that will be passed to the transaction
callback during transaction execution
mode - optional argument that specifies if this package should
be installed ('i'), upgraded ('u'), or if it is just
available to the transaction when computing
dependencies but no action should be performed with it
('a').
depcheck() - performs a dependency and conflict check on the
transaction set After headers have been added to a
transaction set, a dependency check can be performed
to make sure that all package dependencies are
satisfied. If there are no unresolved dependencies,
None is returned. If there are dependencies, a list
of complex tuples is returned, one tuple per
unresolved dependency.
The format of the dependency tuple is:
((packageName, packageVersion, packageRelease),
(reqName, reqVersion),
needsFlags,
suggestedPackage,
sense)
packageName, packageVersion, packageRelease are the name,
version, and release of the package that has the unresolved
dependency or conflict.
The reqName and reqVersion are the name and version of the
requirement or conflict.
The needsFlags is a bitfield that describes the versioned
nature of a requirement or conflict. The constants
rpm.RPMDEP_SENSE_LESS, rpm.RPMDEP_SENSE_GREATER, and
rpm.RPMDEP_SENSE_EQUAL can be logical ANDed with the needsFlags
to get versioned dependency information.
suggestedPackage is a tuple if the dependency check was aware
of a package that solves this dependency problem when the
dependency check was run. Packages that are added to the
transaction set as "available" are examined during the
dependency check as possible dependency solvers. The tuple
contains two values, (header, suggestedName). These are set to
the header of the suggested package and its name, respectively.
If there is no known package to solve the dependency problem,
suggestedPackage is None.
The constants rpm.RPMDEP_SENSE_CONFLICTS and
rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a
requirement or a conflict.
run(flags, problemSetFilter, callback, data) - attempts to execute
transaction set
After the transaction set has been populated with install and
upgrade actions, it can be executed by invoking the run()
method.
Arguments -
flags - modifies the behavior of the transaction set as it is
processed. The following values can be locical ORed
together:
rpm.RPMTRANS_FLAG_TEST - test mode, do not modify the RPM
database, change any files, or run
any package scripts
rpm.RPMTRANS_FLAG_BUILD_PROBS - only build a list of
problems encountered when attempting to run this transaction
set
rpm.RPMTRANS_FLAG_NOSCRIPTS - do not execute package scripts
rpm.RPMTRANS_FLAG_JUSTDB - only make changes to the rpm
database, do not modify files.
rpm.RPMTRANS_FLAG_NOTRIGGERS - do not run trigger scripts
rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc
rpm.RPMTRANS_FLAG_ALLFILES - create all files, even if a
file is marked %config(missingok) and an upgrade is
being performed.
rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted
packages.
problemSetFilter - a bitfield that tells the transaction set
engine to ignore classes of problems
rpm.RPMPROB_FILTER_IGNOREOS -
rpm.RPMPROB_FILTER_IGNOREARCH -
rpm.RPMPROB_FILTER_REPLACEPKG -
rpm.RPMPROB_FILTER_FORCERELOCATE -
rpm.RPMPROB_FILTER_REPLACENEWFILES -
rpm.RPMPROB_FILTER_REPLACEOLDFILES -
rpm.RPMPROB_FILTER_OLDPACKAGE -
rpm.RPMPROB_FILTER_DISKSPACE -
On Mon, Aug 14, 2000 at 01:07:02PM -0400, Kohli, Ranjan wrote:
> All,
> I have looking all over for documentation/examples of how I can use
> Python to install apps that are packed in a RPM. I find bits and pieces
> and passing references to a rpm module in rpmlint/anaconda/up2date, but
> am having a hard time finding what the API looks like. I would
> appreciate it if some one could point me in the right direction. The
> actual module would be perfect.
>
> Thanks, I appreciate it.
>
> Ranjan
>
>
>
Matt
On Thu, Aug 17, 2000 at 10:31:02AM -0400, Kohli, Ranjan wrote:
> Jeff,
> Thanks for taking the time to reply. I did make some headway by looking
> through the rmpmodule source code. What I have not been able to find is
> exactly where/how in the anaconda python modules are the rpm packages
> actually installed. I have looked at the todo.py, text.py, gui.py etc and
> can't locate it. Any clues as to where the call is actually made i.e. rpm -i
> to install a package would be appreciated.
_______________________________________________
> Here's the start, it's not quite finised, though. :| There's still
> some important stuff missing.
> ......
>
> A rpmtrans object has the following methods:
> ....
> run(flags, problemSetFilter, callback, data) - attempts to execute
> transaction set
>
> .....
Matt,
Could you let me know what the format of the callback and the data
arguments need to be. The callback in todo.py (self.instCallback) is alot
more complicated than what I need to do.
Thanks,
Yea, I haven't gotten to that part. I'll try to do it next week..
Matt
Thanks all,
Ranjan
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/usr/bin/python
import rpm
import os
import sys
from gtk import *
import GtkExtra
def instCallback(self, what, amount, total, h):
print "In instCallback"
print self, what,amount, total, h, "\n"
if (what == rpm.RPMCALLBACK_TRANS_START):
print "rpm.RPMCALLBACK_TRANS_START"
if (what == rpm.RPMCALLBACK_TRANS_PROGRESS):
print "rpm.RPMCALLBACK_TRANS_PROGRESS"
if (what == rpm.RPMCALLBACK_TRANS_STOP):
print "rpm.RPMCALLBACK_TRANS_STOP"
if (what == rpm.RPMCALLBACK_INST_OPEN_FILE):
print "rpm.RPMCALLBACK_INST_OPEN_FILE"
elif (what == rpm.RPMCALLBACK_INST_PROGRESS):
if total:
print "rpm.RPMCALLBACK_INST_OPEN_FILE"
print amount, total, "\n"
elif (what == rpm.RPMCALLBACK_INST_CLOSE_FILE):
print "rpm.RPMCALLBACK_INST_OPEN_FILE"
else:
pass
def doNothing():
pass
def do_rpm_stuff():
# Here is where I do RPM installs
# In general we take the following steps
# we need to open the rpm database
# db = rpm.opendb()
# Create a transaction set
# ts = rpm.TransactionSet(db)
# First I need to open the database
print "Beginning to do RPM Stuff \n"
# Misc RPM stuff
try:
fd = os.open("tripwire-1.2-5.i386.rpm", os.O_RDONLY)
(header, isSource) = rpm.headerFromPackage(fd)
os.close(fd)
if ( isSource ):
print header[rpm.RPMTAG_NAME], ' is a source package'
else:
print header[rpm.RPMTAG_NAME], ' is a binary package'
print header[rpm.RPMTAG_NAME]
print header[rpm.RPMTAG_VERSION]
print header[rpm.RPMTAG_RELEASE]
except:
sys.stderr.write('error in do_rpm_stuf()!\n')
print 'error!', sys.exc_type, sys.exc_value
# Open the rpm database
db = rpm.opendb()
# Create a transaction set
ts = rpm.TransactionSet()
# Add the rpm to the transaction set
ts.add( header, header, "u" )
# Do a dependency check
deps = ts.depcheck()
rc = []
if deps:
print 'Looking for dependencies'
for ((name, version, release),
(reqname, reqversion),
flags, suggest, sense) in deps:
print deps
if sense == rpm.RPMDEP_SENSE_REQUIRES:
if suggest:
(header, sugname) = suggest
print (header, sugname)
else:
sugname = "no suggestion"
print sugname
if sense == rpm.RPMDEP_SENSE_CONFLICTS:
if suggest:
(header, sugname) = suggest
print (header, sugname), "conflict"
else:
sugname = "no conflict suggestion"
print sugname
if not (name, sugname) in rc:
rc.append ((name, sugname))
print "Done with dependency check"
ts.order()
try:
#problems =
ts.run(rpm.RPMTRANS_FLAG_BUILD_PROBS,~rpm.RPMPROB_FILTER_DISKSPACE,
instCallback, 0)
# at this point I get a core dump...
problems = ts.run(0,~rpm.RPMPROB_FILTER_DISKSPACE, doNothing, 0)
print problems
except:
sys.stderr.write('error in do_rpm_stuf()!\n')
print 'error!', sys.exc_type, sys.exc_value
# Main starts here...
def main():
rc_parse("testgtkrc")
do_rpm_stuff()
#mainloop()
if __name__ == '__main__': main()