summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/.gitignore1
-rw-r--r--python/MANIFEST.in1
-rw-r--r--python/Makefile.am38
-rw-r--r--python/header-py.c119
-rw-r--r--python/rpm/__init__.py (renamed from python/rpm/__init__.py.in)68
-rw-r--r--python/rpm/transaction.py (renamed from python/rpm/transaction.py.in)62
-rw-r--r--python/rpmarchive-py.c275
-rw-r--r--python/rpmarchive-py.h15
-rw-r--r--python/rpmds-py.c82
-rw-r--r--python/rpmfd-py.c58
-rw-r--r--python/rpmfi-py.c96
-rw-r--r--python/rpmfiles-py.c598
-rw-r--r--python/rpmfiles-py.h18
-rw-r--r--python/rpmii-py.c28
-rw-r--r--python/rpmkeyring-py.c4
-rw-r--r--python/rpmmacro-py.c14
-rw-r--r--python/rpmmi-py.c54
-rw-r--r--python/rpmmodule.c151
-rw-r--r--python/rpmps-py.c2
-rw-r--r--python/rpmsmodule.c29
-rw-r--r--python/rpmstrpool-py.c156
-rw-r--r--python/rpmstrpool-py.h14
-rw-r--r--python/rpmsystem-py.h3
-rw-r--r--python/rpmtd-py.c160
-rw-r--r--python/rpmtd-py.h1
-rw-r--r--python/rpmte-py.c71
-rw-r--r--python/rpmts-py.c148
-rw-r--r--python/setup.py.in59
-rw-r--r--python/spec-py.c73
-rw-r--r--python/spec-py.h2
30 files changed, 1899 insertions, 501 deletions
diff --git a/python/.gitignore b/python/.gitignore
deleted file mode 100644
index ca7802a2b..000000000
--- a/python/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.py
diff --git a/python/MANIFEST.in b/python/MANIFEST.in
deleted file mode 100644
index a4306366e..000000000
--- a/python/MANIFEST.in
+++ /dev/null
@@ -1 +0,0 @@
-include MANIFEST.in *.h
diff --git a/python/Makefile.am b/python/Makefile.am
index 1f2e596ac..a9bd34729 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -1,52 +1,56 @@
# Makefile for rpm library.
+include $(top_srcdir)/rpm.am
+AM_CFLAGS = @RPMCFLAGS@
+
EXTRA_DIST = rpm/__init__.py rpm/transaction.py
AM_CPPFLAGS = -I$(top_builddir)/include/
AM_CPPFLAGS += -I$(top_srcdir)/python
-AM_CPPFLAGS += -I@WITH_PYTHON_INCLUDE@
-AM_CPPFLAGS += -I$(top_srcdir)
+AM_CPPFLAGS += @PYTHON_CFLAGS@
-rpmpyexec_LTLIBRARIES = _rpm.la _rpmb.la _rpms.la
-rpmpyexec_DATA = rpm/__init__.py rpm/transaction.py
-rpmpyexecdir = @pyexecdir@/@PYTHON_MODULENAME@
+pkgpyexec_LTLIBRARIES = _rpmmodule.la _rpmbmodule.la _rpmsmodule.la
+pkgpyexec_DATA = rpm/__init__.py rpm/transaction.py
-_rpm_la_LDFLAGS = -module -avoid-version -shared
-_rpm_la_LIBADD = \
+_rpmmodule_la_LDFLAGS = -module -avoid-version -shared
+_rpmmodule_la_LIBADD = \
$(top_builddir)/lib/librpm.la \
$(top_builddir)/rpmio/librpmio.la \
- @WITH_PYTHON_LIB@
+ @PYTHON_LIBS@
-_rpm_la_SOURCES = rpmmodule.c rpmsystem-py.h \
+_rpmmodule_la_SOURCES = rpmmodule.c rpmsystem-py.h \
header-py.c header-py.h \
+ rpmarchive-py.c rpmarchive-py.h \
rpmds-py.c rpmds-py.h \
rpmfd-py.c rpmfd-py.h \
rpmfi-py.c rpmfi-py.h \
+ rpmfiles-py.c rpmfiles-py.h \
rpmkeyring-py.c rpmkeyring-py.h \
rpmmi-py.c rpmmi-py.h \
rpmii-py.c rpmii-py.h \
rpmps-py.c rpmps-py.h \
rpmmacro-py.c rpmmacro-py.h \
+ rpmstrpool-py.c rpmstrpool-py.h \
rpmtd-py.c rpmtd-py.h \
rpmte-py.c rpmte-py.h \
rpmts-py.c rpmts-py.h
-_rpmb_la_LDFLAGS = -module -avoid-version -shared
-_rpmb_la_LIBADD = \
+_rpmbmodule_la_LDFLAGS = -module -avoid-version -shared
+_rpmbmodule_la_LIBADD = \
$(top_builddir)/build/librpmbuild.la \
$(top_builddir)/lib/librpm.la \
$(top_builddir)/rpmio/librpmio.la \
- @WITH_PYTHON_LIB@
+ @PYTHON_LIBS@
-_rpmb_la_SOURCES = rpmbmodule.c rpmsystem-py.h \
+_rpmbmodule_la_SOURCES = rpmbmodule.c rpmsystem-py.h \
spec-py.c spec-py.h
-_rpms_la_LDFLAGS = -module -avoid-version -shared
-_rpms_la_LIBADD = \
+_rpmsmodule_la_LDFLAGS = -module -avoid-version -shared
+_rpmsmodule_la_LIBADD = \
$(top_builddir)/sign/librpmsign.la \
$(top_builddir)/lib/librpm.la \
$(top_builddir)/rpmio/librpmio.la \
- @WITH_PYTHON_LIB@
+ @PYTHON_LIBS@
-_rpms_la_SOURCES = rpmsmodule.c rpmsystem-py.h
+_rpmsmodule_la_SOURCES = rpmsmodule.c rpmsystem-py.h
diff --git a/python/header-py.c b/python/header-py.c
index ff581f112..45af51637 100644
--- a/python/header-py.c
+++ b/python/header-py.c
@@ -157,20 +157,11 @@ static PyObject * hdrKeyList(hdrObject * s)
return keys;
}
-static PyObject * hdrAsBytes(hdrObject * s, int legacy)
+static PyObject * hdrAsBytes(hdrObject * s)
{
PyObject *res = NULL;
- char *buf = NULL;
- unsigned int len;
- Header h = headerLink(s->h);
-
- /* XXX this legacy switch is a hack, needs to be removed. */
- if (legacy) {
- h = headerCopy(s->h); /* XXX strip region tags, etc */
- headerFree(s->h);
- }
- buf = headerExport(h, &len);
- h = headerFree(h);
+ unsigned int len = 0;
+ char *buf = headerExport(s->h, &len);
if (buf == NULL || len == 0) {
PyErr_SetString(pyrpmError, "can't unload bad header\n");
@@ -181,15 +172,9 @@ static PyObject * hdrAsBytes(hdrObject * s, int legacy)
return res;
}
-static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
+static PyObject * hdrUnload(hdrObject * s)
{
- int legacy = 0;
- static char *kwlist[] = { "legacyHeader", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
- return NULL;
-
- return hdrAsBytes(s, legacy);
+ return hdrAsBytes(s);
}
static PyObject * hdrExpandFilelist(hdrObject * s)
@@ -223,7 +208,6 @@ static PyObject * hdrFullFilelist(hdrObject * s)
if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) {
rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES);
headerPut(h, fileNames, HEADERPUT_DEFAULT);
- rpmtdFreeData(fileNames);
}
rpmtdFree(fileNames);
@@ -337,7 +321,7 @@ static long hdr_hash(PyObject * h)
static PyObject * hdr_reduce(hdrObject *s)
{
PyObject *res = NULL;
- PyObject *blob = hdrAsBytes(s, 0);
+ PyObject *blob = hdrAsBytes(s);
if (blob) {
res = Py_BuildValue("O(O)", Py_TYPE(s), blob);
Py_DECREF(blob);
@@ -347,31 +331,31 @@ static PyObject * hdr_reduce(hdrObject *s)
static struct PyMethodDef hdr_methods[] = {
{"keys", (PyCFunction) hdrKeyList, METH_NOARGS,
- NULL },
- {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "hdr.keys() -- Return a list of the header's rpm tags (int RPMTAG_*)." },
+ {"unload", (PyCFunction) hdrUnload, METH_NOARGS,
+ "hdr.unload() -- Return binary representation\nof the header." },
{"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS,
- NULL },
+ "DEPRECATED -- Use hdr.convert() instead." },
{"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
- NULL },
+ "DEPRECATED -- Use hdr.convert() instead." },
{"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS,
- NULL },
+ "DEPRECATED -- Obsolete method."},
{"convert", (PyCFunction) hdrConvert, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "hdr.convert(op=-1) -- Convert header - See HEADERCONV_*\nfor possible values of op."},
{"format", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "hdr.format(format) -- Expand a query string with the header data.\n\nSee rpm -q for syntax." },
{"sprintf", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "Alias for .format()." },
{"isSource", (PyCFunction)hdrIsSource, METH_NOARGS,
- NULL },
+ "hdr.isSource() -- Return if header describes a source package." },
{"write", (PyCFunction)hdrWrite, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "hdr.write(file, magic=True) -- Write header to file." },
{"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS,
- NULL},
+ "hdr.dsOfHeader() -- Return dependency set with the header's NEVR."},
{"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS,
- NULL},
+ "hdr.dsFromHeader(to=RPMTAG_REQUIRENAME, flags=None)\nGet dependency set from header. to must be one of the NAME tags\nbelonging to a dependency:\n'Providename', 'Requirename', 'Obsoletename', 'Conflictname',\n'Triggername', 'Recommendname', 'Suggestname', 'Supplementname',\n'Enhancename' or one of the corresponding RPMTAG_*NAME constants." },
{"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS,
- NULL},
+ "hdr.fiFromHeader() -- Return rpm.fi object containing the file\nmeta data from the header.\n\nDEPRECATED - Use rpm.files(hdr) instead."},
{"__reduce__", (PyCFunction)hdr_reduce, METH_NOARGS,
NULL},
@@ -393,7 +377,8 @@ static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
if (obj == NULL) {
h = headerNew();
} else if (CAPSULE_CHECK(obj)) {
- h = CAPSULE_EXTRACT(obj, PYTHON_MODULENAME"._C_Header");
+ h = CAPSULE_EXTRACT(obj, "rpm._C_Header");
+ headerLink(h);
} else if (hdrObject_Check(obj)) {
h = headerCopy(((hdrObject*) obj)->h);
} else if (PyBytes_Check(obj)) {
@@ -404,7 +389,7 @@ static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
Py_END_ALLOW_THREADS;
Py_XDECREF(fdo);
} else {
- PyErr_SetString(PyExc_TypeError, "header, blob or file expected!!");
+ PyErr_SetString(PyExc_TypeError, "header, blob or file expected");
return NULL;
}
@@ -606,7 +591,7 @@ static int hdrPutTag(Header h, rpmTagVal tag, PyObject *value)
rc = hdrAppendItem(h, tag, type, item);
}
} else {
- PyErr_SetString(PyExc_RuntimeError, "cant happen, right?");
+ PyErr_SetString(PyExc_RuntimeError, "can't happen, right?");
}
return rc;
@@ -680,11 +665,60 @@ static PySequenceMethods hdr_as_sequence = {
};
static char hdr_doc[] =
-"";
+ "A header object represents an RPM package header.\n"
+ "\n"
+ "All RPM packages have headers that provide metadata for the package.\n"
+ "Header objects can be returned by database queries or loaded from a\n"
+ "binary package on disk.\n"
+ "\n"
+ "The ts.hdrFromFdno() function returns the package header from a\n"
+ "package on disk, verifying package signatures and digests of the\n"
+ "package while reading.\n"
+ "\n"
+ "Note: The older method rpm.headerFromPackage() which has been replaced\n"
+ "by ts.hdrFromFdno() used to return a (hdr, isSource) tuple.\n"
+ "\n"
+ "If you need to distinguish source/binary headers, do:\n"
+ "\n"
+ " import os, rpm\n"
+ "\n"
+ " ts = rpm.TransactionSet()\n"
+ " fdno = os.open('/tmp/foo-1.0-1.i386.rpm', os.O_RDONLY)\n"
+ " hdr = ts.hdrFromFdno(fdno)\n"
+ " os.close(fdno)\n"
+ " if hdr[rpm.RPMTAG_SOURCEPACKAGE]:\n"
+ " print 'header is from a source package'\n"
+ " else:\n"
+ " print 'header is from a binary package'\n"
+ "\n"
+ "The Python interface to the header data is quite elegant. It\n"
+ "presents the data in a dictionary form. We'll take the header we\n"
+ "just loaded and access the data within it:\n"
+ "\n"
+ " print hdr[rpm.RPMTAG_NAME]\n"
+ " print hdr[rpm.RPMTAG_VERSION]\n"
+ " print hdr[rpm.RPMTAG_RELEASE]\n"
+ "\n"
+ "in the case of our 'foo-1.0-1.i386.rpm' package, this code would\n"
+ "output:\n"
+ " foo\n"
+ " 1.0\n"
+ " 1\n"
+ "\n"
+ "You make also access the header data by string name:\n"
+ "\n"
+ " print hdr['name']\n"
+ " print hdr['version']\n"
+ " print hdr['release']\n"
+ "\n"
+ "This method of access is a teensy bit slower because the name must be\n"
+ "translated into the tag number dynamically. You also must make sure\n"
+ "the strings in header lookups don't get translated, or the lookups\n"
+ "will fail.\n";
PyTypeObject hdr_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".hdr", /* tp_name */
+ "rpm.hdr", /* tp_name */
sizeof(hdrObject), /* tp_size */
0, /* tp_itemsize */
(destructor) hdr_dealloc, /* tp_dealloc */
@@ -729,8 +763,7 @@ PyObject * hdr_Wrap(PyTypeObject *subtype, Header h)
{
hdrObject * hdr = (hdrObject *)subtype->tp_alloc(subtype, 0);
if (hdr == NULL) return NULL;
-
- hdr->h = headerLink(h);
+ hdr->h = h;
return (PyObject *) hdr;
}
diff --git a/python/rpm/__init__.py.in b/python/rpm/__init__.py
index df1e3a282..54728bbd4 100644
--- a/python/rpm/__init__.py.in
+++ b/python/rpm/__init__.py
@@ -2,13 +2,42 @@ r"""RPM Module
This module enables you to manipulate rpms and the rpm database.
+The rpm base module provides the main starting point for
+accessing RPM from Python. For most usage, call
+the TransactionSet method to get a transaction set (rpmts).
+
+For example:
+ import rpm
+ ts = rpm.TransactionSet()
+
+The transaction set will open the RPM database as needed, so
+in most cases, you do not need to explicitly open the
+database. The transaction set is the workhorse of RPM.
+
+You can open another RPM database, such as one that holds
+all packages for a given Linux distribution, to provide
+packages used to solve dependencies. To do this, use
+the following code:
+
+rpm.addMacro('_dbpath', '/path/to/alternate/database')
+solvets = rpm.TransactionSet()
+solvets.openDB()
+rpm.delMacro('_dbpath')
+
+# Open default database
+ts = rpm.TransactionSet()
+
+This code gives you access to two RPM databases through
+two transaction sets (rpmts): ts is a transaction set
+associated with the default RPM database and solvets
+is a transaction set tied to an alternate database, which
+is very useful for resolving dependencies.
"""
import warnings
-import os
-from @PYTHON_MODULENAME@._rpm import *
-from @PYTHON_MODULENAME@.transaction import *
-import @PYTHON_MODULENAME@._rpm as _rpm
+from rpm._rpm import *
+from rpm.transaction import *
+import rpm._rpm as _rpm
_RPMVSF_NODIGESTS = _rpm._RPMVSF_NODIGESTS
_RPMVSF_NOHEADER = _rpm._RPMVSF_NOHEADER
_RPMVSF_NOPAYLOAD = _rpm._RPMVSF_NOPAYLOAD
@@ -19,23 +48,26 @@ __version_info__ = tuple(__version__.split('.'))
# try to import build bits but dont require it
try:
- from @PYTHON_MODULENAME@._rpmb import *
+ from rpm._rpmb import *
except ImportError:
pass
# try to import signing bits but dont require it
try:
- from @PYTHON_MODULENAME@._rpms import *
+ from rpm._rpms import *
except ImportError:
pass
# backwards compatibility + give the same class both ways
ts = TransactionSet
+
def headerLoad(*args, **kwds):
+ """DEPRECATED! Use rpm.hdr() instead."""
warnings.warn("Use rpm.hdr() instead.", DeprecationWarning, stacklevel=2)
return hdr(*args, **kwds)
+
def _doHeaderListFromFD(rpm_fd, retrofit):
hlist = []
while 1:
@@ -49,18 +81,22 @@ def _doHeaderListFromFD(rpm_fd, retrofit):
return hlist
-def readHeaderListFromFD(file_desc, retrofit = True):
+
+def readHeaderListFromFD(file_desc, retrofit=True):
if not isinstance(file_desc, fd):
file_desc = fd(file_desc)
return _doHeaderListFromFD(file_desc, retrofit)
-
-def readHeaderListFromFile(path, retrofit = True):
+
+
+def readHeaderListFromFile(path, retrofit=True):
f = fd(path)
hlist = _doHeaderListFromFD(f, retrofit)
f.close()
return hlist
-
+
+
def readHeaderFromFD(file_desc):
+ """Return (header, pos_before_hdr)"""
if not isinstance(file_desc, fd):
file_desc = fd(file_desc)
try:
@@ -72,7 +108,9 @@ def readHeaderFromFD(file_desc):
return (h, offset)
+
def signalsCaught(siglist):
+ """Returns list of signals that were caught."""
caught = []
for sig in siglist:
if signalCaught(sig):
@@ -80,5 +118,11 @@ def signalsCaught(siglist):
return caught
-def dsSingle(TagN, N, EVR = "", Flags = RPMSENSE_ANY):
- return ds((N, EVR, Flags), TagN)
+
+def dsSingle(TagN, N, EVR="", Flags=RPMSENSE_ANY):
+ """
+ Creates a single entry dependency set (ds)
+
+ dsSingle(RPMTAG_CONFLICTNAME, "rpm") corresponds to "Conflicts: rpm"
+ """
+ return ds((N, Flags, EVR), TagN)
diff --git a/python/rpm/transaction.py.in b/python/rpm/transaction.py
index e73075923..675ecaf8e 100644
--- a/python/rpm/transaction.py.in
+++ b/python/rpm/transaction.py
@@ -1,7 +1,14 @@
-#!/usr/bin/python
+from __future__ import with_statement
+
+import sys
+import rpm
+from rpm._rpm import ts as TransactionSetCore
+
+if sys.version_info[0] == 3:
+ _string_types = str,
+else:
+ _string_types = basestring,
-import @PYTHON_MODULENAME@ as rpm
-from @PYTHON_MODULENAME@._rpm import ts as TransactionSetCore
# TODO: migrate relevant documentation from C-side
class TransactionSet(TransactionSetCore):
@@ -11,7 +18,7 @@ class TransactionSet(TransactionSetCore):
oval = getattr(self, attr)
setattr(self, attr, val)
return oval
-
+
def setVSFlags(self, flags):
return self._wrapSetGet('_vsflags', flags)
@@ -31,8 +38,8 @@ class TransactionSet(TransactionSetCore):
return self._wrapSetGet('_probFilter', ignoreSet)
def parseSpec(self, specfile):
- import _rpmb
- return _rpmb.spec(specfile)
+ import rpm._rpmb
+ return rpm._rpmb.spec(specfile)
def getKeys(self):
keys = []
@@ -44,23 +51,32 @@ class TransactionSet(TransactionSetCore):
else:
return tuple(keys)
- def addInstall(self, item, key, how="u"):
- if isinstance(item, basestring):
- f = file(item)
- header = self.hdrFromFdno(f)
- f.close()
- elif isinstance(item, file):
- header = self.hdrFromFdno(item)
- else:
+ def _f2hdr(self, item):
+ if isinstance(item, _string_types):
+ with open(item) as f:
+ header = self.hdrFromFdno(f)
+ elif isinstance(item, rpm.hdr):
header = item
+ else:
+ header = self.hdrFromFdno(item)
+ return header
+
+ def addInstall(self, item, key, how="u"):
+ header = self._f2hdr(item)
- if not how in ['u', 'i']:
+ if how not in ['u', 'i']:
raise ValueError('how argument must be "u" or "i"')
upgrade = (how == "u")
if not TransactionSetCore.addInstall(self, header, key, upgrade):
raise rpm.error("adding package to transaction failed")
+ def addReinstall(self, item, key):
+ header = self._f2hdr(item)
+
+ if not TransactionSetCore.addReinstall(self, header, key):
+ raise rpm.error("adding package to transaction failed")
+
def addErase(self, item):
hdrs = []
if isinstance(item, rpm.hdr):
@@ -69,7 +85,7 @@ class TransactionSet(TransactionSetCore):
hdrs = item
elif isinstance(item, int):
hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item)
- elif isinstance(item, basestring):
+ elif isinstance(item, _string_types):
hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item)
else:
raise TypeError("invalid type %s" % type(item))
@@ -86,7 +102,7 @@ class TransactionSet(TransactionSetCore):
rc = TransactionSetCore.run(self, callback, data, self._probFilter)
# crazy backwards compatibility goo: None for ok, list of problems
- # if transaction didnt complete and empty list if it completed
+ # if transaction didn't complete and empty list if it completed
# with errors
if rc == 0:
return None
@@ -122,14 +138,18 @@ class TransactionSet(TransactionSetCore):
needflags = rpm.RPMSENSE_ANY
if len(needs) == 3:
needop = needs[1]
- if needop.find('<') >= 0: needflags |= rpm.RPMSENSE_LESS
- if needop.find('=') >= 0: needflags |= rpm.RPMSENSE_EQUAL
- if needop.find('>') >= 0: needflags |= rpm.RPMSENSE_GREATER
+ if '<' in needop:
+ needflags |= rpm.RPMSENSE_LESS
+ if '=' in needop:
+ needflags |= rpm.RPMSENSE_EQUAL
+ if '>' in needop:
+ needflags |= rpm.RPMSENSE_GREATER
needver = needs[2]
else:
needver = ""
- res.append(((n, v, r),(needname,needver),needflags,sense,p.key))
+ res.append(((n, v, r),
+ (needname, needver), needflags, sense, p.key))
return res
diff --git a/python/rpmarchive-py.c b/python/rpmarchive-py.c
new file mode 100644
index 000000000..53a078a4e
--- /dev/null
+++ b/python/rpmarchive-py.c
@@ -0,0 +1,275 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmpgp.h>
+
+#include "header-py.h"
+#include "rpmfi-py.h"
+#include "rpmfd-py.h"
+#include "rpmfiles-py.h"
+#include "rpmarchive-py.h"
+#include "rpmstrpool-py.h"
+
+struct rpmarchiveObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmfi archive;
+ rpmfiles files;
+};
+
+static void rpmarchive_dealloc(rpmarchiveObject * s)
+{
+ rpmfilesFree(s->files);
+ rpmfiArchiveClose(s->archive);
+ rpmfiFree(s->archive);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject *rpmarchive_error(int rc)
+{
+ PyErr_SetObject(PyExc_IOError,
+ Py_BuildValue("(is)", rc, rpmfileStrerror(rc)));
+ return NULL;
+}
+
+static PyObject *rpmarchive_closed(void)
+{
+ PyErr_SetString(PyExc_IOError, "I/O operation on closed archive");
+ return NULL;
+}
+
+static PyObject *rpmarchive_tell(rpmarchiveObject *s)
+{
+ return PyLong_FromLongLong(rpmfiArchiveTell(s->archive));
+}
+
+static PyObject *rpmarchive_close(rpmarchiveObject *s)
+{
+ if (s->archive) {
+ int rc = rpmfiArchiveClose(s->archive);
+ s->archive = rpmfiFree(s->archive);
+ if (rc)
+ return rpmarchive_error(rc);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmarchive_has_content(rpmarchiveObject *s)
+{
+ return PyLong_FromLong(rpmfiArchiveHasContent(s->archive));
+}
+
+static PyObject *rpmarchive_read(rpmarchiveObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = { "size", NULL };
+ char buf[BUFSIZ];
+ ssize_t chunksize = sizeof(buf);
+ ssize_t left = -1;
+ ssize_t nb = 0;
+ PyObject *res = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &left))
+ return NULL;
+
+ if (s->archive == NULL)
+ return rpmarchive_closed();
+
+ /* ConcatAndDel() doesn't work on NULL string, meh */
+ res = PyBytes_FromStringAndSize(NULL, 0);
+ do {
+ if (left >= 0 && left < chunksize)
+ chunksize = left;
+
+ Py_BEGIN_ALLOW_THREADS
+ nb = rpmfiArchiveRead(s->archive, buf, chunksize);
+ Py_END_ALLOW_THREADS
+
+ if (nb > 0) {
+ PyObject *tmp = PyBytes_FromStringAndSize(buf, nb);
+ PyBytes_ConcatAndDel(&res, tmp);
+ left -= nb;
+ }
+ } while (nb > 0);
+
+ if (nb < 0) {
+ Py_XDECREF(res);
+ return rpmarchive_error(nb);
+ } else {
+ return res;
+ }
+}
+
+static PyObject *rpmarchive_write(rpmarchiveObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ const char *buf = NULL;
+ ssize_t size = 0;
+ char *kwlist[] = { "buffer", NULL };
+ ssize_t rc = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &buf, &size)) {
+ return NULL;
+ }
+
+ if (s->archive == NULL)
+ return rpmarchive_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmfiArchiveWrite(s->archive, buf, size);
+ Py_END_ALLOW_THREADS
+
+ if (rc < 0)
+ return rpmarchive_error(rc);
+ else
+ return Py_BuildValue("n", rc);
+}
+
+static PyObject *rpmarchive_readto(rpmarchiveObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ rpmfdObject *fdo = NULL;
+ int nodigest = 0;
+ int rc;
+ char *kwlist[] = { "fd", "nodigest", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
+ rpmfdFromPyObject, &fdo, &nodigest)) {
+ return NULL;
+ }
+
+ if (s->archive == NULL)
+ return rpmarchive_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmfiArchiveReadToFile(s->archive, rpmfdGetFd(fdo), nodigest);
+ Py_END_ALLOW_THREADS
+
+ if (rc)
+ return rpmarchive_error(rc);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmarchive_writeto(rpmarchiveObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ rpmfdObject *fdo = NULL;
+ int rc;
+ char *kwlist[] = { "fd", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
+ rpmfdFromPyObject, &fdo)) {
+ return NULL;
+ }
+
+ if (s->archive == NULL)
+ return rpmarchive_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmfiArchiveWriteFile(s->archive, rpmfdGetFd(fdo));
+ Py_END_ALLOW_THREADS
+
+ if (rc)
+ return rpmarchive_error(rc);
+
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef rpmarchive_methods[] = {
+ { "tell", (PyCFunction)rpmarchive_tell, METH_NOARGS,
+ "archive.tell() -- Return current position in archive." },
+ { "close", (PyCFunction)rpmarchive_close, METH_NOARGS,
+ "archive.close() -- Close archive and do final consistency checks."},
+ { "read", (PyCFunction)rpmarchive_read, METH_VARARGS|METH_KEYWORDS,
+ "archive.read(size=None) -- Read next size bytes from current file.\n\n"
+ "Returns bytes\n"},
+ { "write", (PyCFunction)rpmarchive_write, METH_VARARGS|METH_KEYWORDS,
+ "archive.write(buffer) -- Write buffer to current file." },
+ { "readto", (PyCFunction)rpmarchive_readto, METH_VARARGS|METH_KEYWORDS,
+ "archive.readto(fd, nodigest=None) -- Read content of fd\n"
+ "and write as content of the current file to archive." },
+ { "writeto", (PyCFunction)rpmarchive_writeto,METH_VARARGS|METH_KEYWORDS,
+ "archive.writeto(fd) -- Write content of current file in archive\n to fd." },
+ { "hascontent", (PyCFunction)rpmarchive_has_content, METH_NOARGS,
+ "archive.hascontent() -- Return if current file has a content.\n\n"
+ "Returns false for non regular and all but one of hardlinked files."},
+ { NULL, NULL, 0, NULL }
+};
+
+static char rpmarchive_doc[] =
+"Gives access to the payload of an rpm package.\n\n"
+"Is returned by .archive() method of an rpm.files instance.\n"
+"All methods can raise an IOError exception.";
+
+static PyObject *rpmarchive_iternext(rpmarchiveObject *s)
+{
+ PyObject *next = NULL;
+ int fx = rpmfiNext(s->archive);
+
+ if (fx >= 0) {
+ next = rpmfile_Wrap(s->files, fx);
+ } else if (fx < -1) {
+ next = rpmarchive_error(fx);
+ } else {
+ /* end of iteration, nothing to do */
+ }
+
+ return next;
+}
+
+PyTypeObject rpmarchive_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.archive", /* tp_name */
+ sizeof(rpmarchiveObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) rpmarchive_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmarchive_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmarchive_iternext, /* tp_iternext */
+ rpmarchive_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * rpmarchive_Wrap(PyTypeObject *subtype,
+ rpmfiles files, rpmfi archive)
+{
+ rpmarchiveObject *s = (rpmarchiveObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->files = rpmfilesLink(files);
+ s->archive = archive;
+
+ return (PyObject *) s;
+}
+
diff --git a/python/rpmarchive-py.h b/python/rpmarchive-py.h
new file mode 100644
index 000000000..96f09fd29
--- /dev/null
+++ b/python/rpmarchive-py.h
@@ -0,0 +1,15 @@
+#ifndef H_RPMARCHIVE_PY
+#define H_RPMARCHIVE_PY
+
+#include <rpm/rpmarchive.h>
+
+typedef struct rpmarchiveObject_s rpmarchiveObject;
+
+extern PyTypeObject rpmarchive_Type;
+
+#define rpmarchiveObject_Check(v) ((v)->ob_type == &rpmarchive_Type)
+
+PyObject * rpmarchive_Wrap(PyTypeObject *subtype,
+ rpmfiles files, rpmfi archive);
+
+#endif
diff --git a/python/rpmds-py.c b/python/rpmds-py.c
index 4b44220dc..9eae9a228 100644
--- a/python/rpmds-py.c
+++ b/python/rpmds-py.c
@@ -6,6 +6,7 @@
#include "header-py.h"
#include "rpmds-py.h"
+#include "rpmstrpool-py.h"
struct rpmdsObject_s {
PyObject_HEAD
@@ -96,21 +97,6 @@ rpmds_SetNoPromote(rpmdsObject * s, PyObject * args, PyObject * kwds)
return Py_BuildValue("i", rpmdsSetNoPromote(s->ds, nopromote));
}
-static PyObject *
-rpmds_Notify(rpmdsObject * s, PyObject * args, PyObject * kwds)
-{
- const char * where;
- int rc;
- char * kwlist[] = {"location", "returnCode", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "si:Notify", kwlist,
- &where, &rc))
- return NULL;
-
- rpmdsNotify(s->ds, where, rc);
- Py_RETURN_NONE;
-}
-
/* XXX rpmdsFind uses bsearch on s->ds, so a sort is needed. */
static PyObject *
rpmds_Sort(rpmdsObject * s)
@@ -169,12 +155,18 @@ static PyObject *rpmds_Instance(rpmdsObject * s)
return Py_BuildValue("i", rpmdsInstance(s->ds));
}
-static PyObject * rpmds_Rpmlib(rpmdsObject * s)
+static PyObject * rpmds_Rpmlib(rpmdsObject * s, PyObject *args, PyObject *kwds)
{
+ rpmstrPool pool = NULL;
rpmds ds = NULL;
+ char * kwlist[] = {"pool", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:rpmds_Rpmlib", kwlist,
+ &poolFromPyObject, &pool))
+ return NULL;
/* XXX check return code, permit arg (NULL uses system default). */
- rpmdsRpmlib(&ds, NULL);
+ rpmdsRpmlibPool(pool, &ds, NULL);
return rpmds_Wrap(&rpmds_Type, ds);
}
@@ -183,39 +175,39 @@ static struct PyMethodDef rpmds_methods[] = {
{"Count", (PyCFunction)rpmds_Count, METH_NOARGS,
"Deprecated, use len(ds) instead.\n" },
{"Ix", (PyCFunction)rpmds_Ix, METH_NOARGS,
- "ds.Ix -> Ix - Return current element index.\n" },
+ "ds.Ix -> Ix -- Return current element index.\n" },
{"DNEVR", (PyCFunction)rpmds_DNEVR, METH_NOARGS,
- "ds.DNEVR -> DNEVR - Return current DNEVR.\n" },
+ "ds.DNEVR -> DNEVR -- Return current DNEVR.\n" },
{"N", (PyCFunction)rpmds_N, METH_NOARGS,
- "ds.N -> N - Return current N.\n" },
+ "ds.N -> N -- Return current N.\n" },
{"EVR", (PyCFunction)rpmds_EVR, METH_NOARGS,
- "ds.EVR -> EVR - Return current EVR.\n" },
+ "ds.EVR -> EVR -- Return current EVR.\n" },
{"Flags", (PyCFunction)rpmds_Flags, METH_NOARGS,
- "ds.Flags -> Flags - Return current Flags.\n" },
+ "ds.Flags -> Flags -- Return current Flags.\n" },
{"TagN", (PyCFunction)rpmds_TagN, METH_NOARGS,
- "ds.TagN -> TagN - Return current TagN.\n" },
+ "ds.TagN -> TagN -- Return TagN (RPMTAG_*NAME)\n\n"
+ "the type of all dependencies in this set.\n" },
{"Color", (PyCFunction)rpmds_Color, METH_NOARGS,
- "ds.Color -> Color - Return current Color.\n" },
+ "ds.Color -> Color -- Return current Color.\n" },
{"SetNoPromote",(PyCFunction)rpmds_SetNoPromote, METH_VARARGS|METH_KEYWORDS,
- NULL},
- {"Notify", (PyCFunction)rpmds_Notify, METH_VARARGS|METH_KEYWORDS,
- NULL},
+ "ds.SetNoPromote(noPromote) -- Set noPromote for this instance.\n\n"
+ "If True non existing epochs are no longer equal to an epoch of 0."},
{"Sort", (PyCFunction)rpmds_Sort, METH_NOARGS,
NULL},
{"Find", (PyCFunction)rpmds_Find, METH_O,
- NULL},
+ "ds.find(other_ds) -- Return index of other_ds in ds"},
{"Merge", (PyCFunction)rpmds_Merge, METH_O,
NULL},
{"Search", (PyCFunction)rpmds_Search, METH_O,
"ds.Search(element) -> matching ds index (-1 on failure)\n\
-- Check that element dependency range overlaps some member of ds.\n\
-The current index in ds is positioned at overlapping member upon success.\n" },
- {"Rpmlib", (PyCFunction)rpmds_Rpmlib, METH_NOARGS|METH_STATIC,
- "ds.Rpmlib -> nds - Return internal rpmlib dependency set.\n"},
+Check that element dependency range overlaps some member of ds.\n\
+The current index in ds is positioned at overlapping member." },
+ {"Rpmlib", (PyCFunction)rpmds_Rpmlib, METH_VARARGS|METH_KEYWORDS|METH_STATIC,
+ "ds.Rpmlib -> nds -- Return internal rpmlib dependency set.\n"},
{"Compare", (PyCFunction)rpmds_Compare, METH_O,
- NULL},
+ "ds.compare(other) -- Compare current entries of self and other.\n\nReturns True if the entries match each other, False otherwise"},
{"Instance", (PyCFunction)rpmds_Instance, METH_NOARGS,
- NULL},
+ "ds.Instance() -- Return rpmdb key of corresponding package or 0."},
{NULL, NULL} /* sentinel */
};
@@ -305,10 +297,12 @@ static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kw
rpmTagVal tagN = RPMTAG_REQUIRENAME;
rpmds ds = NULL;
Header h = NULL;
- char * kwlist[] = {"obj", "tag", NULL};
+ rpmstrPool pool = NULL;
+ char * kwlist[] = {"obj", "tag", "pool", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:rpmds_new", kwlist,
- &obj, tagNumFromPyObject, &tagN))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&|O&:rpmds_new", kwlist,
+ &obj, tagNumFromPyObject, &tagN,
+ &poolFromPyObject, &pool))
return NULL;
if (PyTuple_Check(obj)) {
@@ -317,16 +311,16 @@ static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kw
rpmsenseFlags flags = RPMSENSE_ANY;
/* TODO: if flags are specified, evr should be required too */
if (PyArg_ParseTuple(obj, "s|O&s", &name, depflags, &flags, &evr)) {
- ds = rpmdsSingle(tagN, name, evr, flags);
+ ds = rpmdsSinglePool(pool, tagN, name, evr, flags);
} else {
PyErr_SetString(PyExc_ValueError, "invalid dependency tuple");
return NULL;
}
} else if (hdrFromPyObject(obj, &h)) {
if (tagN == RPMTAG_NEVR) {
- ds = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
+ ds = rpmdsThisPool(pool, h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
} else {
- ds = rpmdsNew(h, tagN, 0);
+ ds = rpmdsNewPool(pool, h, tagN, 0);
}
} else {
PyErr_SetString(PyExc_TypeError, "header or tuple expected");
@@ -337,11 +331,15 @@ static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kw
}
static char rpmds_doc[] =
-"";
+ "rpm.ds (dependendcy set) gives a more convenient access to dependencies\n\n"
+ "It can hold multiple entries of Name Flags and EVR.\n"
+ "It typically represents all dependencies of one kind of a package\n"
+ "e.g. all Requires or all Conflicts.\n"
+ ;
PyTypeObject rpmds_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".ds", /* tp_name */
+ "rpm.ds", /* tp_name */
sizeof(rpmdsObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c
index 41f494108..85fb0cd24 100644
--- a/python/rpmfd-py.c
+++ b/python/rpmfd-py.c
@@ -8,6 +8,8 @@ struct rpmfdObject_s {
PyObject_HEAD
PyObject *md_dict;
FD_t fd;
+ char *mode;
+ char *flags;
};
FD_t rpmfdGetFd(rpmfdObject *fdo)
@@ -43,14 +45,21 @@ static PyObject *err_closed(void)
return NULL;
}
-static FD_t openPath(const char *path, const char *mode, const char *flags)
+static FD_t openPath(const char *path, const char *mode)
{
FD_t fd;
- char *m = rstrscat(NULL, mode, ".", flags, NULL);
Py_BEGIN_ALLOW_THREADS
- fd = Fopen(path, m);
+ fd = Fopen(path, mode);
+ Py_END_ALLOW_THREADS;
+ return fd;
+}
+
+static FD_t openFd(FD_t ofd, const char *mode)
+{
+ FD_t fd;
+ Py_BEGIN_ALLOW_THREADS
+ fd = Fdopen(ofd, mode);
Py_END_ALLOW_THREADS;
- free(m);
return fd;
}
@@ -59,6 +68,7 @@ static int rpmfd_init(rpmfdObject *s, PyObject *args, PyObject *kwds)
char *kwlist[] = { "obj", "mode", "flags", NULL };
const char *mode = "r";
const char *flags = "ufdio";
+ char *rpmio_mode = NULL;
PyObject *fo = NULL;
FD_t fd = NULL;
int fdno;
@@ -67,8 +77,10 @@ static int rpmfd_init(rpmfdObject *s, PyObject *args, PyObject *kwds)
&fo, &mode, &flags))
return -1;
+ rpmio_mode = rstrscat(NULL, mode, ".", flags, NULL);
+
if (PyBytes_Check(fo)) {
- fd = openPath(PyBytes_AsString(fo), mode, flags);
+ fd = openPath(PyBytes_AsString(fo), rpmio_mode);
} else if (PyUnicode_Check(fo)) {
PyObject *enc = NULL;
int rc;
@@ -78,26 +90,38 @@ static int rpmfd_init(rpmfdObject *s, PyObject *args, PyObject *kwds)
rc = utf8FromPyObject(fo, &enc);
#endif
if (rc) {
- fd = openPath(PyBytes_AsString(enc), mode, flags);
+ fd = openPath(PyBytes_AsString(enc), rpmio_mode);
Py_DECREF(enc);
}
+ } else if (rpmfdObject_Check(fo)) {
+ rpmfdObject *fdo = (rpmfdObject *)fo;
+ fd = openFd(fdDup(Fileno(fdo->fd)), rpmio_mode);
} else if ((fdno = PyObject_AsFileDescriptor(fo)) >= 0) {
- fd = fdDup(fdno);
+ fd = openFd(fdDup(fdno), rpmio_mode);
} else {
PyErr_SetString(PyExc_TypeError, "path or file object expected");
}
if (fd != NULL) {
- /* TODO: remember our filename, mode & flags */
Fclose(s->fd); /* in case __init__ was called again */
+ free(s->mode);
+ free(s->flags);
s->fd = fd;
+ s->mode = rstrdup(mode);
+ s->flags = rstrdup(flags);
} else {
PyErr_SetString(PyExc_IOError, Fstrerror(fd));
}
+ free(rpmio_mode);
return (fd == NULL) ? -1 : 0;
}
+static PyObject *rpmfd_open(PyObject *cls, PyObject *args, PyObject *kwds)
+{
+ return PyObject_Call(cls, args, kwds);
+}
+
static PyObject *do_close(rpmfdObject *s)
{
/* mimic python fileobject: close on closed file is not an error */
@@ -119,6 +143,8 @@ static void rpmfd_dealloc(rpmfdObject *s)
{
PyObject *res = do_close(s);
Py_XDECREF(res);
+ free(s->mode);
+ free(s->flags);
Py_TYPE(s)->tp_free((PyObject *)s);
}
@@ -272,6 +298,8 @@ static PyObject *rpmfd_write(rpmfdObject *s, PyObject *args, PyObject *kwds)
static char rpmfd_doc[] = "";
static struct PyMethodDef rpmfd_methods[] = {
+ { "open", (PyCFunction) rpmfd_open, METH_VARARGS|METH_KEYWORDS|METH_CLASS,
+ NULL },
{ "close", (PyCFunction) rpmfd_close, METH_NOARGS,
NULL },
{ "fileno", (PyCFunction) rpmfd_fileno, METH_NOARGS,
@@ -302,15 +330,27 @@ static PyObject *rpmfd_get_name(rpmfdObject *s)
return Py_BuildValue("s", Fdescr(s->fd));
}
+static PyObject *rpmfd_get_mode(rpmfdObject *s)
+{
+ return Py_BuildValue("s", s->mode);
+}
+
+static PyObject *rpmfd_get_flags(rpmfdObject *s)
+{
+ return Py_BuildValue("s", s->flags);
+}
+
static PyGetSetDef rpmfd_getseters[] = {
{ "closed", (getter)rpmfd_get_closed, NULL, NULL },
{ "name", (getter)rpmfd_get_name, NULL, NULL },
+ { "mode", (getter)rpmfd_get_mode, NULL, NULL },
+ { "flags", (getter)rpmfd_get_flags, NULL, NULL },
{ NULL },
};
PyTypeObject rpmfd_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".fd", /* tp_name */
+ "rpm.fd", /* tp_name */
sizeof(rpmfdObject), /* tp_size */
0, /* tp_itemsize */
/* methods */
diff --git a/python/rpmfi-py.c b/python/rpmfi-py.c
index 14e89df1f..a1a743a1d 100644
--- a/python/rpmfi-py.c
+++ b/python/rpmfi-py.c
@@ -5,6 +5,7 @@
#include "header-py.h"
#include "rpmfi-py.h"
+#include "rpmstrpool-py.h"
struct rpmfiObject_s {
PyObject_HEAD
@@ -56,6 +57,18 @@ rpmfi_FN(rpmfiObject * s, PyObject * unused)
}
static PyObject *
+rpmfi_FindFN(rpmfiObject * s, PyObject * args, PyObject * kwds)
+{
+ char * kwlist[] = {"filename", NULL};
+ PyObject * filename = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:FindFN", kwlist,
+ &filename))
+ return NULL;
+ return Py_BuildValue("i", rpmfiFindFN(s->fi, PyBytes_AsString(filename)));
+}
+
+
+static PyObject *
rpmfi_FFlags(rpmfiObject * s, PyObject * unused)
{
return Py_BuildValue("i", rpmfiFFlags(s->fi));
@@ -146,6 +159,25 @@ rpmfi_FClass(rpmfiObject * s, PyObject * unused)
}
static PyObject *
+rpmfi_FLinks(rpmfiObject * s, PyObject * unused)
+{
+ uint32_t nlinks;
+ const int * files;
+ PyObject * result;
+
+ nlinks = rpmfiFLinks(s->fi, &files);
+ if (nlinks==1) {
+ return Py_BuildValue("(i)", rpmfiFX(s->fi));
+ }
+
+ result = PyTuple_New(nlinks);
+ for (uint32_t i=0; i<nlinks; i++) {
+ PyTuple_SET_ITEM(result, i, PyInt_FromLong(files[i]));
+ }
+ return result;
+}
+
+static PyObject *
rpmfi_iternext(rpmfiObject * s)
{
PyObject * result = NULL;
@@ -206,47 +238,51 @@ rpmfi_iternext(rpmfiObject * s)
static struct PyMethodDef rpmfi_methods[] = {
{"FC", (PyCFunction)rpmfi_FC, METH_NOARGS,
- NULL},
+ "fi.FC() -- Return number of files entries."},
{"FX", (PyCFunction)rpmfi_FX, METH_NOARGS,
- NULL},
+ "fi.FX() -- Return current position of the iterator."},
{"DC", (PyCFunction)rpmfi_DC, METH_NOARGS,
- NULL},
+ "fi.DC() --Return number of directory entries."},
{"DX", (PyCFunction)rpmfi_DX, METH_NOARGS,
- NULL},
+ "fi.DX() -- Return number of directory entry matching current file."},
{"BN", (PyCFunction)rpmfi_BN, METH_NOARGS,
- NULL},
+ "fi.BN() -- Return base name of current file."},
{"DN", (PyCFunction)rpmfi_DN, METH_NOARGS,
- NULL},
+ "fi.DN() -- Return directory name of the current file."},
{"FN", (PyCFunction)rpmfi_FN, METH_NOARGS,
- NULL},
+ "fi.FN() -- Return the name/path of the current file."},
+ {"FindFN", (PyCFunction)rpmfi_FindFN, METH_VARARGS|METH_KEYWORDS,
+ "fi.FindFN(pathname) -- Return entry number of given pathname.\n\nReturn -1 if file is not found.\nLeading '.' in the given name is stripped before the search."},
{"FFlags", (PyCFunction)rpmfi_FFlags, METH_NOARGS,
- NULL},
+ "fi.FFlags() -- Return the flags of the current file."},
{"VFlags", (PyCFunction)rpmfi_VFlags, METH_NOARGS,
- NULL},
+ "fi.VFlags() -- Return the verify flags of the current file.\n\nSee RPMVERIFY_* (in rpmvf.h)"},
{"FMode", (PyCFunction)rpmfi_FMode, METH_NOARGS,
- NULL},
+ "fi.FMode() -- Return the mode flags of the current file."},
{"FState", (PyCFunction)rpmfi_FState, METH_NOARGS,
- NULL},
+ "fi.FState() -- Return the file state of the current file."},
{"MD5", (PyCFunction)rpmfi_Digest, METH_NOARGS,
- NULL},
+ "fi.() -- Return the checksum of the current file.\n\nDEPRECATED! Use fi.Digest instead!"},
{"Digest", (PyCFunction)rpmfi_Digest, METH_NOARGS,
- NULL},
+ "fi.() -- Return the checksum of the current file."},
{"FLink", (PyCFunction)rpmfi_FLink, METH_NOARGS,
- NULL},
+ "fi.() -- Return the link target of the current file.\n\nFor soft links only."},
{"FSize", (PyCFunction)rpmfi_FSize, METH_NOARGS,
- NULL},
+ "fi.() -- Return the size of the current file."},
{"FRdev", (PyCFunction)rpmfi_FRdev, METH_NOARGS,
- NULL},
+ "fi.() -- Return the device number of the current file.\n\nFor device files only."},
{"FMtime", (PyCFunction)rpmfi_FMtime, METH_NOARGS,
- NULL},
+ "fi.() -- Return the modification time of the current file."},
{"FUser", (PyCFunction)rpmfi_FUser, METH_NOARGS,
- NULL},
+ "fi.() -- Return the user name owning the current file."},
{"FGroup", (PyCFunction)rpmfi_FGroup, METH_NOARGS,
- NULL},
+ "fi.() -- Return the group name of the current file."},
{"FColor", (PyCFunction)rpmfi_FColor, METH_NOARGS,
- NULL},
+ "fi.() -- Return the color of the current file.\n\n2 for 64 bit binaries\n1 for 32 bit binaries\n0 for everything else"},
{"FClass", (PyCFunction)rpmfi_FClass, METH_NOARGS,
- NULL},
+ "fi.() -- Return the classification of the current file."},
+ {"FLinks", (PyCFunction)rpmfi_FLinks, METH_NOARGS,
+ "fi.() -- Return the number of hardlinks pointing to of the\ncurrent file."},
{NULL, NULL} /* sentinel */
};
@@ -299,13 +335,15 @@ static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kw
rpmfi fi = NULL;
rpmTagVal tagN = RPMTAG_BASENAMES;
int flags = 0;
- char * kwlist[] = {"header", "tag", "flags", NULL};
+ rpmstrPool pool = NULL;
+ char * kwlist[] = {"header", "tag", "flags", "pool", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|Oi:rpmfi_init", kwlist,
- hdrFromPyObject, &h, &to, &flags))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|OiO&:rpmfi_init", kwlist,
+ hdrFromPyObject, &h, &to, &flags,
+ poolFromPyObject, &pool))
return NULL;
- fi = rpmfiNew(NULL, h, tagN, flags);
+ fi = rpmfiNewPool(pool, h, tagN, flags);
if (fi == NULL) {
PyErr_SetString(PyExc_ValueError, "invalid file data in header");
@@ -316,11 +354,15 @@ static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kw
}
static char rpmfi_doc[] =
-"";
+"File iterator\n\n"
+"DEPRECATED! This old API mixes storing and iterating over the meta data\n"
+"of the files of a package. Use rpm.files and rpm.file data types as a\n"
+"much cleaner API.\n\n"
+"Iteration returns a tuple of\n(FN, FSize, FMode, FMtime, FFlags, FRdev, FInode, FNlink, FState,\n VFlags, FUser, FGroup, Digest)";
PyTypeObject rpmfi_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".fi", /* tp_name */
+ "rpm.fi", /* tp_name */
sizeof(rpmfiObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c
new file mode 100644
index 000000000..d69d1f2ee
--- /dev/null
+++ b/python/rpmfiles-py.c
@@ -0,0 +1,598 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmpgp.h>
+
+#include "header-py.h"
+#include "rpmfi-py.h"
+#include "rpmfiles-py.h"
+#include "rpmfd-py.h"
+#include "rpmarchive-py.h"
+#include "rpmstrpool-py.h"
+
+/* A single file from rpmfiles set, can't be independently instanciated */
+struct rpmfileObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmfiles files; /* reference to rpmfiles */
+ int ix; /* index to rpmfiles */
+};
+
+static void rpmfile_dealloc(rpmfileObject * s)
+{
+ s->files = rpmfilesFree(s->files);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static char rpmfile_doc[] =
+ "Gives access to the meta data of a single file.\n\n"
+ "Instances of this class are only available through an rpm.files object.";
+
+static PyObject *rpmfile_fx(rpmfileObject *s)
+{
+ return Py_BuildValue("i", s->ix);
+}
+
+static PyObject *rpmfile_dx(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesDI(s->files, s->ix));
+}
+
+static PyObject *rpmfile_name(rpmfileObject *s)
+{
+ char * fn = rpmfilesFN(s->files, s->ix);
+ PyObject *o = Py_BuildValue("s", fn);
+ free(fn);
+ return o;
+}
+
+static PyObject *rpmfile_basename(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesBN(s->files, s->ix));
+}
+
+static PyObject *rpmfile_dirname(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesDN(s->files, rpmfilesDI(s->files, s->ix)));
+}
+
+static PyObject *rpmfile_orig_name(rpmfileObject *s)
+{
+ char * fn = rpmfilesOFN(s->files, s->ix);
+ PyObject *o = Py_BuildValue("s", fn);
+ free(fn);
+ return o;
+}
+
+static PyObject *rpmfile_orig_basename(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesOBN(s->files, s->ix));
+}
+
+static PyObject *rpmfile_orig_dirname(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesODN(s->files, rpmfilesODI(s->files, s->ix)));
+}
+static PyObject *rpmfile_mode(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFMode(s->files, s->ix));
+}
+
+static PyObject *rpmfile_size(rpmfileObject *s)
+{
+ return Py_BuildValue("L", rpmfilesFSize(s->files, s->ix));
+}
+
+static PyObject *rpmfile_mtime(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFMtime(s->files, s->ix));
+}
+
+static PyObject *rpmfile_rdev(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFRdev(s->files, s->ix));
+}
+
+static PyObject *rpmfile_inode(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFInode(s->files, s->ix));
+}
+
+static PyObject *rpmfile_nlink(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFNlink(s->files, s->ix));
+}
+
+static PyObject *rpmfile_linkto(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFLink(s->files, s->ix));
+}
+
+static PyObject *rpmfile_user(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFUser(s->files, s->ix));
+}
+
+static PyObject *rpmfile_group(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFGroup(s->files, s->ix));
+}
+
+static PyObject *rpmfile_fflags(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFFlags(s->files, s->ix));
+}
+
+static PyObject *rpmfile_vflags(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesVFlags(s->files, s->ix));
+}
+
+static PyObject *rpmfile_color(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFColor(s->files, s->ix));
+}
+
+static PyObject *rpmfile_state(rpmfileObject *s)
+{
+ return Py_BuildValue("i", rpmfilesFState(s->files, s->ix));
+}
+
+static PyObject *rpmfile_digest(rpmfileObject *s)
+{
+ size_t diglen = 0;
+ const unsigned char *digest = rpmfilesFDigest(s->files, s->ix,
+ NULL, &diglen);
+ if (digest) {
+ char * hex = pgpHexStr(digest, diglen);
+ PyObject *o = Py_BuildValue("s", hex);
+ free(hex);
+ return o;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfile_class(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFClass(s->files, s->ix));
+}
+
+static PyObject *rpmfile_caps(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFCaps(s->files, s->ix));
+}
+
+static PyObject *rpmfile_langs(rpmfileObject *s)
+{
+ return Py_BuildValue("s", rpmfilesFLangs(s->files, s->ix));
+}
+
+static PyObject *rpmfile_links(rpmfileObject *s)
+{
+ PyObject *result = NULL;
+ const int * links = NULL;
+ uint32_t nlinks = rpmfilesFLinks(s->files, s->ix, &links);
+
+ if (nlinks == 0)
+ Py_RETURN_NONE;
+ else if (nlinks == 1)
+ links = &s->ix; /* file itself */
+
+ result = PyTuple_New(nlinks);
+ if (result) {
+ for (uint32_t i = 0; i < nlinks; i++) {
+ int lix = links[i];
+ PyObject * o;
+
+ if (lix == s->ix) {
+ /* file itself, return a reference instead of new object */
+ Py_INCREF(s);
+ o = (PyObject *) s;
+ } else {
+ o = rpmfile_Wrap(s->files, lix);
+ }
+
+ PyTuple_SET_ITEM(result, i, o);
+ }
+ }
+ return result;
+}
+
+/*
+ * Exported as "matches" instead of a rich comparison operator or such
+ * as this cannot be used for comparing file *object* equality,
+ * rpmfilesCompare() determines whether the file *contents* match.
+ */
+static PyObject *rpmfile_matches(rpmfileObject *s, PyObject *o)
+{
+ PyObject *result = NULL;
+ if (rpmfileObject_Check(o)) {
+ rpmfileObject *of = (rpmfileObject *)o;
+ int rc = rpmfilesCompare(s->files, s->ix, of->files, of->ix);
+ result = PyBool_FromLong(rc == 0);
+ } else {
+ PyErr_SetObject(PyExc_TypeError, o);
+ }
+ return result;
+}
+
+static PyObject *rpmfile_verify(rpmfileObject *s, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = { "omitMask", NULL };
+ rpmVerifyAttrs omitMask = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &omitMask))
+ return NULL;
+
+ return Py_BuildValue("i", rpmfilesVerify(s->files, s->ix, omitMask));
+}
+
+static PyGetSetDef rpmfile_getseters[] = {
+ { "fx", (getter) rpmfile_fx, NULL,
+ "index in header and rpm.files object" },
+ { "dx", (getter) rpmfile_dx, NULL,
+ "index of dirname entry" },
+ { "name", (getter) rpmfile_name, NULL,
+ "file name (path)" },
+ { "basename", (getter) rpmfile_basename, NULL, NULL },
+ { "dirname", (getter) rpmfile_dirname, NULL, NULL },
+ { "orig_name", (getter) rpmfile_orig_name, NULL,
+ "original file name (may differ due to relocation)" },
+ { "orig_basename", (getter) rpmfile_orig_basename, NULL,
+ "original base name (may differ due to relocation)" },
+ { "orig_dirname", (getter) rpmfile_orig_dirname, NULL,
+ "original dir name (may differ due to relocation)" },
+ { "mode", (getter) rpmfile_mode, NULL,
+ "mode flags / unix permissions" },
+ { "mtime", (getter) rpmfile_mtime, NULL,
+ "modification time (in unix time)" },
+ { "size", (getter) rpmfile_size, NULL,
+ "file size" },
+ { "rdev", (getter) rpmfile_rdev, NULL,
+ "device number - for device files only" },
+ { "inode", (getter) rpmfile_inode, NULL,
+ "inode number - contains fake, data used to identify hard liked files" },
+ { "fflags", (getter) rpmfile_fflags, NULL,
+ "file flags - see RPMFILE_* constants" },
+ { "vflags", (getter) rpmfile_vflags, NULL,
+ "verification flags - see RPMVERIFY_* (in rpmvf.h)" },
+ { "linkto", (getter) rpmfile_linkto, NULL,
+ "link target - symlinks only" },
+ { "color", (getter) rpmfile_color, NULL,
+ "file color - 2 for 64 bit binaries, 1 for 32 bit binaries, 0 else" },
+ { "nlink", (getter) rpmfile_nlink, NULL,
+ "number of hardlinks pointing to the same content as this file" },
+ { "links", (getter) rpmfile_links, NULL,
+ "list of file indexes that are hardlinked with this file" },
+ { "user", (getter) rpmfile_user, NULL,
+ "user name owning this file" },
+ { "group", (getter) rpmfile_group, NULL,
+ "group name owning this file" },
+ { "digest", (getter) rpmfile_digest, NULL,
+ "check sum of file content" },
+ { "class", (getter) rpmfile_class, NULL,
+ "classfication of file content based on libmagic/file(1)" },
+ { "state", (getter) rpmfile_state, NULL,
+ "file state - see RPMFILE_STATE_* constants" },
+ { "langs", (getter) rpmfile_langs, NULL,
+ "language the file provides (typically for doc files)" },
+ { "caps", (getter) rpmfile_caps, NULL,
+ "file capabilities" },
+ { NULL, NULL, NULL, NULL }
+};
+
+static struct PyMethodDef rpmfile_methods[] = {
+ { "matches", (PyCFunction) rpmfile_matches, METH_O,
+ NULL },
+ { "verify", (PyCFunction) rpmfile_verify, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+PyTypeObject rpmfile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.file", /* tp_name */
+ sizeof(rpmfileObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor) rpmfile_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)rpmfile_name, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmfile_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmfile_methods, /* tp_methods */
+ 0, /* tp_members */
+ rpmfile_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * rpmfile_Wrap(rpmfiles files, int ix)
+{
+ rpmfileObject *s = PyObject_New(rpmfileObject, &rpmfile_Type);
+ if (s == NULL) return NULL;
+
+ s->files = rpmfilesLink(files);
+ s->ix = ix;
+ return (PyObject *) s;
+}
+
+/* The actual rpmfiles info set */
+struct rpmfilesObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ rpmfiles files;
+};
+
+static void rpmfiles_dealloc(rpmfilesObject * s)
+{
+ s->files = rpmfilesFree(s->files);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject * rpmfiles_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+{
+ PyObject * to = NULL;
+ Header h = NULL;
+ rpmfiles files = NULL;
+ rpmTagVal tagN = RPMTAG_BASENAMES;
+ int flags = 0;
+ rpmstrPool pool = NULL;
+ char * kwlist[] = {"header", "tag", "flags", "pool", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|OiO&:rpmfiles_new", kwlist,
+ hdrFromPyObject, &h, &to, &flags,
+ poolFromPyObject, &pool))
+ return NULL;
+
+ files = rpmfilesNew(pool, h, tagN, flags);
+
+ if (files == NULL) {
+ PyErr_SetString(PyExc_ValueError, "invalid file data in header");
+ return NULL;
+ }
+
+ return rpmfiles_Wrap(subtype, files);
+}
+
+static Py_ssize_t rpmfiles_length(rpmfilesObject *s)
+{
+ return rpmfilesFC(s->files);
+}
+
+static PyObject * rpmfiles_getitem(rpmfilesObject *s, Py_ssize_t ix)
+{
+ if (ix >= 0 && ix < rpmfilesFC(s->files))
+ return rpmfile_Wrap(s->files, ix);
+
+ PyErr_SetObject(PyExc_IndexError, Py_BuildValue("i", ix));
+ return NULL;
+}
+
+static int rpmfiles_contains(rpmfilesObject *s, PyObject *value)
+{
+ const char *fn = NULL;
+
+ if (!PyArg_Parse(value, "s", &fn))
+ return -1;
+
+ return (rpmfilesFindFN(s->files, fn) >= 0) ? 1 : 0;
+}
+
+static PySequenceMethods rpmfiles_as_sequence = {
+ (lenfunc)rpmfiles_length, /* sq_length */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ (ssizeargfunc) rpmfiles_getitem, /* sq_item */
+ 0, /* sq_slice */
+ 0, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ (objobjproc)rpmfiles_contains, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0, /* sq_inplace_repeat */
+};
+
+static PyObject * rpmfiles_find(rpmfileObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ const char *fn = NULL;
+ int fx, orig = 0;
+ char * kwlist[] = {"filename", "orig", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &fn, &orig))
+ return NULL;
+
+ if (orig)
+ fx = rpmfilesFindOFN(s->files, fn);
+ else
+ fx = rpmfilesFindFN(s->files, fn);
+
+ if (fx >= 0)
+ return rpmfile_Wrap(s->files, fx);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfiles_archive(rpmfilesObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ char * kwlist[] = {"fd", "write", NULL};
+ rpmfdObject *fdo = NULL;
+ FD_t fd = NULL;
+ rpmfi archive = NULL;
+ int writer = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
+ rpmfdFromPyObject, &fdo, &writer)) {
+ return NULL;
+ }
+
+ fd = rpmfdGetFd(fdo);
+ if (writer) {
+ archive = rpmfiNewArchiveWriter(fd, s->files);
+ } else {
+ archive = rpmfiNewArchiveReader(fd, s->files, RPMFI_ITER_READ_ARCHIVE);
+ }
+
+ return rpmarchive_Wrap(&rpmarchive_Type, s->files, archive);
+}
+
+static PyObject *rpmfiles_subscript(rpmfilesObject *s, PyObject *item)
+{
+ PyObject *str = NULL;
+
+ /* treat numbers as sequence accesses */
+ if (PyInt_Check(item)) {
+ return rpmfiles_getitem(s, PyInt_AsSsize_t(item));
+ } else if (PyLong_Check(item)) {
+ return rpmfiles_getitem(s, PyLong_AsSsize_t(item));
+ }
+
+ /* handle slices by returning tuples of rpm.file items */
+ if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength, i, cur;
+ PyObject * result;
+
+ if (PySlice_GetIndicesEx(
+#if PY_MAJOR_VERSION < 3
+ (PySliceObject*)
+#endif
+ item, rpmfiles_length(s),
+ &start, &stop, &step, &slicelength) < 0) {
+ return NULL;
+ }
+
+ result = PyTuple_New(slicelength);
+ if (result) {
+ for (cur = start, i = 0; i < slicelength; cur += step, i++) {
+ PyTuple_SET_ITEM(result, i, rpmfiles_getitem(s, cur));
+ }
+ }
+ return result;
+ }
+
+ /* ... and strings as mapping access */
+ if (utf8FromPyObject(item, &str)) {
+ int fx = rpmfilesFindFN(s->files, PyBytes_AsString(str));
+ Py_DECREF(str);
+
+ if (fx >= 0) {
+ return rpmfile_Wrap(s->files, fx);
+ } else {
+ PyErr_SetObject(PyExc_KeyError, item);
+ }
+ } else {
+ PyErr_SetObject(PyExc_TypeError, item);
+ }
+
+ return NULL;
+}
+
+static PyMappingMethods rpmfiles_as_mapping = {
+ (lenfunc) rpmfiles_length, /* mp_length */
+ (binaryfunc) rpmfiles_subscript, /* mp_subscript */
+ 0, /* mp_ass_subscript */
+};
+
+static struct PyMethodDef rpmfiles_methods[] = {
+ { "archive", (PyCFunction) rpmfiles_archive, METH_VARARGS|METH_KEYWORDS,
+ "files.archive(fd, write=False) -- Return a rpm.archive object\n\n"
+ "Args:\n"
+ " fd : File to read from or write to.\n"
+ " write : True to get an archive writer, False for an archive reader"},
+ { "find", (PyCFunction) rpmfiles_find, METH_VARARGS|METH_KEYWORDS,
+ "files.find(filename, orig=False) -- Return index of given file name.\n\n"
+ " Return -1 if file is not found.\n"
+ " Leading \".\" in filename is ignored."},
+ { NULL, NULL, 0, NULL }
+};
+
+static char rpmfiles_doc[] =
+ "rpm.files(hdr, tag=RPMTAG_BASENAMES, flags=None, pool=None)\n\n"
+ "Stores the meta data of a package's files.\n\n"
+ "Args:\n"
+ "\thdr: The header object to get the data from.\n"
+ "\tflags : Controls which data to store and whether to create\n\t\tcopies or use the data from the header.\n\t\tBy default all data is copied.\n\t\tSee RPMFI_* constants in rpmfiles.h.\n"
+ "\tpool : rpm.strpool object to store the strings in.\n\t\tLeave empty to use global pool.\n"
+ "\ttag : Obsolete. Leave alone!\n\n"
+ "rpm.files is basically a sequence of rpm.file objects.\nNote that this is a read only data structure. To write file data you\nhave to write it directly into aheader object.";
+
+PyTypeObject rpmfiles_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.files", /* tp_name */
+ sizeof(rpmfilesObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor) rpmfiles_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ &rpmfiles_as_sequence, /* tp_as_sequence */
+ &rpmfiles_as_mapping, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmfiles_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmfiles_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc) rpmfiles_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * rpmfiles_Wrap(PyTypeObject *subtype, rpmfiles files)
+{
+ rpmfilesObject *s = (rpmfilesObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->files = files;
+ return (PyObject *) s;
+}
+
diff --git a/python/rpmfiles-py.h b/python/rpmfiles-py.h
new file mode 100644
index 000000000..2e27d3db4
--- /dev/null
+++ b/python/rpmfiles-py.h
@@ -0,0 +1,18 @@
+#ifndef H_RPMFILES_PY
+#define H_RPMFILES_PY
+
+#include <rpm/rpmfiles.h>
+
+typedef struct rpmfileObject_s rpmfileObject;
+typedef struct rpmfilesObject_s rpmfilesObject;
+
+extern PyTypeObject rpmfile_Type;
+extern PyTypeObject rpmfiles_Type;
+
+#define rpmfileObject_Check(v) ((v)->ob_type == &rpmfile_Type)
+#define rpmfilesObject_Check(v) ((v)->ob_type == &rpmfiles_Type)
+
+PyObject * rpmfile_Wrap(rpmfiles files, int ix);
+PyObject * rpmfiles_Wrap(PyTypeObject *subtype, rpmfiles files);
+
+#endif
diff --git a/python/rpmii-py.c b/python/rpmii-py.c
index 9209b54e5..180741479 100644
--- a/python/rpmii-py.c
+++ b/python/rpmii-py.c
@@ -1,7 +1,9 @@
#include "rpmsystem-py.h"
#include <rpm/rpmdb.h>
+#include <rpm/rpmtd.h>
+#include "rpmtd-py.h"
#include "rpmii-py.h"
#include "header-py.h"
@@ -36,18 +38,25 @@ struct rpmiiObject_s {
PyObject *md_dict; /*!< to look like PyModuleObject */
PyObject *ref; /* for db/ts refcounting */
rpmdbIndexIterator ii;
+ rpmtd keytd;
};
static PyObject *
rpmii_iternext(rpmiiObject * s)
{
- char * key;
- size_t keylen;
- if (s->ii == NULL || (rpmdbIndexIteratorNext(s->ii, (const void**)&key, &keylen)) != 0) {
- s->ii = rpmdbIndexIteratorFree(s->ii);
- return NULL;
+ PyObject *keyo = NULL;
+
+ if (s->ii != NULL) {
+ if (rpmdbIndexIteratorNextTd(s->ii, s->keytd) == 0) {
+ /* The keys must never be arrays so rpmtd_AsPyObj() wont work */
+ keyo = rpmtd_ItemAsPyobj(s->keytd, rpmtdClass(s->keytd));
+ rpmtdFreeData(s->keytd);
+ } else {
+ s->ii = rpmdbIndexIteratorFree(s->ii);
+ }
}
- return PyBytes_FromStringAndSize(key, keylen);
+
+ return keyo;
};
static PyObject *
@@ -75,6 +84,7 @@ static struct PyMethodDef rpmii_methods[] = {
static void rpmii_dealloc(rpmiiObject * s)
{
s->ii = rpmdbIndexIteratorFree(s->ii);
+ rpmtdFree(s->keytd);
Py_DECREF(s->ref);
Py_TYPE(s)->tp_free((PyObject *)s);
}
@@ -88,6 +98,9 @@ static PyNumberMethods rpmii_as_number = {
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_divide */
+#endif
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
@@ -102,7 +115,7 @@ static char rpmii_doc[] =
PyTypeObject rpmii_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".ii", /* tp_name */
+ "rpm.ii", /* tp_name */
sizeof(rpmiiObject), /* tp_size */
0, /* tp_itemsize */
(destructor) rpmii_dealloc, /* tp_dealloc */
@@ -150,6 +163,7 @@ PyObject * rpmii_Wrap(PyTypeObject *subtype, rpmdbIndexIterator ii, PyObject *s)
iio->ii = ii;
iio->ref = s;
+ iio->keytd = rpmtdNew();
Py_INCREF(iio->ref);
return (PyObject *) iio;
}
diff --git a/python/rpmkeyring-py.c b/python/rpmkeyring-py.c
index 7df847db7..d5f131e42 100644
--- a/python/rpmkeyring-py.c
+++ b/python/rpmkeyring-py.c
@@ -52,7 +52,7 @@ static char rpmPubkey_doc[] = "";
PyTypeObject rpmPubkey_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".pubkey", /* tp_name */
+ "rpm.pubkey", /* tp_name */
sizeof(rpmPubkeyObject), /* tp_size */
0, /* tp_itemsize */
(destructor) rpmPubkey_dealloc,/* tp_dealloc */
@@ -133,7 +133,7 @@ static char rpmKeyring_doc[] =
PyTypeObject rpmKeyring_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".keyring", /* tp_name */
+ "rpm.keyring", /* tp_name */
sizeof(rpmKeyringObject), /* tp_size */
0, /* tp_itemsize */
(destructor) rpmKeyring_dealloc,/* tp_dealloc */
diff --git a/python/rpmmacro-py.c b/python/rpmmacro-py.c
index 3eb0acb56..3cb1a51f5 100644
--- a/python/rpmmacro-py.c
+++ b/python/rpmmacro-py.c
@@ -2,6 +2,7 @@
#include <rpm/rpmmacro.h>
+#include "header-py.h" /* XXX for pyrpmError, doh */
#include "rpmmacro-py.h"
PyObject *
@@ -14,7 +15,7 @@ rpmmacro_AddMacro(PyObject * self, PyObject * args, PyObject * kwds)
&name, &val))
return NULL;
- addMacro(NULL, name, NULL, val, -1);
+ rpmPushMacro(NULL, name, NULL, val, -1);
Py_RETURN_NONE;
}
@@ -28,7 +29,7 @@ rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:DelMacro", kwlist, &name))
return NULL;
- delMacro(NULL, name);
+ rpmPopMacro(NULL, name);
Py_RETURN_NONE;
}
@@ -37,7 +38,7 @@ PyObject *
rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds)
{
const char *macro;
- PyObject *res;
+ PyObject *res = NULL;
int num = 0;
char * kwlist[] = {"macro", "numeric", NULL};
@@ -47,8 +48,11 @@ rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds)
if (num) {
res = Py_BuildValue("i", rpmExpandNumeric(macro));
} else {
- char *str = rpmExpand(macro, NULL);
- res = Py_BuildValue("s", str);
+ char *str = NULL;
+ if (rpmExpandMacros(NULL, macro, &str, 0) < 0)
+ PyErr_SetString(pyrpmError, "error expanding macro");
+ else
+ res = Py_BuildValue("s", str);
free(str);
}
return res;
diff --git a/python/rpmmi-py.c b/python/rpmmi-py.c
index 70bb1665b..379cafb38 100644
--- a/python/rpmmi-py.c
+++ b/python/rpmmi-py.c
@@ -1,6 +1,7 @@
#include "rpmsystem-py.h"
#include <rpm/rpmdb.h>
+#include <rpm/header.h>
#include "rpmmi-py.h"
#include "header-py.h"
@@ -36,20 +37,20 @@
* \code
* import rpm
* ts = rpm.TransactionSet()
- * mi = ts.dbMatch('name', "kernel")
+ * mi = ts.dbMatch('name', 'kernel')
* for h in mi:
- * print "%s-%s-%s" % (h['name'], h['version'], h['release'])
+ * print '%s-%s-%s' % (h['name'], h['version'], h['release'])
* \endcode
*
* Finally, here's an example that retrieves all packages whose name
- * matches the glob expression "XFree*":
+ * matches the glob expression 'XFree*':
* \code
* import rpm
* ts = rpm.TransactionSet()
* mi = ts.dbMatch()
- * mi.pattern('name', rpm.RPMMIRE_GLOB, "XFree*")
+ * mi.pattern('name', rpm.RPMMIRE_GLOB, 'XFree*')
* for h in mi:
- * print "%s-%s-%s" % (h['name'], h['version'], h['release'])
+ * print '%s-%s-%s' % (h['name'], h['version'], h['release'])
* \endcode
*
*/
@@ -74,6 +75,7 @@ rpmmi_iternext(rpmmiObject * s)
s->mi = rpmdbFreeIterator(s->mi);
return NULL;
}
+ headerLink(h);
return hdr_Wrap(&hdr_Type, h);
}
@@ -114,7 +116,7 @@ rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds)
static struct PyMethodDef rpmmi_methods[] = {
{"instance", (PyCFunction) rpmmi_Instance, METH_NOARGS,
- NULL },
+ "mi.instance() -- Return the number (db key) of the current header."},
{"count", (PyCFunction) rpmmi_Count, METH_NOARGS,
"Deprecated, use len(mi) instead.\n" },
{"pattern", (PyCFunction) rpmmi_Pattern, METH_VARARGS|METH_KEYWORDS,
@@ -149,6 +151,9 @@ static PyNumberMethods rpmmi_as_number = {
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_divide */
+#endif
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
@@ -159,11 +164,44 @@ static PyNumberMethods rpmmi_as_number = {
};
static char rpmmi_doc[] =
-"";
+ "rpm.mi match iterator object represents the result of a\n"
+ " database query.\n"
+ "\n"
+ "Instances of the rpm.mi object provide access to headers that match\n"
+ "certain criteria. Typically, a primary index is accessed to find\n"
+ "a set of headers that contain a key, and each header is returned\n"
+ "serially.\n"
+ "\n"
+ "To obtain a rpm.mi object to query the database used by a transaction,\n"
+ "the ts.match(tag,key,len) method is used.\n"
+ "\n"
+ "Here's an example that prints the name of all installed packages:\n"
+ " import rpm\n"
+ " ts = rpm.TransactionSet()\n"
+ " for h in ts.dbMatch():\n"
+ " print h['name']\n"
+ "\n"
+ "Here's a more typical example that uses the Name index to retrieve\n"
+ "all installed kernel(s):\n"
+ " import rpm\n"
+ " ts = rpm.TransactionSet()\n"
+ " mi = ts.dbMatch('name', 'kernel')\n"
+ " for h in mi:\n"
+ " print '%s-%s-%s' % (h['name'], h['version'], h['release'])\n"
+ "\n"
+ "Finally, here's an example that retrieves all packages whose name\n"
+ "matches the glob expression 'XFree*':\n"
+ " import rpm\n"
+ " ts = rpm.TransactionSet()\n"
+ " mi = ts.dbMatch()\n"
+ " mi.pattern('name', rpm.RPMMIRE_GLOB, 'XFree*')\n"
+ " for h in mi:\n"
+ " print '%s-%s-%s' % (h['name'], h['version'], h['release'])\n"
+;
PyTypeObject rpmmi_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".mi", /* tp_name */
+ "rpm.mi", /* tp_name */
sizeof(rpmmiObject), /* tp_size */
0, /* tp_itemsize */
(destructor) rpmmi_dealloc, /* tp_dealloc */
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index a4fe217dd..d1390e889 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -8,14 +8,17 @@
#include <rpm/rpmmacro.h>
#include "header-py.h"
+#include "rpmarchive-py.h"
#include "rpmds-py.h"
#include "rpmfd-py.h"
#include "rpmfi-py.h"
+#include "rpmfiles-py.h"
#include "rpmkeyring-py.h"
#include "rpmmi-py.h"
#include "rpmii-py.h"
#include "rpmps-py.h"
#include "rpmmacro-py.h"
+#include "rpmstrpool-py.h"
#include "rpmtd-py.h"
#include "rpmte-py.h"
#include "rpmts-py.h"
@@ -46,10 +49,18 @@ static PyObject * signalCaught(PyObject *self, PyObject *o)
static PyObject * checkSignals(PyObject * self)
{
- rpmdbCheckSignals();
- Py_RETURN_NONE;
+ return Py_BuildValue("i", rpmsqPoll());
+}
+
+static PyObject * blockSignals(PyObject * self, PyObject *arg)
+{
+ int block;
+ if (!PyArg_Parse(arg, "p", &block)) return NULL;
+
+ return Py_BuildValue("i", rpmsqBlock(block ? SIG_BLOCK : SIG_UNBLOCK));
}
+
static PyObject * setLogFile (PyObject * self, PyObject *arg)
{
FILE *fp;
@@ -131,56 +142,83 @@ static PyObject * reloadConfig(PyObject * self, PyObject * args, PyObject *kwds)
return PyBool_FromLong(rc == 0);
}
+static PyObject * setInterruptSafety(PyObject * self, PyObject * args, PyObject *kwds)
+{
+ int on = 1;
+ PyObject * obj;
+ char * kwlist[] = { "on", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj))
+ return NULL;
+ if (obj) {
+ on = PyObject_IsTrue(obj);
+ }
+ rpmsqSetInterruptSafety(on);
+ Py_RETURN_NONE;
+}
+
static PyMethodDef rpmModuleMethods[] = {
{ "addMacro", (PyCFunction) rpmmacro_AddMacro, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "rpmPushMacro(macro, value)\n"
+ },
{ "delMacro", (PyCFunction) rpmmacro_DelMacro, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "rpmPopMacro(macro)\n"
+ },
{ "expandMacro", (PyCFunction) rpmmacro_ExpandMacro, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "expandMacro(string, numeric=False) -- expands a string containing macros\n\n"
+ "Returns an int if numeric is True. 'Y' or 'y' returns 1,\n'N' or 'n' returns 0\nAn undefined macro returns 0."},
{ "archscore", (PyCFunction) archScore, METH_O,
- NULL },
+ "archscore(archname) -- How well does an architecture fit on this machine\n\n"
+ "0 for non matching arch names\n1 for best arch\nhigher numbers for less fitting arches\n(e.g. 2 for \"i586\" on an i686 machine)" },
{ "signalCaught", (PyCFunction) signalCaught, METH_O,
- NULL },
+ "signalCaught(signo) -- Returns True if signal was caught." },
{ "checkSignals", (PyCFunction) checkSignals, METH_NOARGS,
- NULL },
+ "checkSignals() -- Check for and exit on termination signals."},
+ { "blockSignals", (PyCFunction) blockSignals, METH_O,
+ "blocksignals(True/False) -- Block/unblock signals, refcounted."},
{ "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS|METH_KEYWORDS,
NULL },
{ "log", (PyCFunction) doLog, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "log(level, msg) -- Write msg to log if level is selected to be logged.\n\n"
+ "level must be one of the RPMLOG_* constants."},
{ "setLogFile", (PyCFunction) setLogFile, METH_O,
- NULL },
+ "setLogFile(file) -- set file to write log messages to or None." },
{ "versionCompare", (PyCFunction) versionCompare, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "versionCompare(version0, version1) -- compares two version strings\n\n"
+ "Returns 1 if version0 > version1\n"
+ "Returns 0 if version0 == version1\n"
+ "Returns -1 if version0 < version1\n"},
{ "labelCompare", (PyCFunction) labelCompare, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "labelCompare(version0, version1) -- as versionCompare()\n\n"
+ "but arguments are tuples of of strings for (epoch, version, release)"},
{ "setVerbosity", (PyCFunction) setVerbosity, METH_O,
- NULL },
+ "setVerbosity(level) -- Set log level. See RPMLOG_* constants." },
{ "setEpochPromote", (PyCFunction) setEpochPromote, METH_O,
- NULL },
+ "setEpochPromote(bool) -- Set if no epoch shall be treated as epoch 0" },
{ "setStats", (PyCFunction) setStats, METH_O,
- NULL },
+ "setStats(bool) -- Set if timing stats are printed after a transaction."},
{ "reloadConfig", (PyCFunction) reloadConfig, METH_VARARGS|METH_KEYWORDS,
- NULL },
-
+ "reloadConfig(target=None) -- Reload config from files.\n\n"
+ "Set all macros and settings accordingly."},
+
+ { "setInterruptSafety", (PyCFunction) setInterruptSafety,
+ METH_VARARGS|METH_KEYWORDS,
+ "setInterruptSafety(on=True) -- Set if various signals get intercepted.\n\n"
+ "By default, librpm will trap various unix signals (like SIGINT and\n"
+ "SIGTERM), in order to avoid process exit while locks are held or\n"
+ "a transaction is being performed.\n\n"
+ "If this is not the desired behaviour it's recommended to call this\n"
+ "once only at process startup because currently signal handlers will\n"
+ "not be retroactively applied if a database is open."
+ },
{ NULL }
} ;
-/*
-* Force clean up of open iterators and dbs on exit.
-*/
-static void rpm_exithook(void)
-{
- rpmdbCheckTerminate(1);
-}
-
-static char rpm__doc__[] =
-"";
+static char rpm__doc__[] = "";
/*
* Add rpm tag dictionaries to the module
@@ -205,7 +243,6 @@ static void addRpmTags(PyObject *module)
Py_DECREF(pyname);
}
PyModule_AddObject(module, "tagnames", dict);
- rpmtdFreeData(names);
rpmtdFree(names);
}
@@ -215,14 +252,18 @@ static void addRpmTags(PyObject *module)
static int prepareInitModule(void)
{
if (PyType_Ready(&hdr_Type) < 0) return 0;
+ if (PyType_Ready(&rpmarchive_Type) < 0) return 0;
if (PyType_Ready(&rpmds_Type) < 0) return 0;
if (PyType_Ready(&rpmfd_Type) < 0) return 0;
if (PyType_Ready(&rpmfi_Type) < 0) return 0;
+ if (PyType_Ready(&rpmfile_Type) < 0) return 0;
+ if (PyType_Ready(&rpmfiles_Type) < 0) return 0;
if (PyType_Ready(&rpmKeyring_Type) < 0) return 0;
if (PyType_Ready(&rpmmi_Type) < 0) return 0;
if (PyType_Ready(&rpmii_Type) < 0) return 0;
if (PyType_Ready(&rpmProblem_Type) < 0) return 0;
if (PyType_Ready(&rpmPubkey_Type) < 0) return 0;
+ if (PyType_Ready(&rpmstrPool_Type) < 0) return 0;
#if 0
if (PyType_Ready(&rpmtd_Type) < 0) return 0;
#endif
@@ -287,14 +328,9 @@ static int initModule(PyObject *m)
{
PyObject * d;
- /*
- * treat error to register rpm cleanup hook as fatal, tracebacks
- * can and will leave stale locks around if we can't clean up
- */
- if (Py_AtExit(rpm_exithook) == -1)
- return 0;
-
- rpmReadConfigFiles(NULL, NULL);
+ /* failure to initialize rpm (crypto and all) is rather fatal too... */
+ if (rpmReadConfigFiles(NULL, NULL) == -1)
+ return 0;
d = PyModule_GetDict(m);
@@ -305,6 +341,9 @@ static int initModule(PyObject *m)
Py_INCREF(&hdr_Type);
PyModule_AddObject(m, "hdr", (PyObject *) &hdr_Type);
+ Py_INCREF(&rpmarchive_Type);
+ PyModule_AddObject(m, "archive", (PyObject *) &rpmarchive_Type);
+
Py_INCREF(&rpmds_Type);
PyModule_AddObject(m, "ds", (PyObject *) &rpmds_Type);
@@ -314,6 +353,12 @@ static int initModule(PyObject *m)
Py_INCREF(&rpmfi_Type);
PyModule_AddObject(m, "fi", (PyObject *) &rpmfi_Type);
+ Py_INCREF(&rpmfile_Type);
+ PyModule_AddObject(m, "file", (PyObject *) &rpmfile_Type);
+
+ Py_INCREF(&rpmfiles_Type);
+ PyModule_AddObject(m, "files", (PyObject *) &rpmfiles_Type);
+
Py_INCREF(&rpmKeyring_Type);
PyModule_AddObject(m, "keyring", (PyObject *) &rpmKeyring_Type);
@@ -329,6 +374,9 @@ static int initModule(PyObject *m)
Py_INCREF(&rpmPubkey_Type);
PyModule_AddObject(m, "pubkey", (PyObject *) &rpmPubkey_Type);
+ Py_INCREF(&rpmstrPool_Type);
+ PyModule_AddObject(m, "strpool", (PyObject *) &rpmstrPool_Type);
+
#if 0
Py_INCREF(&rpmtd_Type);
PyModule_AddObject(m, "td", (PyObject *) &rpmtd_Type);
@@ -344,6 +392,9 @@ static int initModule(PyObject *m)
PyModule_AddStringConstant(m, "__version__", RPMVERSION);
+ PyModule_AddObject(m, "header_magic",
+ PyBytes_FromStringAndSize((const char *)rpm_header_magic, 8));
+
#define REGISTER_ENUM(val) PyModule_AddIntConstant(m, #val, val)
REGISTER_ENUM(RPMTAG_NOT_FOUND);
@@ -362,12 +413,15 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMFILE_CONFIG);
REGISTER_ENUM(RPMFILE_DOC);
+ REGISTER_ENUM(RPMFILE_ICON);
REGISTER_ENUM(RPMFILE_MISSINGOK);
REGISTER_ENUM(RPMFILE_NOREPLACE);
+ REGISTER_ENUM(RPMFILE_SPECFILE);
REGISTER_ENUM(RPMFILE_GHOST);
REGISTER_ENUM(RPMFILE_LICENSE);
REGISTER_ENUM(RPMFILE_README);
REGISTER_ENUM(RPMFILE_PUBKEY);
+ REGISTER_ENUM(RPMFILE_ARTIFACT);
REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
@@ -395,6 +449,7 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMSENSE_KEYRING);
REGISTER_ENUM(RPMSENSE_STRONG);
REGISTER_ENUM(RPMSENSE_CONFIG);
+ REGISTER_ENUM(RPMSENSE_MISSINGOK);
REGISTER_ENUM(RPMTRANS_FLAG_TEST);
REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
@@ -403,8 +458,10 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPLUGINS);
REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
REGISTER_ENUM(RPMTRANS_FLAG_NOCONTEXTS);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOCAPS);
REGISTER_ENUM(RPMTRANS_FLAG_REPACKAGE);
REGISTER_ENUM(RPMTRANS_FLAG_REVERSE);
REGISTER_ENUM(RPMTRANS_FLAG_NOPRE);
@@ -415,11 +472,14 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMTRANS_FLAG_NOPREUN);
REGISTER_ENUM(RPMTRANS_FLAG_NOPOSTUN);
REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERPOSTUN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPRETRANS);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPOSTTRANS);
REGISTER_ENUM(RPMTRANS_FLAG_NOMD5);
REGISTER_ENUM(RPMTRANS_FLAG_NOFILEDIGEST);
REGISTER_ENUM(RPMTRANS_FLAG_NOSUGGEST);
REGISTER_ENUM(RPMTRANS_FLAG_ADDINDEPS);
REGISTER_ENUM(RPMTRANS_FLAG_NOCONFIGS);
+ REGISTER_ENUM(RPMTRANS_FLAG_DEPLOOPS);
REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
@@ -451,6 +511,7 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMCALLBACK_SCRIPT_START);
REGISTER_ENUM(RPMCALLBACK_SCRIPT_STOP);
REGISTER_ENUM(RPMCALLBACK_INST_STOP);
+ REGISTER_ENUM(RPMCALLBACK_ELEM_PROGRESS);
REGISTER_ENUM(RPMPROB_BADARCH);
REGISTER_ENUM(RPMPROB_BADOS);
@@ -486,10 +547,10 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMVSF_NOHDRCHK);
REGISTER_ENUM(RPMVSF_NEEDPAYLOAD);
REGISTER_ENUM(RPMVSF_NOSHA1HEADER);
- REGISTER_ENUM(RPMVSF_NOMD5HEADER);
+ REGISTER_ENUM(RPMVSF_NOSHA256HEADER);
REGISTER_ENUM(RPMVSF_NODSAHEADER);
REGISTER_ENUM(RPMVSF_NORSAHEADER);
- REGISTER_ENUM(RPMVSF_NOSHA1);
+ REGISTER_ENUM(RPMVSF_NOPAYLOAD);
REGISTER_ENUM(RPMVSF_NOMD5);
REGISTER_ENUM(RPMVSF_NODSA);
REGISTER_ENUM(RPMVSF_NORSA);
@@ -521,6 +582,20 @@ static int initModule(PyObject *m)
REGISTER_ENUM(HEADERCONV_COMPRESSFILELIST);
REGISTER_ENUM(HEADERCONV_RETROFIT_V3);
+ REGISTER_ENUM(RPMVERIFY_NONE);
+ REGISTER_ENUM(RPMVERIFY_FILEDIGEST);
+ REGISTER_ENUM(RPMVERIFY_FILESIZE);
+ REGISTER_ENUM(RPMVERIFY_LINKTO);
+ REGISTER_ENUM(RPMVERIFY_USER);
+ REGISTER_ENUM(RPMVERIFY_GROUP);
+ REGISTER_ENUM(RPMVERIFY_MTIME);
+ REGISTER_ENUM(RPMVERIFY_MODE);
+ REGISTER_ENUM(RPMVERIFY_RDEV);
+ REGISTER_ENUM(RPMVERIFY_CAPS);
+ REGISTER_ENUM(RPMVERIFY_READLINKFAIL);
+ REGISTER_ENUM(RPMVERIFY_READFAIL);
+ REGISTER_ENUM(RPMVERIFY_LSTATFAIL);
+
return 1;
}
diff --git a/python/rpmps-py.c b/python/rpmps-py.c
index 3ee9d4a9a..bdc899a60 100644
--- a/python/rpmps-py.c
+++ b/python/rpmps-py.c
@@ -72,7 +72,7 @@ static void rpmprob_dealloc(rpmProblemObject *s)
PyTypeObject rpmProblem_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".prob", /* tp_name */
+ "rpm.prob", /* tp_name */
sizeof(rpmProblemObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
diff --git a/python/rpmsmodule.c b/python/rpmsmodule.c
index a8289b5f6..72465221d 100644
--- a/python/rpmsmodule.c
+++ b/python/rpmsmodule.c
@@ -5,33 +5,36 @@
static char rpms__doc__[] =
"";
+static int parseSignArgs(PyObject * args, PyObject *kwds,
+ const char **path, struct rpmSignArgs *sargs)
+{
+ char * kwlist[] = { "path", "keyid", "hashalgo", NULL };
+
+ memset(sargs, 0, sizeof(*sargs));
+ return PyArg_ParseTupleAndKeywords(args, kwds, "s|si", kwlist,
+ path, &sargs->keyid, &sargs->hashalgo);
+}
+
static PyObject * addSign(PyObject * self, PyObject * args, PyObject *kwds)
{
const char *path = NULL;
- const char *passPhrase = NULL;
- char * kwlist[] = { "path", "passPhrase", "keyid", "hashalgo", NULL };
- struct rpmSignArgs sig, *sigp = NULL;
+ struct rpmSignArgs sargs;
- memset(&sig, 0, sizeof(sig));
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|si", kwlist,
- &path, &passPhrase, &sig.keyid, &sig.hashalgo))
+ if (parseSignArgs(args, kwds, &path, &sargs))
return NULL;
- if (sig.keyid || sig.hashalgo)
- sigp = &sig;
-
- return PyBool_FromLong(rpmPkgSign(path, sigp, passPhrase) == 0);
+ return PyBool_FromLong(rpmPkgSign(path, &sargs) == 0);
}
static PyObject * delSign(PyObject * self, PyObject * args, PyObject *kwds)
{
const char *path = NULL;
- char * kwlist[] = { "path", NULL };
+ struct rpmSignArgs sargs;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &path))
+ if (parseSignArgs(args, kwds, &path, &sargs))
return NULL;
- return PyBool_FromLong(rpmPkgDelSign(path) == 0);
+ return PyBool_FromLong(rpmPkgDelSign(path, &sargs) == 0);
}
/*
diff --git a/python/rpmstrpool-py.c b/python/rpmstrpool-py.c
new file mode 100644
index 000000000..356bd1de5
--- /dev/null
+++ b/python/rpmstrpool-py.c
@@ -0,0 +1,156 @@
+#include "rpmsystem-py.h"
+#include <rpm/rpmstrpool.h>
+#include "rpmstrpool-py.h"
+
+struct rpmstrPoolObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmstrPool pool;
+};
+
+static char strpool_doc[] = "";
+
+static void strpool_dealloc(rpmstrPoolObject *s)
+{
+ s->pool = rpmstrPoolFree(s->pool);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject *strpool_new(PyTypeObject *subtype,
+ PyObject *args, PyObject *kwds)
+{
+ return rpmstrPool_Wrap(subtype, NULL);
+}
+
+static PyObject *strpool_str2id(rpmstrPoolObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ char * kwlist[] = { "str", "create", NULL };
+ const char *str = NULL;
+ int create = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &str, &create))
+ return NULL;
+
+ return PyLong_FromLong(rpmstrPoolId(s->pool, str, create));
+}
+
+static PyObject *strpool_id2str(rpmstrPoolObject *s, PyObject *item)
+{
+ PyObject *ret = NULL;
+ rpmsid id = 0;
+
+ if (PyArg_Parse(item, "I", &id)) {
+ const char *str = rpmstrPoolStr(s->pool, id);
+
+ if (str)
+ ret = PyBytes_FromString(str);
+ else
+ PyErr_SetObject(PyExc_KeyError, item);
+ }
+ return ret;
+}
+
+static PyObject *strpool_freeze(rpmstrPoolObject *s,
+ PyObject *args, PyObject *kwds)
+{
+ char * kwlist[] = { "keephash", NULL };
+ int keephash = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &keephash))
+ return NULL;
+
+ rpmstrPoolFreeze(s->pool, keephash);
+ Py_RETURN_NONE;
+}
+
+static PyObject *strpool_unfreeze(rpmstrPoolObject *s)
+{
+ rpmstrPoolUnfreeze(s->pool);
+ Py_RETURN_NONE;
+}
+
+static Py_ssize_t strpool_length(rpmstrPoolObject *s)
+{
+ return rpmstrPoolNumStr(s->pool);
+}
+
+static struct PyMethodDef strpool_methods[] = {
+ { "str2id", (PyCFunction)strpool_str2id, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "id2str", (PyCFunction)strpool_id2str, METH_O,
+ NULL },
+ { "freeze", (PyCFunction)strpool_freeze, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "unfreeze", (PyCFunction)strpool_unfreeze, METH_NOARGS,
+ NULL },
+ { NULL, NULL }
+};
+
+static PyMappingMethods strpool_as_mapping = {
+ (lenfunc) strpool_length, /* mp_length */
+ (binaryfunc) strpool_id2str, /* mp_subscript */
+ (objobjargproc) 0, /* mp_ass_subscript */
+};
+
+PyTypeObject rpmstrPool_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.strpool", /* tp_name */
+ sizeof(rpmstrPoolObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) strpool_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ &strpool_as_mapping, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ strpool_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ strpool_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ strpool_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * rpmstrPool_Wrap(PyTypeObject *subtype, rpmstrPool pool)
+{
+ rpmstrPoolObject *s = (rpmstrPoolObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ /* permit referencing a pre-existing pool as well */
+ s->pool = (pool != NULL) ? rpmstrPoolLink(pool) : rpmstrPoolCreate();
+
+ return (PyObject *) s;
+}
+
+int poolFromPyObject(PyObject *item, rpmstrPool *pool)
+{
+ rpmstrPoolObject *p = NULL;
+ if (PyArg_Parse(item, "O!", &rpmstrPool_Type, &p))
+ *pool = p->pool;
+ return (p != NULL);
+}
diff --git a/python/rpmstrpool-py.h b/python/rpmstrpool-py.h
new file mode 100644
index 000000000..b91c8f642
--- /dev/null
+++ b/python/rpmstrpool-py.h
@@ -0,0 +1,14 @@
+#ifndef H_RPMSTRPOOL_PY
+#define H_RPMSTRPOOL_PY
+
+#include <rpm/rpmtypes.h>
+
+typedef struct rpmstrPoolObject_s rpmstrPoolObject;
+
+extern PyTypeObject rpmstrPool_Type;
+
+PyObject * rpmstrPool_Wrap(PyTypeObject *subtype, rpmstrPool pool);
+
+int poolFromPyObject(PyObject *item, rpmstrPool *pool);
+
+#endif
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index 30f74561e..c8423e3dc 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -5,11 +5,10 @@
#include <sys/types.h>
#endif
+#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
-#include "config.h"
-
#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0205
typedef ssize_t Py_ssize_t;
typedef Py_ssize_t (*lenfunc)(PyObject *);
diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c
index ed3a1455a..247c7502a 100644
--- a/python/rpmtd-py.c
+++ b/python/rpmtd-py.c
@@ -11,7 +11,7 @@
/*
* Convert single tag data item to python object of suitable type
*/
-static PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
+PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
{
PyObject *res = NULL;
@@ -61,161 +61,3 @@ PyObject *rpmtd_AsPyobj(rpmtd td)
}
return res;
}
-
-#if 0
-struct rpmtdObject_s {
- PyObject_HEAD
- PyObject *md_dict;
- struct rpmtd_s td;
-};
-
-/* string format should never fail but do regular repr just in case it does */
-static PyObject *rpmtd_str(rpmtdObject *s)
-{
- PyObject *res = NULL;
- char *str = rpmtdFormat(&(s->td), RPMTD_FORMAT_STRING, NULL);
- if (str) {
- res = PyBytes_FromString(str);
- free(str);
- } else {
- res = PyObject_Repr((PyObject *)s);
- }
- return res;
-}
-
-static PyObject *rpmtd_iternext(rpmtdObject *s)
-{
- PyObject *next = NULL;
-
- if (rpmtdNext(&(s->td)) >= 0) {
- Py_INCREF(s);
- next = (PyObject*) s;
- }
- return next;
-}
-
-static PyObject *rpmtd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
-{
- rpmtdObject *s = NULL;
- Header h = NULL;
- rpmTagVal tag;
- int raw = 0;
- int noext = 0;
- headerGetFlags flags = (HEADERGET_EXT | HEADERGET_ALLOC);
- char *kwlist[] = { "header", "tag", "raw", "noext", NULL };
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|ii", kwlist,
- hdrFromPyObject, &h, tagNumFromPyObject, &tag,
- &raw, &noext))
- return NULL;
-
- if (raw) {
- flags |= HEADERGET_RAW;
- noext = 1; /* extensions with raw dont make sense */
- }
- if (noext) flags &= ~HEADERGET_EXT;
-
- if ((s = (rpmtdObject *)subtype->tp_alloc(subtype, 0)) == NULL)
- return NULL;
-
- headerGet(h, tag, &(s->td), flags);
-
- return (PyObject *) s;
-}
-
-static void rpmtd_dealloc(rpmtdObject * s)
-{
- rpmtdFreeData(&(s->td));
- Py_TYPE(s)->tp_free((PyObject *)s);
-}
-
-static int rpmtd_length(rpmtdObject *s)
-{
- return rpmtdCount(&(s->td));
-}
-
-static PyMappingMethods rpmtd_as_mapping = {
- (lenfunc) rpmtd_length, /* mp_length */
-};
-
-static PyMemberDef rpmtd_members[] = {
- { "type", T_INT, offsetof(rpmtdObject, td.type), READONLY, NULL },
- { NULL }
-};
-
-static PyObject *rpmtd_get_tag(rpmtdObject *s, void *closure)
-{
- return Py_BuildValue("i", rpmtdTag(&(s->td)));
-}
-
-static int rpmtd_set_tag(rpmtdObject *s, PyObject *value, void *closure)
-{
- rpmTagVal tag;
- if (!tagNumFromPyObject(value, &tag)) return -1;
-
- if (!rpmtdSetTag(&(s->td), tag)) {
- PyErr_SetString(PyExc_ValueError, "incompatible tag for data");
- return -1;
- }
- return 0;
-}
-
-static PyGetSetDef rpmtd_getseters[] = {
- { "tag", (getter)rpmtd_get_tag, (setter)rpmtd_set_tag, NULL },
- { NULL }
-};
-
-PyTypeObject rpmtd_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".td", /* tp_name */
- sizeof(rpmtdObject), /* tp_size */
- 0, /* tp_itemsize */
- (destructor) rpmtd_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- (getattrfunc)0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- &rpmtd_as_mapping, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)rpmtd_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)rpmtd_iternext, /* tp_iternext */
- 0, /* tp_methods */
- rpmtd_members, /* tp_members */
- rpmtd_getseters, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- rpmtd_new, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
-};
-
-int rpmtdFromPyObject(PyObject *obj, rpmtd *td)
-{
- if (rpmtdObject_Check(obj)) {
- *td = &(((rpmtdObject *)obj)->td);
- return 1;
- } else {
- PyErr_SetString(PyExc_TypeError, PYTHON_MODULENAME".td type expected");
- return 0;
- }
-}
-#endif
diff --git a/python/rpmtd-py.h b/python/rpmtd-py.h
index 4c95e89b4..c7ac4091c 100644
--- a/python/rpmtd-py.h
+++ b/python/rpmtd-py.h
@@ -7,6 +7,7 @@ extern PyTypeObject rpmtd_Type;
#define rpmtdObject_Check(v) ((v)->ob_type == &rpmtd_Type)
+PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass);
PyObject * rpmtd_AsPyobj(rpmtd td);
int rpmtdFromPyObject(PyObject *obj, rpmtd *td);
diff --git a/python/rpmte-py.c b/python/rpmte-py.c
index 6b338260f..6936e757e 100644
--- a/python/rpmte-py.c
+++ b/python/rpmte-py.c
@@ -3,6 +3,7 @@
#include "header-py.h" /* XXX tagNumFromPyObject */
#include "rpmds-py.h"
#include "rpmfi-py.h"
+#include "rpmfiles-py.h"
#include "rpmte-py.h"
#include "rpmps-py.h"
@@ -35,8 +36,9 @@
* - te.Key() Return the associated opaque key, i.e. 2nd arg ts.addInstall().
* - te.DS(tag) Return package dependency set.
* @param tag 'Providename', 'Requirename', 'Obsoletename', 'Conflictname'
- * - te.FI(tag) Return package file info set.
+ * - te.FI(tag) Return package file info set iterator (deprecated).
* @param tag 'Basenames'
+ * - te.Files() Return package file info set.
*/
struct rpmteObject_s {
@@ -182,6 +184,8 @@ rpmte_FI(rpmteObject * s, PyObject * args, PyObject * kwds)
{
rpmfi fi;
+ DEPRECATED_METHOD("use .Files() instead");
+
fi = rpmteFI(s->te);
if (fi == NULL) {
Py_RETURN_NONE;
@@ -189,57 +193,60 @@ rpmte_FI(rpmteObject * s, PyObject * args, PyObject * kwds)
return rpmfi_Wrap(&rpmfi_Type, rpmfiLink(fi));
}
+static PyObject *
+rpmte_Files(rpmteObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmfiles files = rpmteFiles(s->te);
+ if (files == NULL) {
+ Py_RETURN_NONE;
+ }
+ return rpmfiles_Wrap(&rpmfiles_Type, files);
+}
static struct PyMethodDef rpmte_methods[] = {
{"Type", (PyCFunction)rpmte_TEType, METH_NOARGS,
-"te.Type() -> Type\n\
-- Return element type ("PYTHON_MODULENAME".TR_ADDED | "PYTHON_MODULENAME".TR_REMOVED).\n" },
+ "te.Type() -- Return element type (rpm.TR_ADDED | rpm.TR_REMOVED).\n" },
{"N", (PyCFunction)rpmte_N, METH_NOARGS,
-"te.N() -> N\n\
-- Return element name.\n" },
+ "te.N() -- Return element name.\n" },
{"E", (PyCFunction)rpmte_E, METH_NOARGS,
-"te.E() -> E\n\
-- Return element epoch.\n" },
+ "te.E() -- Return element epoch.\n" },
{"V", (PyCFunction)rpmte_V, METH_NOARGS,
-"te.V() -> V\n\
-- Return element version.\n" },
+ "te.V() -- Return element version.\n" },
{"R", (PyCFunction)rpmte_R, METH_NOARGS,
-"te.R() -> R\n\
-- Return element release.\n" },
+ "te.R() -- Return element release.\n" },
{"A", (PyCFunction)rpmte_A, METH_NOARGS,
-"te.A() -> A\n\
-- Return element arch.\n" },
+ "te.A() -- Return element arch.\n" },
{"O", (PyCFunction)rpmte_O, METH_NOARGS,
-"te.O() -> O\n\
-- Return element os.\n" },
+ "te.O() -- Return element os.\n" },
{"NEVR", (PyCFunction)rpmte_NEVR, METH_NOARGS,
-"te.NEVR() -> NEVR\n\
-- Return element name-[epoch:]version-release.\n" },
+ "te.NEVR() -- Return element name-[epoch:]version-release.\n" },
{"NEVRA", (PyCFunction)rpmte_NEVRA, METH_NOARGS,
-"te.NEVRA() -> NEVRA\n\
-- Return element name-[epoch:]version-release.arch\n" },
+ "te.NEVRA() -- Return element name-[epoch:]version-release.arch\n" },
{"Color",(PyCFunction)rpmte_Color, METH_NOARGS,
- NULL},
+ "te.Color() -- Return package color bits."},
{"PkgFileSize",(PyCFunction)rpmte_PkgFileSize, METH_NOARGS,
- NULL},
+ "te.PkgFileSize() -- Return no. of bytes in package file (approx)."},
{"Parent", (PyCFunction)rpmte_Parent, METH_NOARGS,
- NULL},
+ "te.Parent() -- Return the parent element index."},
{"Problems",(PyCFunction)rpmte_Problems, METH_NOARGS,
- NULL},
+ "te.Problems() -- Return problems associated with this element."},
/* {"DependsOnKey",(PyCFunction)rpmte_DependsOnKey, METH_NOARGS,
NULL}, */
{"DBOffset",(PyCFunction)rpmte_DBOffset, METH_NOARGS,
- NULL},
+ "te.DBOffset() -- Return the Package's database instance number.\n\nTR_REMOVED only"},
{"Failed", (PyCFunction)rpmte_Failed, METH_NOARGS,
- NULL},
+ "te.Failed() -- Return if there are any related errors."},
{"Key", (PyCFunction)rpmte_Key, METH_NOARGS,
- NULL},
+ "te.Key() -- Return the associated opaque key aka user data\n\
+ as passed e.g. as data arg ts.addInstall()"},
{"DS", (PyCFunction)rpmte_DS, METH_VARARGS|METH_KEYWORDS,
-"te.DS(TagN) -> DS\n\
-- Return the TagN dependency set (or None). TagN is one of\n\
- 'Providename', 'Requirename', 'Obsoletename', 'Conflictname'\n" },
+"te.DS(TagN) -- Return the TagN dependency set (or None).\n\
+ TagN is one of 'Providename', 'Requirename', 'Obsoletename',\n\
+ 'Conflictname', 'Triggername', 'Recommendname', 'Suggestname',\n\
+ 'Supplementname', 'Enhancename'" },
{"FI", (PyCFunction)rpmte_FI, METH_VARARGS|METH_KEYWORDS,
-"te.FI(TagN) -> FI\n\
-- Return the TagN dependency set (or None). TagN must be 'Basenames'.\n" },
+"te.FI(TagN) -- Return file info iterator of element.\n\n DEPRECATED! Use .Files() instead.\n" },
+ {"Files", (PyCFunction)rpmte_Files, METH_NOARGS,
+"te.Files() -- Return file info set of element.\n" },
{NULL, NULL} /* sentinel */
};
@@ -250,7 +257,7 @@ static char rpmte_doc[] =
PyTypeObject rpmte_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".te", /* tp_name */
+ "rpm.te", /* tp_name */
sizeof(rpmteObject), /* tp_size */
0, /* tp_itemsize */
(destructor)0, /* tp_dealloc */
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index 1072f354e..d56a09c22 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -96,23 +96,26 @@
* @return None
*
* - ts.setFlags(transFlags) Set transaction set flags.
- * @param transFlags - bit(s) to controll transaction operations. The
+ * @param transFlags - bit(s) to control transaction operations. The
* following values can be logically OR'ed 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_NOSCRIPTS - do not execute package scripts
* - rpm.RPMTRANS_FLAG_NOTRIGGERS - do not run trigger scripts
+ * - rpm.RPMTRANS_FLAG_NO* - disable specific scripts and triggers
* - rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc
+ * - rpm.RPMTRANS_FLAG_NOPLUGINS - do not run plugins
+ * - rpm.RPMTRANS_FLAG_NOFILEDIGEST - disable checking checksums
* - 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.
+ * - rpm.RPMTRANS_FLAG_NOCONFIGS - skip config files
+ * - rpm.RPMTRANS_FLAG_DEPLOOPS - enable debugging for dependency loops
* @return previous transFlags
*
* - ts.setProbFilter(ignoreSet) Set transaction set problem filter.
@@ -164,7 +167,6 @@ static void die(PyObject *cb)
}
fprintf(stderr, "FATAL ERROR: python callback %s failed, aborting!\n",
pyfn ? pyfn : "???");
- rpmdbCheckTerminate(1);
exit(EXIT_FAILURE);
}
@@ -188,6 +190,24 @@ rpmts_AddInstall(rpmtsObject * s, PyObject * args)
}
static PyObject *
+rpmts_AddReinstall(rpmtsObject * s, PyObject * args)
+{
+ Header h = NULL;
+ PyObject * key;
+ int rc;
+
+ if (!PyArg_ParseTuple(args, "O&O:AddReinstall",
+ hdrFromPyObject, &h, &key))
+ return NULL;
+
+ rc = rpmtsAddReinstallElement(s->ts, h, key);
+ if (key && rc == 0) {
+ PyList_Append(s->keyList, key);
+ }
+ return PyBool_FromLong((rc == 0));
+}
+
+static PyObject *
rpmts_AddErase(rpmtsObject * s, PyObject * args)
{
Header h;
@@ -363,7 +383,6 @@ rpmts_HdrFromFdno(rpmtsObject * s, PyObject *arg)
if (rpmrc == RPMRC_OK) {
ho = hdr_Wrap(&hdr_Type, h);
- h = headerFree(h); /* ref held by python object */
} else {
Py_INCREF(Py_None);
ho = Py_None;
@@ -440,7 +459,7 @@ static PyObject *rpmts_setKeyring(rpmtsObject *s, PyObject *arg)
if (arg == Py_None || rpmKeyringFromPyObject(arg, &keyring)) {
return PyBool_FromLong(rpmtsSetKeyring(s->ts, keyring) == 0);
} else {
- PyErr_SetString(PyExc_TypeError, PYTHON_MODULENAME".keyring or None expected");
+ PyErr_SetString(PyExc_TypeError, "rpm.keyring or None expected");
return NULL;
}
}
@@ -609,6 +628,10 @@ rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
lkey = PyInt_AsLong(Key);
key = (char *)&lkey;
len = sizeof(lkey);
+ } else if (PyLong_Check(Key)) {
+ lkey = PyLong_AsLong(Key);
+ key = (char *)&lkey;
+ len = sizeof(lkey);
} else if (utf8FromPyObject(Key, &str)) {
key = PyBytes_AsString(str);
len = PyBytes_Size(str);
@@ -669,13 +692,55 @@ exit:
static struct PyMethodDef rpmts_methods[] = {
{"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS,
- NULL },
+ "ts.addInstall(hdr, data, mode) -- Add transaction element(s)\n"
+ "representing an installation or update of a package.\n\n"
+ "Args:\n"
+ " hdr : the header to be added\n"
+ " data : user data that will be passed to the transaction callback\n\t\tduring transaction execution\n"
+ " mode : optional argument that specifies if this package should be\n\t\tinstalled ('i'), upgraded ('u')"},
+ {"addReinstall", (PyCFunction) rpmts_AddReinstall, METH_VARARGS,
+ "ts.addReinstall(hdr, data) -- Adds transaction elements\nrepresenting a reinstall of an already installed package.\n\nSee addInstall for details."},
{"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "addErase(name) -- Add a transaction element representing an erase\nof an installed package.\n\n"
+ " name: the package name to be erased"},
{"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "ts.check( )-- Perform a dependency check on the transaction set.\n"
+ " After headers have been added to a transaction set,\n"
+ " a dependencycheck can be performed to make sure that\n"
+ " all package dependencies are satisfied.\n"
+ "Return None If there are no unresolved dependencies\n"
+ " Otherwise a list of complex tuples is returned,\n"
+ " one tuple per unresolved dependency, with\n"
+ "The format of the dependency tuple is:\n"
+ " ((packageName, packageVersion, packageRelease),\n"
+ " (reqName, reqVersion),\n"
+ " needsFlags,\n"
+ " suggestedPackage,\n"
+ " sense)\n"
+ " packageName, packageVersion, packageRelease are the name,\n"
+ " version, and release of the package that has the unresolved\n"
+ " dependency or conflict.\n"
+ " The reqName and reqVersion are the name and version of the\n"
+ " requirement or conflict.\n"
+ " The needsFlags is a bitfield that describes the versioned\n"
+ " nature of a requirement or conflict. The constants\n"
+ " rpm.RPMSENSE_LESS, rpm.RPMSENSE_GREATER, and\n"
+ " rpm.RPMSENSE_EQUAL can be logical ANDed with the needsFlags\n"
+ " to get versioned dependency information.\n"
+ " suggestedPackage is a tuple if the dependency check was aware\n"
+ " of a package that solves this dependency problem when the\n"
+ " dependency check was run. Packages that are added to the\n"
+ " transaction set as \"available\" are examined during the\n"
+ " dependency check as possible dependency solvers. The tuple\n"
+ " contains two values, (header, suggestedName). These are set to\n"
+ " the header of the suggested package and its name, respectively.\n"
+ " If there is no known package to solve the dependency problem,\n"
+ " suggestedPackage is None.\n"
+ " The constants rpm.RPMDEP_SENSE_CONFLICTS and\n"
+ " rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a\n"
+ " requirement or a conflict.\n"},
{"order", (PyCFunction) rpmts_Order, METH_NOARGS,
- NULL },
+ "ts.order() Do a topological sort of added element relations." },
{"problems", (PyCFunction) rpmts_Problems, METH_NOARGS,
"ts.problems() -> ps\n\
- Return current problem set.\n" },
@@ -684,18 +749,18 @@ static struct PyMethodDef rpmts_methods[] = {
- Run a transaction set, returning list of problems found.\n\
Note: The callback may not be None.\n" },
{"clean", (PyCFunction) rpmts_Clean, METH_NOARGS,
- NULL },
+ "ts.clean()-- Free memory needed only for dependency checks\nand ordering. Should not be needed in normal operation." },
{"clear", (PyCFunction) rpmts_Clear, METH_NOARGS,
"ts.clear() -> None\n\
Remove all elements from the transaction set\n" },
{"openDB", (PyCFunction) rpmts_OpenDB, METH_NOARGS,
-"ts.openDB() -> None\n\
-- Open the default transaction rpmdb.\n\
- Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
+"ts.openDB() -> None -- Open the default transaction rpmdb.\n\n\
+ Note: The transaction rpmdb is lazily opened,\n so ts.openDB() is seldom needed.\n" },
{"closeDB", (PyCFunction) rpmts_CloseDB, METH_NOARGS,
"ts.closeDB() -> None\n\
- Close the default transaction rpmdb.\n\
- Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
+ Note: ts.closeDB() disables lazy opens,\n\
+ and should hardly ever be used.\n" },
{"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS,
"ts.initDB() -> None\n\
- Initialize the default transaction rpmdb.\n\
@@ -710,15 +775,21 @@ Remove all elements from the transaction set\n" },
"ts.hdrFromFdno(fdno) -> hdr\n\
- Read a package header from a file descriptor.\n" },
{"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_O,
- NULL },
+ "ts.hdrCheck(hdrblob) -- Check header consistency,\nperforming headerGetEntry() the hard way.\n\n"
+ "Sanity checks on the header are performed while looking for a\n"
+ "header-only digest or signature to verify the blob. If found,\n"
+ "the digest or signature is verified.\n\n"
+ "\thdrblob : unloaded header blob\n"
+ "Return tuple (int status, message string)"},
{"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "pgpPrtPkts(octets) -- Print/parse a OpenPGP packet(s).\n\nReturn 0 on success." },
{"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "pgpImportPubkey(pubkey) -- Import public key packet." },
{"getKeyring", (PyCFunction) rpmts_getKeyring, METH_VARARGS|METH_KEYWORDS,
- NULL },
+ "ts.getKeyring(autoload=False) -- Return key ring object." },
{"setKeyring", (PyCFunction) rpmts_setKeyring, METH_O,
- NULL },
+ "ts.setKeyring(keyring) -- Set key ring used for checking signatures\n\n"
+ "Pass None for an empty key ring." },
{"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS,
"ts.dbMatch([TagN, [key]]) -> mi\n\
- Create a match iterator for the default transaction rpmdb.\n" },
@@ -856,13 +927,38 @@ static PyObject *rpmts_get_vsflags(rpmtsObject *s, void *closure)
}
static char rpmts_doc[] =
-"";
+ "A python rpm.ts object represents an RPM transaction set.\n"
+ "\n"
+ "The transaction set is the workhorse of RPM. It performs the\n"
+ "installation and upgrade of packages. The rpm.ts object is\n"
+ "instantiated by the TransactionSet function in the rpm module.\n"
+ "\n"
+ "The TransactionSet function takes two optional arguments. The first\n"
+ "argument is the root path. The second is the verify signature disable\n"
+ "flags, a set of the following bits:\n"
+ "\n"
+ "- rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers\n"
+ "- rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload\n"
+ " (if possible)\n"
+ "- rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest\n"
+ "- rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature\n"
+ "- rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest\n"
+ "- rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature\n"
+ "- rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature\n"
+ "\n"
+ "For convenience, there are the following masks:\n"
+ "- rpm._RPMVSF_NODIGESTS if set, don't check digest(s).\n"
+ "- rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s).\n\n"
+ "The transaction set offers an read only iterable interface for the\ntransaction elements added by the .addInstall(), .addErase() and\n.addReinstall() methods.";
static PyGetSetDef rpmts_getseters[] = {
/* only provide a setter until we have rpmfd wrappings */
- {"scriptFd", NULL, (setter)rpmts_set_scriptFd, NULL },
- {"tid", (getter)rpmts_get_tid, NULL, NULL },
- {"rootDir", (getter)rpmts_get_rootDir, NULL, NULL },
+ {"scriptFd", NULL, (setter)rpmts_set_scriptFd,
+ "write only, file descriptor the output of script gets written to." },
+ {"tid", (getter)rpmts_get_tid, NULL,
+ "read only, current transaction id, i.e. transaction time stamp."},
+ {"rootDir", (getter)rpmts_get_rootDir, NULL,
+ "read only, directory rpm treats as root of the file system." },
{"_color", (getter)rpmts_get_color, (setter)rpmts_set_color, NULL},
{"_prefcolor", (getter)rpmts_get_prefcolor, (setter)rpmts_set_prefcolor, NULL},
{"_flags", (getter)rpmts_get_flags, (setter)rpmts_set_flags, NULL},
@@ -872,7 +968,7 @@ static PyGetSetDef rpmts_getseters[] = {
PyTypeObject rpmts_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".ts", /* tp_name */
+ "rpm.ts", /* tp_name */
sizeof(rpmtsObject), /* tp_size */
0, /* tp_itemsize */
(destructor) rpmts_dealloc, /* tp_dealloc */
diff --git a/python/setup.py.in b/python/setup.py.in
index 14be973a3..dd56a47a9 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -2,7 +2,7 @@
from distutils.core import setup, Extension
import subprocess
-from glob import glob
+import os
def pkgconfig(what):
out = []
@@ -12,37 +12,50 @@ def pkgconfig(what):
out.append(token[2:])
return out
-def mksources(names):
- srcs = []
- for n in names:
- srcs.extend(glob('%s*.c' % n))
- return srcs
+cflags = ['-std=c99', '-Wno-strict-aliasing']
+additional_link_args = []
-cflags = ['-std=c99']
+# See if we're building in-tree
+if os.access('Makefile.am', os.F_OK):
+ cflags.append('-I../include')
+ additional_link_args.extend(['-Wl,-L../rpmio/.libs',
+ '-Wl,-L../lib/.libs',
+ '-Wl,-L../build/.libs',
+ '-Wl,-L../sign/.libs'])
+ os.environ['PKG_CONFIG_PATH'] = '..'
-rpmmod = Extension('@PYTHON_MODULENAME@._rpm',
- sources = mksources([
- 'header', 'rpmds', 'rpmfd', 'rpmfi', 'rpmii',
- 'rpmkeyring', 'rpmmacro', 'rpmmi', 'rpmps',
- 'rpmtd', 'rpmte', 'rpmts', 'rpmmodule',
- ]),
+
+rpmmod = Extension('rpm._rpm',
+ sources = [ 'header-py.c', 'rpmds-py.c', 'rpmfd-py.c',
+ 'rpmfi-py.c', 'rpmii-py.c', 'rpmkeyring-py.c',
+ 'rpmmacro-py.c', 'rpmmi-py.c', 'rpmps-py.c',
+ 'rpmstrpool-py.c', 'rpmfiles-py.c',
+ 'rpmarchive-py.c', 'rpmtd-py.c',
+ 'rpmte-py.c', 'rpmts-py.c', 'rpmmodule.c',
+ ],
include_dirs = pkgconfig('--cflags'),
- libraries = pkgconfig('--libs'),
- extra_compile_args = cflags
+ library_dirs = pkgconfig('--libs-only-L'),
+ libraries = pkgconfig('--libs-only-l'),
+ extra_compile_args = cflags,
+ extra_link_args = additional_link_args
)
-rpmbuild_mod = Extension('@PYTHON_MODULENAME@._rpmb',
- sources = mksources(['rpmbmodule', 'spec']),
+rpmbuild_mod = Extension('rpm._rpmb',
+ sources = ['rpmbmodule.c', 'spec-py.c'],
include_dirs = pkgconfig('--cflags'),
- libraries = pkgconfig('--libs') + ['rpmbuild'],
- extra_compile_args = cflags
+ library_dirs = pkgconfig('--libs-only-L'),
+ libraries = pkgconfig('--libs-only-l') + ['rpmbuild'],
+ extra_compile_args = cflags,
+ extra_link_args = additional_link_args
)
-rpmsign_mod = Extension('@PYTHON_MODULENAME@._rpms',
- sources = mksources(['rpmbmodule']),
+rpmsign_mod = Extension('rpm._rpms',
+ sources = ['rpmsmodule.c'],
include_dirs = pkgconfig('--cflags'),
- libraries = pkgconfig('--libs') + ['rpmsign'],
- extra_compile_args = cflags
+ library_dirs = pkgconfig('--libs-only-L'),
+ libraries = pkgconfig('--libs-only-l') + ['rpmsign'],
+ extra_compile_args = cflags,
+ extra_link_args = additional_link_args
)
setup(name='@PACKAGE_NAME@',
diff --git a/python/spec-py.c b/python/spec-py.c
index 82245200e..47c17400f 100644
--- a/python/spec-py.c
+++ b/python/spec-py.c
@@ -19,7 +19,7 @@
* For example
* \code
* import rpm
- * rpm.addMacro("_topdir","/path/to/topdir")
+ * rpm.rpmPushMacro("_topdir","/path/to/topdir")
* s=rpm.spec("foo.spec")
* print s.prep()
* \endcode
@@ -31,10 +31,10 @@
/* Header objects are in another module, some hoop jumping required... */
static PyObject *makeHeader(Header h)
{
- PyObject *rpmmod = PyImport_ImportModuleNoBlock(PYTHON_MODULENAME);
+ PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
if (rpmmod == NULL) return NULL;
- PyObject *ptr = CAPSULE_BUILD(h, PYTHON_MODULENAME"._C_Header");
+ PyObject *ptr = CAPSULE_BUILD(h, "rpm._C_Header");
PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
Py_XDECREF(ptr);
Py_XDECREF(rpmmod);
@@ -45,27 +45,63 @@ struct specPkgObject_s {
PyObject_HEAD
/*type specific fields */
rpmSpecPkg pkg;
+ specObject *source_spec;
};
+static void specPkg_dealloc(specPkgObject * s)
+{
+ Py_DECREF(s->source_spec);
+}
+
+static PyObject *pkgGetSection(rpmSpecPkg pkg, int section)
+{
+ char *sect = rpmSpecPkgGetSection(pkg, section);
+ if (sect != NULL) {
+ PyObject *ps = PyBytes_FromString(sect);
+ free(sect);
+ if (ps != NULL)
+ return ps;
+ }
+ Py_RETURN_NONE;
+}
+
static char specPkg_doc[] =
-"";
+"Package data parsed from spec file.";
static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
{
return makeHeader(rpmSpecPkgHeader(s->pkg));
}
+static PyObject * specpkg_get_fileFile(specPkgObject *s, void *closure)
+{
+ return pkgGetSection(s->pkg, RPMBUILD_FILE_FILE);
+}
+
+static PyObject * specpkg_get_fileList(specPkgObject *s, void *closure)
+{
+ return pkgGetSection(s->pkg, RPMBUILD_FILE_LIST);
+}
+
+static PyObject * specpkg_get_policyList(specPkgObject *s, void *closure)
+{
+ return pkgGetSection(s->pkg, RPMBUILD_POLICY);
+}
+
static PyGetSetDef specpkg_getseters[] = {
- { "header", (getter) specpkg_get_header, NULL, NULL },
- { NULL } /* sentinel */
+ { "header", (getter) specpkg_get_header, NULL, NULL },
+ { "fileFile", (getter) specpkg_get_fileFile, NULL, NULL },
+ { "fileList", (getter) specpkg_get_fileList, NULL, NULL },
+ { "policyList", (getter) specpkg_get_policyList, NULL, NULL },
+ { NULL } /* sentinel */
};
PyTypeObject specPkg_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".specpkg", /* tp_name */
+ "rpm.specpkg", /* tp_name */
sizeof(specPkgObject), /* tp_size */
0, /* tp_itemsize */
- 0, /* tp_dealloc */
+ (destructor) specPkg_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
@@ -127,6 +163,12 @@ static PyObject * getSection(rpmSpec spec, int section)
Py_RETURN_NONE;
}
+static PyObject *
+spec_get_parsed(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_NONE);
+}
+
static PyObject *
spec_get_prep(specObject * s, void *closure)
{
@@ -144,6 +186,11 @@ static PyObject * spec_get_install(specObject * s, void *closure)
return getSection(s->spec, RPMBUILD_INSTALL);
}
+static PyObject * spec_get_check(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_CHECK);
+}
+
static PyObject * spec_get_clean(specObject * s, void *closure)
{
return getSection(s->spec, RPMBUILD_CLEAN);
@@ -192,7 +239,7 @@ static PyObject * spec_get_packages(specObject *s, void *closure)
iter = rpmSpecPkgIterInit(s->spec);
while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
- PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
+ PyObject *po = specPkg_Wrap(&specPkg_Type, pkg, s);
if (!po) {
rpmSpecPkgIterFree(iter);
Py_DECREF(pkgList);
@@ -214,9 +261,11 @@ static char spec_doc[] = "RPM Spec file object";
static PyGetSetDef spec_getseters[] = {
{"sources", (getter) spec_get_sources, NULL, NULL },
+ {"parsed", (getter) spec_get_parsed, NULL, NULL},
{"prep", (getter) spec_get_prep, NULL, NULL },
{"build", (getter) spec_get_build, NULL, NULL },
{"install", (getter) spec_get_install, NULL, NULL },
+ {"check", (getter) spec_get_check, NULL, NULL },
{"clean", (getter) spec_get_clean, NULL, NULL },
{"packages", (getter) spec_get_packages, NULL, NULL },
{"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
@@ -263,7 +312,7 @@ static struct PyMethodDef spec_methods[] = {
PyTypeObject spec_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- PYTHON_MODULENAME".spec", /*tp_name*/
+ "rpm.spec", /*tp_name*/
sizeof(specObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) spec_dealloc, /*tp_dealloc*/
@@ -314,12 +363,14 @@ spec_Wrap(PyTypeObject *subtype, rpmSpec spec)
return (PyObject *) s;
}
-PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg)
+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source)
{
specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
if (s == NULL) return NULL;
s->pkg = pkg;
+ s->source_spec = source;
+ Py_INCREF(s->source_spec);
return (PyObject *) s;
}
diff --git a/python/spec-py.h b/python/spec-py.h
index 558fbf207..65b8dc3d7 100644
--- a/python/spec-py.h
+++ b/python/spec-py.h
@@ -13,6 +13,6 @@ extern PyTypeObject specPkg_Type;
#define specPkgObject_Check(v) ((v)->ob_type == &specPkg_Type)
PyObject * spec_Wrap(PyTypeObject *subtype, rpmSpec spec);
-PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg);
+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source);
#endif /* RPMPYTHON_SPEC */