summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorJinkun Jang <jinkun.jang@samsung.com>2013-03-12 15:17:20 +0900
committerJinkun Jang <jinkun.jang@samsung.com>2013-03-12 15:17:20 +0900
commit7df2385c2f6c93f96e00bc87f2086066cae89ecc (patch)
tree79d5c20a494622eb084de831a2a51530cd421e33 /python
parentb7a3bffb8e0341b7e4ef69def268bca3a7f279ff (diff)
downloadrpm-tizen_2.1.tar.gz
rpm-tizen_2.1.tar.bz2
rpm-tizen_2.1.zip
Diffstat (limited to 'python')
-rw-r--r--python/Makefile.am51
-rw-r--r--python/Makefile.in742
-rw-r--r--python/header-py.c855
-rw-r--r--python/header-py.h26
-rw-r--r--python/rpm/__init__.py84
-rw-r--r--python/rpm/transaction.py156
-rw-r--r--python/rpmbmodule.c97
-rw-r--r--python/rpmds-py.c405
-rw-r--r--python/rpmds-py.h16
-rw-r--r--python/rpmfd-py.c354
-rw-r--r--python/rpmfd-py.h17
-rw-r--r--python/rpmfi-py.c378
-rw-r--r--python/rpmfi-py.h16
-rw-r--r--python/rpmii-py.c158
-rw-r--r--python/rpmii-py.h12
-rw-r--r--python/rpmkeyring-py.c202
-rw-r--r--python/rpmkeyring-py.h16
-rw-r--r--python/rpmmacro-py.c58
-rw-r--r--python/rpmmacro-py.h8
-rw-r--r--python/rpmmi-py.c220
-rw-r--r--python/rpmmi-py.h12
-rw-r--r--python/rpmmodule.c504
-rw-r--r--python/rpmps-py.c141
-rw-r--r--python/rpmps-py.h16
-rw-r--r--python/rpmsmodule.c97
-rw-r--r--python/rpmsystem-py.h45
-rw-r--r--python/rpmtd-py.c214
-rw-r--r--python/rpmtd-py.h14
-rw-r--r--python/rpmte-py.c302
-rw-r--r--python/rpmte-py.h14
-rw-r--r--python/rpmts-py.c904
-rw-r--r--python/rpmts-py.h18
-rw-r--r--python/spec-py.c304
-rw-r--r--python/spec-py.h18
34 files changed, 6474 insertions, 0 deletions
diff --git a/python/Makefile.am b/python/Makefile.am
new file mode 100644
index 0000000..4f85519
--- /dev/null
+++ b/python/Makefile.am
@@ -0,0 +1,51 @@
+# Makefile for rpm library.
+
+EXTRA_DIST = rpm/__init__.py rpm/transaction.py
+
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/
+AM_CPPFLAGS += -I$(top_srcdir)/python
+AM_CPPFLAGS += -I$(top_srcdir)/misc
+AM_CPPFLAGS += -I@WITH_PYTHON_INCLUDE@
+
+pkgpyexec_LTLIBRARIES = _rpmmodule.la _rpmbmodule.la _rpmsmodule.la
+pkgpyexec_DATA = rpm/__init__.py rpm/transaction.py
+
+_rpmmodule_la_LDFLAGS = -module -avoid-version -shared
+_rpmmodule_la_LIBADD = \
+ $(top_builddir)/lib/librpm.la \
+ $(top_builddir)/rpmio/librpmio.la \
+ @WITH_PYTHON_LIB@
+
+_rpmmodule_la_SOURCES = rpmmodule.c rpmsystem-py.h \
+ header-py.c header-py.h \
+ rpmds-py.c rpmds-py.h \
+ rpmfd-py.c rpmfd-py.h \
+ rpmfi-py.c rpmfi-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 \
+ rpmtd-py.c rpmtd-py.h \
+ rpmte-py.c rpmte-py.h \
+ rpmts-py.c rpmts-py.h
+
+_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@
+
+_rpmbmodule_la_SOURCES = rpmbmodule.c rpmsystem-py.h \
+ spec-py.c spec-py.h
+
+_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@
+
+_rpmsmodule_la_SOURCES = rpmsmodule.c rpmsystem-py.h
+
diff --git a/python/Makefile.in b/python/Makefile.in
new file mode 100644
index 0000000..1c97893
--- /dev/null
+++ b/python/Makefile.in
@@ -0,0 +1,742 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile for rpm library.
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = python
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pkgpyexecdir)" \
+ "$(DESTDIR)$(pkgpyexecdir)"
+LTLIBRARIES = $(pkgpyexec_LTLIBRARIES)
+_rpmbmodule_la_DEPENDENCIES = $(top_builddir)/build/librpmbuild.la \
+ $(top_builddir)/lib/librpm.la \
+ $(top_builddir)/rpmio/librpmio.la
+am__rpmbmodule_la_OBJECTS = rpmbmodule.lo spec-py.lo
+_rpmbmodule_la_OBJECTS = $(am__rpmbmodule_la_OBJECTS)
+_rpmbmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(_rpmbmodule_la_LDFLAGS) $(LDFLAGS) -o $@
+_rpmmodule_la_DEPENDENCIES = $(top_builddir)/lib/librpm.la \
+ $(top_builddir)/rpmio/librpmio.la
+am__rpmmodule_la_OBJECTS = rpmmodule.lo header-py.lo rpmds-py.lo \
+ rpmfd-py.lo rpmfi-py.lo rpmkeyring-py.lo rpmmi-py.lo \
+ rpmii-py.lo rpmps-py.lo rpmmacro-py.lo rpmtd-py.lo rpmte-py.lo \
+ rpmts-py.lo
+_rpmmodule_la_OBJECTS = $(am__rpmmodule_la_OBJECTS)
+_rpmmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(_rpmmodule_la_LDFLAGS) $(LDFLAGS) -o $@
+_rpmsmodule_la_DEPENDENCIES = $(top_builddir)/sign/librpmsign.la \
+ $(top_builddir)/lib/librpm.la \
+ $(top_builddir)/rpmio/librpmio.la
+am__rpmsmodule_la_OBJECTS = rpmsmodule.lo
+_rpmsmodule_la_OBJECTS = $(am__rpmsmodule_la_OBJECTS)
+_rpmsmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(_rpmsmodule_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES =
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(_rpmbmodule_la_SOURCES) $(_rpmmodule_la_SOURCES) \
+ $(_rpmsmodule_la_SOURCES)
+DIST_SOURCES = $(_rpmbmodule_la_SOURCES) $(_rpmmodule_la_SOURCES) \
+ $(_rpmsmodule_la_SOURCES)
+DATA = $(pkgpyexec_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOM4TE = @AUTOM4TE@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FIXPERMS = @FIXPERMS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LUA_CFLAGS = @LUA_CFLAGS@
+LUA_LIBS = @LUA_LIBS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RPMCANONARCH = @RPMCANONARCH@
+RPMCANONCOLOR = @RPMCANONCOLOR@
+RPMCANONGNU = @RPMCANONGNU@
+RPMCANONOS = @RPMCANONOS@
+RPMCANONVENDOR = @RPMCANONVENDOR@
+RPMCONFIGDIR = @RPMCONFIGDIR@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WITH_ACL_LIB = @WITH_ACL_LIB@
+WITH_BZ2_LIB = @WITH_BZ2_LIB@
+WITH_CAP_LIB = @WITH_CAP_LIB@
+WITH_DB_LIB = @WITH_DB_LIB@
+WITH_LIBELF_LIB = @WITH_LIBELF_LIB@
+WITH_LZMA_LIB = @WITH_LZMA_LIB@
+WITH_MAGIC_INCLUDE = @WITH_MAGIC_INCLUDE@
+WITH_MAGIC_LIB = @WITH_MAGIC_LIB@
+WITH_NSS_INCLUDE = @WITH_NSS_INCLUDE@
+WITH_NSS_LIB = @WITH_NSS_LIB@
+WITH_POPT_INCLUDE = @WITH_POPT_INCLUDE@
+WITH_POPT_LIB = @WITH_POPT_LIB@
+WITH_PYTHON_INCLUDE = @WITH_PYTHON_INCLUDE@
+WITH_PYTHON_LIB = @WITH_PYTHON_LIB@
+WITH_SELINUX_LIB = @WITH_SELINUX_LIB@
+WITH_SEMANAGE_LIB = @WITH_SEMANAGE_LIB@
+WITH_ZLIB_INCLUDE = @WITH_ZLIB_INCLUDE@
+WITH_ZLIB_LIB = @WITH_ZLIB_LIB@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+__BZIP2 = @__BZIP2@
+__CAT = @__CAT@
+__CC = @__CC@
+__CHGRP = @__CHGRP@
+__CHMOD = @__CHMOD@
+__CHOWN = @__CHOWN@
+__CP = @__CP@
+__CPIO = @__CPIO@
+__CURL = @__CURL@
+__FAKECHROOT = @__FAKECHROOT@
+__FILE = @__FILE@
+__GPG = @__GPG@
+__GREP = @__GREP@
+__GZIP = @__GZIP@
+__ID = @__ID@
+__INSTALL = @__INSTALL@
+__LD = @__LD@
+__LRZIP = @__LRZIP@
+__LZIP = @__LZIP@
+__MAKE = @__MAKE@
+__MKDIR = @__MKDIR@
+__MKDIR_P = @__MKDIR_P@
+__MV = @__MV@
+__NM = @__NM@
+__OBJCOPY = @__OBJCOPY@
+__OBJDUMP = @__OBJDUMP@
+__PATCH = @__PATCH@
+__PERL = @__PERL@
+__PGP = @__PGP@
+__PYTHON = @__PYTHON@
+__RESTORECON = @__RESTORECON@
+__RM = @__RM@
+__RSH = @__RSH@
+__SED = @__SED@
+__SEMODULE = @__SEMODULE@
+__SSH = @__SSH@
+__STRIP = @__STRIP@
+__TAR = @__TAR@
+__UNZIP = @__UNZIP@
+__XZ = @__XZ@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dirstamp = @dirstamp@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = rpm/__init__.py rpm/transaction.py
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) \
+ -I$(top_builddir)/include/ -I$(top_srcdir)/python \
+ -I$(top_srcdir)/misc -I@WITH_PYTHON_INCLUDE@
+pkgpyexec_LTLIBRARIES = _rpmmodule.la _rpmbmodule.la _rpmsmodule.la
+pkgpyexec_DATA = rpm/__init__.py rpm/transaction.py
+_rpmmodule_la_LDFLAGS = -module -avoid-version -shared
+_rpmmodule_la_LIBADD = \
+ $(top_builddir)/lib/librpm.la \
+ $(top_builddir)/rpmio/librpmio.la \
+ @WITH_PYTHON_LIB@
+
+_rpmmodule_la_SOURCES = rpmmodule.c rpmsystem-py.h \
+ header-py.c header-py.h \
+ rpmds-py.c rpmds-py.h \
+ rpmfd-py.c rpmfd-py.h \
+ rpmfi-py.c rpmfi-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 \
+ rpmtd-py.c rpmtd-py.h \
+ rpmte-py.c rpmte-py.h \
+ rpmts-py.c rpmts-py.h
+
+_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@
+
+_rpmbmodule_la_SOURCES = rpmbmodule.c rpmsystem-py.h \
+ spec-py.c spec-py.h
+
+_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@
+
+_rpmsmodule_la_SOURCES = rpmsmodule.c rpmsystem-py.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign python/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pkgpyexecLTLIBRARIES: $(pkgpyexec_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgpyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgpyexecdir)"
+ @list='$(pkgpyexec_LTLIBRARIES)'; test -n "$(pkgpyexecdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgpyexecdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgpyexecdir)"; \
+ }
+
+uninstall-pkgpyexecLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgpyexec_LTLIBRARIES)'; test -n "$(pkgpyexecdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgpyexecdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgpyexecdir)/$$f"; \
+ done
+
+clean-pkgpyexecLTLIBRARIES:
+ -test -z "$(pkgpyexec_LTLIBRARIES)" || rm -f $(pkgpyexec_LTLIBRARIES)
+ @list='$(pkgpyexec_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+_rpmbmodule.la: $(_rpmbmodule_la_OBJECTS) $(_rpmbmodule_la_DEPENDENCIES)
+ $(_rpmbmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmbmodule_la_OBJECTS) $(_rpmbmodule_la_LIBADD) $(LIBS)
+_rpmmodule.la: $(_rpmmodule_la_OBJECTS) $(_rpmmodule_la_DEPENDENCIES)
+ $(_rpmmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmmodule_la_OBJECTS) $(_rpmmodule_la_LIBADD) $(LIBS)
+_rpmsmodule.la: $(_rpmsmodule_la_OBJECTS) $(_rpmsmodule_la_DEPENDENCIES)
+ $(_rpmsmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmsmodule_la_OBJECTS) $(_rpmsmodule_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmbmodule.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmds-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfd-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfi-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmii-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmkeyring-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmacro-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmi-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmodule.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmps-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmsmodule.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmtd-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmte-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmts-py.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spec-py.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgpyexecDATA: $(pkgpyexec_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgpyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgpyexecdir)"
+ @list='$(pkgpyexec_DATA)'; test -n "$(pkgpyexecdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgpyexecdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgpyexecdir)" || exit $$?; \
+ done
+
+uninstall-pkgpyexecDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgpyexec_DATA)'; test -n "$(pkgpyexecdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkgpyexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkgpyexecdir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(pkgpyexecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkgpyexecLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pkgpyexecDATA install-pkgpyexecLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkgpyexecDATA uninstall-pkgpyexecLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pkgpyexecLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pkgpyexecDATA \
+ install-pkgpyexecLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pkgpyexecDATA uninstall-pkgpyexecLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/python/header-py.c b/python/header-py.c
new file mode 100644
index 0000000..a790099
--- /dev/null
+++ b/python/header-py.c
@@ -0,0 +1,855 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmlib.h> /* rpmvercmp */
+#include <rpm/rpmtag.h>
+#include <rpm/rpmstring.h>
+#include <rpm/rpmts.h> /* XXX rpmtsCreate/rpmtsFree */
+
+#include "header-py.h"
+#include "rpmds-py.h"
+#include "rpmfd-py.h"
+#include "rpmfi-py.h"
+#include "rpmtd-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \class Rpm
+ * \brief START HERE / RPM base module for the Python API
+ *
+ * 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:
+ * \code
+ * import rpm
+ *
+ * ts = rpm.TransactionSet()
+ * \endcode
+ *
+ * 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:
+ *
+ * \code
+ * rpm.addMacro('_dbpath', '/path/to/alternate/database')
+ * solvets = rpm.TransactionSet()
+ * solvets.openDB()
+ * rpm.delMacro('_dbpath')
+ *
+ * # Open default database
+ * ts = rpm.TransactionSet()
+ * \endcode
+ *
+ * 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.
+ *
+ * The rpm methods used here are:
+ *
+ * - addMacro(macro, value)
+ * @param macro Name of macro to add
+ * @param value Value for the macro
+ *
+ * - delMacro(macro)
+ * @param macro Name of macro to delete
+ *
+ */
+
+/** \ingroup python
+ * \class Rpmhdr
+ * \brief A python header object represents an RPM package header.
+ *
+ * All RPM packages have headers that provide metadata for the package.
+ * Header objects can be returned by database queries or loaded from a
+ * binary package on disk.
+ *
+ * The ts.hdrFromFdno() function returns the package header from a
+ * package on disk, verifying package signatures and digests of the
+ * package while reading.
+ *
+ * Note: The older method rpm.headerFromPackage() which has been replaced
+ * by ts.hdrFromFdno() used to return a (hdr, isSource) tuple.
+ *
+ * If you need to distinguish source/binary headers, do:
+ * \code
+ * import os, rpm
+ *
+ * ts = rpm.TransactionSet()
+ * fdno = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY)
+ * hdr = ts.hdrFromFdno(fdno)
+ * os.close(fdno)
+ * if hdr[rpm.RPMTAG_SOURCEPACKAGE]:
+ * print "header is from a source package"
+ * else:
+ * print "header is from a binary package"
+ * \endcode
+ *
+ * The Python interface to the header data is quite elegant. It
+ * presents the data in a dictionary form. We'll take the header we
+ * just loaded and access the data within it:
+ * \code
+ * print hdr[rpm.RPMTAG_NAME]
+ * print hdr[rpm.RPMTAG_VERSION]
+ * print hdr[rpm.RPMTAG_RELEASE]
+ * \endcode
+ * in the case of our "foo-1.0-1.i386.rpm" package, this code would
+ * output:
+\verbatim
+ foo
+ 1.0
+ 1
+\endverbatim
+ *
+ * You make also access the header data by string name:
+ * \code
+ * print hdr['name']
+ * print hdr['version']
+ * print hdr['release']
+ * \endcode
+ *
+ * This method of access is a teensy bit slower because the name must be
+ * translated into the tag number dynamically. You also must make sure
+ * the strings in header lookups don't get translated, or the lookups
+ * will fail.
+ */
+
+/** \ingroup python
+ * \name Class: rpm.hdr
+ */
+
+struct hdrObject_s {
+ PyObject_HEAD
+ Header h;
+ HeaderIterator hi;
+};
+
+static PyObject * hdrKeyList(hdrObject * s)
+{
+ PyObject * keys = PyList_New(0);
+ HeaderIterator hi = headerInitIterator(s->h);
+ rpmTagVal tag;
+
+ while ((tag = headerNextTag(hi)) != RPMTAG_NOT_FOUND) {
+ PyObject *to = PyInt_FromLong(tag);
+ PyList_Append(keys, to);
+ Py_DECREF(to);
+ }
+ headerFreeIterator(hi);
+
+ return keys;
+}
+
+static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
+{
+ char * buf;
+ PyObject * rc;
+ int len, legacy = 0;
+ Header h;
+ static char *kwlist[] = { "legacyHeader", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
+ return NULL;
+
+ 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);
+ }
+ len = headerSizeof(h, HEADER_MAGIC_NO);
+ buf = headerUnload(h);
+ h = headerFree(h);
+
+ if (buf == NULL || len == 0) {
+ PyErr_SetString(pyrpmError, "can't unload bad header\n");
+ return NULL;
+ }
+
+ rc = PyBytes_FromStringAndSize(buf, len);
+ buf = _free(buf);
+
+ return rc;
+}
+
+static PyObject * hdrExpandFilelist(hdrObject * s)
+{
+ DEPRECATED_METHOD("use hdr.convert() instead");
+ headerConvert(s->h, HEADERCONV_EXPANDFILELIST);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * hdrCompressFilelist(hdrObject * s)
+{
+ DEPRECATED_METHOD("use hdr.convert() instead");
+ headerConvert(s->h, HEADERCONV_COMPRESSFILELIST);
+
+ Py_RETURN_NONE;
+}
+
+/* make a header with _all_ the tags we need */
+static PyObject * hdrFullFilelist(hdrObject * s)
+{
+ rpmtd fileNames = rpmtdNew();
+ Header h = s->h;
+
+ DEPRECATED_METHOD("obsolete method");
+ if (!headerIsEntry (h, RPMTAG_BASENAMES)
+ || !headerIsEntry (h, RPMTAG_DIRNAMES)
+ || !headerIsEntry (h, RPMTAG_DIRINDEXES))
+ headerConvert(h, HEADERCONV_COMPRESSFILELIST);
+
+ if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) {
+ rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES);
+ headerPut(h, fileNames, HEADERPUT_DEFAULT);
+ rpmtdFreeData(fileNames);
+ }
+ rpmtdFree(fileNames);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds)
+{
+ char * fmt;
+ char * r;
+ errmsg_t err;
+ PyObject * result;
+ char * kwlist[] = {"format", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
+ return NULL;
+
+ r = headerFormat(s->h, fmt, &err);
+ if (!r) {
+ PyErr_SetString(pyrpmError, err);
+ return NULL;
+ }
+
+ result = Py_BuildValue("s", r);
+ r = _free(r);
+
+ return result;
+}
+
+static PyObject *hdrIsSource(hdrObject *s)
+{
+ return PyBool_FromLong(headerIsSource(s->h));
+}
+
+static int hdrContains(hdrObject *s, PyObject *pytag)
+{
+ rpmTagVal tag;
+ if (!tagNumFromPyObject(pytag, &tag)) return -1;
+
+ return headerIsEntry(s->h, tag);
+}
+
+static PyObject *hdrConvert(hdrObject *self, PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = {"op", NULL};
+ int op = -1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &op)) {
+ return NULL;
+ }
+ return PyBool_FromLong(headerConvert(self->h, op));
+}
+
+static PyObject * hdrWrite(hdrObject *s, PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = { "file", "magic", NULL };
+ int magic = HEADER_MAGIC_YES;
+ rpmfdObject *fdo = NULL;
+ int rc;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
+ rpmfdFromPyObject, &fdo, &magic))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ rc = headerWrite(rpmfdGetFd(fdo), s->h,
+ magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
+ Py_END_ALLOW_THREADS;
+
+ if (rc) PyErr_SetFromErrno(PyExc_IOError);
+ Py_XDECREF(fdo); /* avoid messing up errno with file close */
+ if (rc) return NULL;
+
+ Py_RETURN_NONE;
+}
+
+/*
+ * Just a backwards-compatibility dummy, the arguments are not looked at
+ * or used. TODO: push this over to python side...
+ */
+static PyObject * hdr_fiFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
+{
+ return PyObject_Call((PyObject *) &rpmfi_Type,
+ Py_BuildValue("(O)", s), NULL);
+}
+
+/* Backwards compatibility. Flags argument is just a dummy and discarded. */
+static PyObject * hdr_dsFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmTagVal tag = RPMTAG_REQUIRENAME;
+ rpmsenseFlags flags = 0;
+ char * kwlist[] = {"to", "flags", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&i:dsFromHeader", kwlist,
+ tagNumFromPyObject, &tag, &flags))
+ return NULL;
+
+ return PyObject_Call((PyObject *) &rpmds_Type,
+ Py_BuildValue("(Oi)", s, tag), NULL);
+}
+
+static PyObject * hdr_dsOfHeader(PyObject * s)
+{
+ return PyObject_Call((PyObject *) &rpmds_Type,
+ Py_BuildValue("(Oi)", s, RPMTAG_NEVR), NULL);
+}
+
+static long hdr_hash(PyObject * h)
+{
+ return (long) h;
+}
+
+static struct PyMethodDef hdr_methods[] = {
+ {"keys", (PyCFunction) hdrKeyList, METH_NOARGS,
+ NULL },
+ {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS,
+ NULL },
+ {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
+ NULL },
+ {"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS,
+ NULL },
+ {"convert", (PyCFunction) hdrConvert, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"format", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"sprintf", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"isSource", (PyCFunction)hdrIsSource, METH_NOARGS,
+ NULL },
+ {"write", (PyCFunction)hdrWrite, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS,
+ NULL},
+ {"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS,
+ NULL},
+ {"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS,
+ NULL},
+
+ {NULL, NULL} /* sentinel */
+};
+
+/* TODO: permit keyring check + retrofits on copy/load */
+static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj = NULL;
+ rpmfdObject *fdo = NULL;
+ Header h = NULL;
+ char *kwlist[] = { "obj", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) {
+ return NULL;
+ }
+
+ if (obj == NULL) {
+ h = headerNew();
+ } else if (PyCObject_Check(obj)) {
+ h = PyCObject_AsVoidPtr(obj);
+ } else if (hdrObject_Check(obj)) {
+ h = headerCopy(((hdrObject*) obj)->h);
+ } else if (PyBytes_Check(obj)) {
+ h = headerCopyLoad(PyBytes_AsString(obj));
+ } else if (rpmfdFromPyObject(obj, &fdo)) {
+ Py_BEGIN_ALLOW_THREADS;
+ h = headerRead(rpmfdGetFd(fdo), HEADER_MAGIC_YES);
+ Py_END_ALLOW_THREADS;
+ Py_XDECREF(fdo);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "header, blob or file expected");
+ return NULL;
+ }
+
+ if (h == NULL) {
+ PyErr_SetString(pyrpmError, "bad header");
+ return NULL;
+ }
+
+ return hdr_Wrap(subtype, h);
+}
+
+static void hdr_dealloc(hdrObject * s)
+{
+ if (s->h) headerFree(s->h);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject * hdr_iternext(hdrObject *s)
+{
+ PyObject *res = NULL;
+ rpmTagVal tag;
+
+ if (s->hi == NULL) s->hi = headerInitIterator(s->h);
+
+ if ((tag = headerNextTag(s->hi)) != RPMTAG_NOT_FOUND) {
+ res = PyInt_FromLong(tag);
+ } else {
+ s->hi = headerFreeIterator(s->hi);
+ }
+ return res;
+}
+
+int utf8FromPyObject(PyObject *item, PyObject **str)
+{
+ PyObject *res = NULL;
+ if (PyBytes_Check(item)) {
+ Py_XINCREF(item);
+ res = item;
+ } else if (PyUnicode_Check(item)) {
+ res = PyUnicode_AsUTF8String(item);
+ }
+ if (res == NULL) return 0;
+
+ *str = res;
+ return 1;
+}
+
+int tagNumFromPyObject (PyObject *item, rpmTagVal *tagp)
+{
+ rpmTagVal tag = RPMTAG_NOT_FOUND;
+ PyObject *str = NULL;
+
+ if (PyInt_Check(item)) {
+ /* XXX we should probably validate tag numbers too */
+ tag = PyInt_AsLong(item);
+ } else if (utf8FromPyObject(item, &str)) {
+ tag = rpmTagGetValue(PyBytes_AsString(str));
+ Py_DECREF(str);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "expected a string or integer");
+ return 0;
+ }
+ if (tag == RPMTAG_NOT_FOUND) {
+ PyErr_SetString(PyExc_ValueError, "unknown header tag");
+ return 0;
+ }
+
+ *tagp = tag;
+ return 1;
+}
+
+static PyObject * hdrGetTag(Header h, rpmTagVal tag)
+{
+ PyObject *res = NULL;
+ struct rpmtd_s td;
+
+ /* rpmtd_AsPyObj() knows how to handle empty containers and all */
+ (void) headerGet(h, tag, &td, HEADERGET_EXT);
+ res = rpmtd_AsPyobj(&td);
+ rpmtdFreeData(&td);
+ return res;
+}
+
+static int validItem(rpmTagClass tclass, PyObject *item)
+{
+ int rc;
+
+ switch (tclass) {
+ case RPM_NUMERIC_CLASS:
+ rc = (PyLong_Check(item) || PyInt_Check(item));
+ break;
+ case RPM_STRING_CLASS:
+ rc = (PyBytes_Check(item) || PyUnicode_Check(item));
+ break;
+ case RPM_BINARY_CLASS:
+ rc = PyBytes_Check(item);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static int validData(rpmTagVal tag, rpmTagType type, rpmTagReturnType retype, PyObject *value)
+{
+ rpmTagClass tclass = rpmTagGetClass(tag);
+ int valid = 1;
+
+ if (retype == RPM_SCALAR_RETURN_TYPE) {
+ valid = validItem(tclass, value);
+ } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) {
+ /* python lists can contain arbitrary objects, validate each item */
+ Py_ssize_t len = PyList_Size(value);
+ for (Py_ssize_t i = 0; i < len; i++) {
+ PyObject *item = PyList_GetItem(value, i);
+ if (!validItem(tclass, item)) {
+ valid = 0;
+ break;
+ }
+ }
+ } else {
+ valid = 0;
+ }
+ return valid;
+}
+
+static int hdrAppendItem(Header h, rpmTagVal tag, rpmTagType type, PyObject *item)
+{
+ int rc = 0;
+
+ switch (type) {
+ case RPM_I18NSTRING_TYPE: /* XXX this needs to be handled separately */
+ case RPM_STRING_TYPE:
+ case RPM_STRING_ARRAY_TYPE: {
+ PyObject *str = NULL;
+ if (utf8FromPyObject(item, &str))
+ rc = headerPutString(h, tag, PyBytes_AsString(str));
+ Py_XDECREF(str);
+ } break;
+ case RPM_BIN_TYPE: {
+ uint8_t *val = (uint8_t *) PyBytes_AsString(item);
+ rpm_count_t len = PyBytes_Size(item);
+ rc = headerPutBin(h, tag, val, len);
+ } break;
+ case RPM_INT64_TYPE: {
+ uint64_t val = PyInt_AsUnsignedLongLongMask(item);
+ rc = headerPutUint64(h, tag, &val, 1);
+ } break;
+ case RPM_INT32_TYPE: {
+ uint32_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint32(h, tag, &val, 1);
+ } break;
+ case RPM_INT16_TYPE: {
+ uint16_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint16(h, tag, &val, 1);
+ } break;
+ case RPM_INT8_TYPE:
+ case RPM_CHAR_TYPE: {
+ uint8_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint8(h, tag, &val, 1);
+ } break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "unhandled datatype");
+ }
+ return rc;
+}
+
+static int hdrPutTag(Header h, rpmTagVal tag, PyObject *value)
+{
+ rpmTagType type = rpmTagGetTagType(tag);
+ rpmTagReturnType retype = rpmTagGetReturnType(tag);
+ int rc = 0;
+
+ /* XXX this isn't really right (i18n strings etc) but for now ... */
+ if (headerIsEntry(h, tag)) {
+ PyErr_SetString(PyExc_TypeError, "tag already exists");
+ return rc;
+ }
+
+ /* validate all data before trying to insert */
+ if (!validData(tag, type, retype, value)) {
+ PyErr_SetString(PyExc_TypeError, "invalid type for tag");
+ return 0;
+ }
+
+ if (retype == RPM_SCALAR_RETURN_TYPE) {
+ rc = hdrAppendItem(h, tag, type, value);
+ } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) {
+ Py_ssize_t len = PyList_Size(value);
+ for (Py_ssize_t i = 0; i < len; i++) {
+ PyObject *item = PyList_GetItem(value, i);
+ rc = hdrAppendItem(h, tag, type, item);
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "cant happen, right?");
+ }
+
+ return rc;
+}
+
+static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
+{
+ rpmTagVal tag;
+
+ if (!tagNumFromPyObject(item, &tag)) return NULL;
+ return hdrGetTag(s->h, tag);
+}
+
+static int hdr_ass_subscript(hdrObject *s, PyObject *key, PyObject *value)
+{
+ rpmTagVal tag;
+ if (!tagNumFromPyObject(key, &tag)) return -1;
+
+ if (value == NULL) {
+ /* XXX should failure raise key error? */
+ headerDel(s->h, tag);
+ } else if (!hdrPutTag(s->h, tag, value)) {
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject * hdr_getattro(hdrObject * s, PyObject * n)
+{
+ PyObject *res = PyObject_GenericGetAttr((PyObject *) s, n);
+ if (res == NULL) {
+ PyObject *type, *value, *traceback;
+ rpmTagVal tag;
+
+ /* Save and restore original exception if it's not a valid tag either */
+ PyErr_Fetch(&type, &value, &traceback);
+ if (tagNumFromPyObject(n, &tag)) {
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+ res = hdrGetTag(s->h, tag);
+ } else {
+ PyErr_Restore(type, value, traceback);
+ }
+ }
+ return res;
+}
+
+static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
+{
+ return PyObject_GenericSetAttr(o, n, v);
+}
+
+static PyMappingMethods hdr_as_mapping = {
+ (lenfunc) 0, /* mp_length */
+ (binaryfunc) hdr_subscript, /* mp_subscript */
+ (objobjargproc)hdr_ass_subscript,/* mp_ass_subscript */
+};
+
+static PySequenceMethods hdr_as_sequence = {
+ 0, /* sq_length */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ 0, /* sq_item */
+ 0, /* sq_slice */
+ 0, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ (objobjproc)hdrContains, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0, /* sq_inplace_repeat */
+};
+
+static char hdr_doc[] =
+"";
+
+PyTypeObject hdr_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.hdr", /* tp_name */
+ sizeof(hdrObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) hdr_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc) 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ &hdr_as_sequence, /* tp_as_sequence */
+ &hdr_as_mapping, /* tp_as_mapping */
+ hdr_hash, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ (getattrofunc) hdr_getattro, /* tp_getattro */
+ (setattrofunc) hdr_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ hdr_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)hdr_iternext, /* tp_iternext */
+ hdr_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 */
+ hdr_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * hdr_Wrap(PyTypeObject *subtype, Header h)
+{
+ hdrObject * hdr = (hdrObject *)subtype->tp_alloc(subtype, 0);
+ if (hdr == NULL) return NULL;
+
+ hdr->h = headerLink(h);
+ return (PyObject *) hdr;
+}
+
+int hdrFromPyObject(PyObject *item, Header *hptr)
+{
+ if (hdrObject_Check(item)) {
+ *hptr = ((hdrObject *) item)->h;
+ return 1;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "header object expected");
+ return 0;
+ }
+}
+
+/**
+ * This assumes the order of list matches the order of the new headers, and
+ * throws an exception if that isn't true.
+ */
+static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
+{
+ Header h;
+ HeaderIterator hi;
+ rpmTagVal newMatch, oldMatch;
+ hdrObject * hdr;
+ rpm_count_t count = 0;
+ int rc = 1; /* assume failure */
+ rpmtd td = rpmtdNew();
+
+ Py_BEGIN_ALLOW_THREADS
+ h = headerRead(fd, HEADER_MAGIC_YES);
+ Py_END_ALLOW_THREADS
+
+ while (h) {
+ if (!headerGet(h, matchTag, td, HEADERGET_MINMEM)) {
+ PyErr_SetString(pyrpmError, "match tag missing in new header");
+ goto exit;
+ }
+ newMatch = rpmtdTag(td);
+ rpmtdFreeData(td);
+
+ hdr = (hdrObject *) PyList_GetItem(list, count++);
+ if (!hdr) goto exit;
+
+ if (!headerGet(hdr->h, matchTag, td, HEADERGET_MINMEM)) {
+ PyErr_SetString(pyrpmError, "match tag missing in new header");
+ goto exit;
+ }
+ oldMatch = rpmtdTag(td);
+ rpmtdFreeData(td);
+
+ if (newMatch != oldMatch) {
+ PyErr_SetString(pyrpmError, "match tag mismatch");
+ goto exit;
+ }
+
+ for (hi = headerInitIterator(h); headerNext(hi, td); rpmtdFreeData(td))
+ {
+ /* could be dupes */
+ headerDel(hdr->h, rpmtdTag(td));
+ headerPut(hdr->h, td, HEADERPUT_DEFAULT);
+ }
+
+ headerFreeIterator(hi);
+ h = headerFree(h);
+
+ Py_BEGIN_ALLOW_THREADS
+ h = headerRead(fd, HEADER_MAGIC_YES);
+ Py_END_ALLOW_THREADS
+ }
+ rc = 0;
+
+exit:
+ rpmtdFree(td);
+ return rc;
+}
+
+PyObject *
+rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
+{
+ FD_t fd;
+ int fileno;
+ PyObject * list;
+ int rc;
+ int matchTag;
+ char * kwlist[] = {"list", "fd", "matchTag", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
+ &fileno, &matchTag))
+ return NULL;
+
+ if (!PyList_Check(list)) {
+ PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
+ return NULL;
+ }
+
+ fd = fdDup(fileno);
+
+ rc = rpmMergeHeaders (list, fd, matchTag);
+ Fclose(fd);
+
+ if (rc) {
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
+{
+ hdrObject * h1, * h2;
+ char * kwlist[] = {"version0", "version1", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
+ &h1, &hdr_Type, &h2))
+ return NULL;
+
+ return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
+}
+
+static int compare_values(const char *str1, const char *str2)
+{
+ if (!str1 && !str2)
+ return 0;
+ else if (str1 && !str2)
+ return 1;
+ else if (!str1 && str2)
+ return -1;
+ return rpmvercmp(str1, str2);
+}
+
+PyObject * labelCompare (PyObject * self, PyObject * args)
+{
+ char *v1, *r1, *v2, *r2;
+ const char *e1, *e2;
+ int rc;
+
+ if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
+ &e1, &v1, &r1, &e2, &v2, &r2))
+ return NULL;
+
+ if (e1 == NULL) e1 = "0";
+ if (e2 == NULL) e2 = "0";
+
+ rc = compare_values(e1, e2);
+ if (!rc) {
+ rc = compare_values(v1, v2);
+ if (!rc)
+ rc = compare_values(r1, r2);
+ }
+ return Py_BuildValue("i", rc);
+}
+
diff --git a/python/header-py.h b/python/header-py.h
new file mode 100644
index 0000000..1103876
--- /dev/null
+++ b/python/header-py.h
@@ -0,0 +1,26 @@
+#ifndef RPMPYTHON_HEADER
+#define RPMPYTHON_HEADER
+
+#include <rpm/rpmtypes.h>
+
+typedef struct hdrObject_s hdrObject;
+
+extern PyTypeObject hdr_Type;
+
+#define hdrObject_Check(v) ((v)->ob_type == &hdr_Type)
+
+#define DEPRECATED_METHOD(_msg) \
+ PyErr_WarnEx(PyExc_PendingDeprecationWarning, (_msg), 2);
+
+extern PyObject * pyrpmError;
+
+PyObject * hdr_Wrap(PyTypeObject *subtype, Header h);
+
+int hdrFromPyObject(PyObject *item, Header *h);
+int utf8FromPyObject(PyObject *item, PyObject **str);
+int tagNumFromPyObject (PyObject *item, rpmTagVal *tagp);
+
+PyObject * labelCompare (PyObject * self, PyObject * args);
+PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds);
+PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds);
+#endif
diff --git a/python/rpm/__init__.py b/python/rpm/__init__.py
new file mode 100644
index 0000000..d868d19
--- /dev/null
+++ b/python/rpm/__init__.py
@@ -0,0 +1,84 @@
+r"""RPM Module
+
+This module enables you to manipulate rpms and the rpm database.
+
+"""
+
+import warnings
+import os
+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
+_RPMVSF_NOSIGNATURES = _rpm._RPMVSF_NOSIGNATURES
+
+__version__ = _rpm.__version__
+__version_info__ = tuple(__version__.split('.'))
+
+# try to import build bits but dont require it
+try:
+ from rpm._rpmb import *
+except ImportError:
+ pass
+
+# try to import signing bits but dont require it
+try:
+ from rpm._rpms import *
+except ImportError:
+ pass
+
+# backwards compatibility + give the same class both ways
+ts = TransactionSet
+
+def headerLoad(*args, **kwds):
+ warnings.warn("Use rpm.hdr() instead.", DeprecationWarning, stacklevel=2)
+ return hdr(*args, **kwds)
+
+def _doHeaderListFromFD(rpm_fd, retrofit):
+ hlist = []
+ while 1:
+ try:
+ h = hdr(rpm_fd)
+ if retrofit:
+ h.convert(HEADERCONV_RETROFIT_V3)
+ hlist.append(h)
+ except _rpm.error:
+ break
+
+ return hlist
+
+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):
+ f = fd(path)
+ hlist = _doHeaderListFromFD(f, retrofit)
+ f.close()
+ return hlist
+
+def readHeaderFromFD(file_desc):
+ if not isinstance(file_desc, fd):
+ file_desc = fd(file_desc)
+ try:
+ offset = file_desc.tell()
+ h = hdr(file_desc)
+ except (_rpm.error, IOError):
+ offset = None
+ h = None
+
+ return (h, offset)
+
+def signalsCaught(siglist):
+ caught = []
+ for sig in siglist:
+ if signalCaught(sig):
+ caught.append(sig)
+
+ return caught
+
+def dsSingle(TagN, N, EVR = "", Flags = RPMSENSE_ANY):
+ return ds((N, EVR, Flags), TagN)
diff --git a/python/rpm/transaction.py b/python/rpm/transaction.py
new file mode 100644
index 0000000..73e4b3c
--- /dev/null
+++ b/python/rpm/transaction.py
@@ -0,0 +1,156 @@
+#!/usr/bin/python
+
+import rpm
+from rpm._rpm import ts as TransactionSetCore
+
+# TODO: migrate relevant documentation from C-side
+class TransactionSet(TransactionSetCore):
+ _probFilter = 0
+
+ def _wrapSetGet(self, attr, val):
+ oval = getattr(self, attr)
+ setattr(self, attr, val)
+ return oval
+
+ def setVSFlags(self, flags):
+ return self._wrapSetGet('_vsflags', flags)
+
+ def getVSFlags(self):
+ return self._vsflags
+
+ def setColor(self, color):
+ return self._wrapSetGet('_color', color)
+
+ def setPrefColor(self, color):
+ return self._wrapSetGet('_prefcolor', color)
+
+ def setFlags(self, flags):
+ return self._wrapSetGet('_flags', flags)
+
+ def setProbFilter(self, ignoreSet):
+ return self._wrapSetGet('_probFilter', ignoreSet)
+
+ def parseSpec(self, specfile):
+ import _rpmb
+ return _rpmb.spec(specfile)
+
+ def getKeys(self):
+ keys = []
+ for te in self:
+ keys.append(te.Key())
+ # Backwards compatibility goo - WTH does this return a *tuple* ?!
+ if not keys:
+ return None
+ 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:
+ header = item
+
+ if not how 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 addErase(self, item):
+ hdrs = []
+ if isinstance(item, rpm.hdr):
+ hdrs = [item]
+ elif isinstance(item, rpm.mi):
+ hdrs = item
+ elif isinstance(item, int):
+ hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item)
+ elif isinstance(item, basestring):
+ hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item)
+ else:
+ raise TypeError("invalid type %s" % type(item))
+
+ for h in hdrs:
+ if not TransactionSetCore.addErase(self, h):
+ raise rpm.error("package not installed")
+
+ # garbage collection should take care but just in case...
+ if isinstance(hdrs, rpm.mi):
+ del hdrs
+
+ def run(self, callback, data):
+ 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
+ # with errors
+ if rc == 0:
+ return None
+
+ res = []
+ if rc > 0:
+ for prob in self.problems():
+ item = ("%s" % prob, (prob.type, prob._str, prob._num))
+ res.append(item)
+ return res
+
+ def check(self, *args, **kwds):
+ TransactionSetCore.check(self, *args, **kwds)
+
+ # compatibility: munge problem strings into dependency tuples of doom
+ res = []
+ for p in self.problems():
+ # is it anything we need to care about?
+ if p.type == rpm.RPMPROB_CONFLICT:
+ sense = rpm.RPMDEP_SENSE_CONFLICTS
+ elif p.type == rpm.RPMPROB_REQUIRES:
+ sense = rpm.RPMDEP_SENSE_REQUIRES
+ else:
+ continue
+
+ # strip arch, split to name, version, release
+ nevr = p.altNEVR.rsplit('.', 1)[0]
+ n, v, r = nevr.rsplit('-', 2)
+
+ # extract the dependency information
+ needs = p._str.split()
+ needname = needs[0]
+ 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
+ needver = needs[2]
+ else:
+ needver = ""
+
+ res.append(((n, v, r),(needname,needver),needflags,sense,p.key))
+
+ return res
+
+ def hdrCheck(self, blob):
+ res, msg = TransactionSetCore.hdrCheck(self, blob)
+ # generate backwards compatibly broken exceptions
+ if res == rpm.RPMRC_NOKEY:
+ raise rpm.error("public key not available")
+ elif res == rpm.RPMRC_NOTTRUSTED:
+ raise rpm.error("public key not trusted")
+ elif res != rpm.RPMRC_OK:
+ raise rpm.error(msg)
+
+ def hdrFromFdno(self, fd):
+ res, h = TransactionSetCore.hdrFromFdno(self, fd)
+ # generate backwards compatibly broken exceptions
+ if res == rpm.RPMRC_NOKEY:
+ raise rpm.error("public key not available")
+ elif res == rpm.RPMRC_NOTTRUSTED:
+ raise rpm.error("public key not trusted")
+ elif res != rpm.RPMRC_OK:
+ raise rpm.error("error reading package header")
+
+ return h
diff --git a/python/rpmbmodule.c b/python/rpmbmodule.c
new file mode 100644
index 0000000..a6a35d8
--- /dev/null
+++ b/python/rpmbmodule.c
@@ -0,0 +1,97 @@
+#include "rpmsystem-py.h"
+
+#include "spec-py.h"
+
+#include "debug.h"
+
+static char rpmb__doc__[] =
+"";
+
+/*
+ Do any common preliminary work before python 2 vs python 3 module creation:
+*/
+static int prepareInitModule(void)
+{
+ if (PyType_Ready(&spec_Type) < 0) return 0;
+ if (PyType_Ready(&specPkg_Type) < 0) return 0;
+
+ return 1;
+}
+
+static int initModule(PyObject *m)
+{
+ Py_INCREF(&spec_Type);
+ PyModule_AddObject(m, "spec", (PyObject *) &spec_Type);
+ Py_INCREF(&specPkg_Type);
+ PyModule_AddObject(m, "specPkg", (PyObject *) &specPkg_Type);
+
+#define REGISTER_ENUM(val) PyModule_AddIntConstant(m, #val, val)
+ REGISTER_ENUM(RPMBUILD_ISSOURCE);
+ REGISTER_ENUM(RPMBUILD_ISPATCH);
+ REGISTER_ENUM(RPMBUILD_ISICON);
+ REGISTER_ENUM(RPMBUILD_ISNO);
+
+ REGISTER_ENUM(RPMBUILD_NONE);
+ REGISTER_ENUM(RPMBUILD_PREP);
+ REGISTER_ENUM(RPMBUILD_BUILD);
+ REGISTER_ENUM(RPMBUILD_INSTALL);
+ REGISTER_ENUM(RPMBUILD_CHECK);
+ REGISTER_ENUM(RPMBUILD_CLEAN);
+ REGISTER_ENUM(RPMBUILD_FILECHECK);
+ REGISTER_ENUM(RPMBUILD_PACKAGESOURCE);
+ REGISTER_ENUM(RPMBUILD_PACKAGEBINARY);
+ REGISTER_ENUM(RPMBUILD_RMSOURCE);
+ REGISTER_ENUM(RPMBUILD_RMBUILD);
+ REGISTER_ENUM(RPMBUILD_RMSPEC);
+
+ REGISTER_ENUM(RPMBUILD_PKG_NONE);
+ REGISTER_ENUM(RPMBUILD_PKG_NODIRTOKENS);
+
+ REGISTER_ENUM(RPMSPEC_NONE);
+ REGISTER_ENUM(RPMSPEC_ANYARCH);
+ REGISTER_ENUM(RPMSPEC_FORCE);
+ REGISTER_ENUM(RPMSPEC_NOLANG);
+
+ return 1;
+}
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_rpmb", /* m_name */
+ rpmb__doc__, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+};
+
+PyObject * PyInit__rpm(void); /* XXX eliminate gcc warning */
+PyObject * PyInit__rpm(void)
+{
+ PyObject *m;
+
+ if (!prepareInitModule())
+ return NULL;
+ m = PyModule_Create(&moduledef);
+ if (m == NULL || !initModule(m)) {
+ Py_XDECREF(m);
+ m = NULL;
+ }
+ return m;
+}
+#else
+void init_rpmb(void); /* XXX eliminate gcc warning */
+void init_rpmb(void)
+{
+ PyObject *m;
+
+ if (!prepareInitModule())
+ return;
+
+ m = Py_InitModule3("_rpmb", NULL, rpmb__doc__);
+ if (m) initModule(m);
+}
+#endif
diff --git a/python/rpmds-py.c b/python/rpmds-py.c
new file mode 100644
index 0000000..1576ec7
--- /dev/null
+++ b/python/rpmds-py.c
@@ -0,0 +1,405 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmstring.h>
+#include <rpm/rpmlib.h> /* rpmvercmp */
+
+#include "header-py.h"
+#include "rpmds-py.h"
+
+#include "debug.h"
+
+struct rpmdsObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ int active;
+ rpmds ds;
+};
+
+static PyObject *
+rpmds_Count(rpmdsObject * s)
+{
+ DEPRECATED_METHOD("use len(ds) instead");
+ return Py_BuildValue("i", PyMapping_Size((PyObject *)s));
+}
+
+static PyObject *
+rpmds_Ix(rpmdsObject * s)
+{
+ return Py_BuildValue("i", rpmdsIx(s->ds));
+}
+
+static PyObject *
+rpmds_DNEVR(rpmdsObject * s)
+{
+ return Py_BuildValue("s", rpmdsDNEVR(s->ds));
+}
+
+static PyObject *
+rpmds_N(rpmdsObject * s)
+{
+ return Py_BuildValue("s", rpmdsN(s->ds));
+}
+
+static PyObject *
+rpmds_EVR(rpmdsObject * s)
+{
+ return Py_BuildValue("s", rpmdsEVR(s->ds));
+}
+
+static PyObject *
+rpmds_Flags(rpmdsObject * s)
+{
+ return Py_BuildValue("i", rpmdsFlags(s->ds));
+}
+
+static PyObject *
+rpmds_TagN(rpmdsObject * s)
+{
+ return Py_BuildValue("i", rpmdsTagN(s->ds));
+}
+
+static PyObject *
+rpmds_Color(rpmdsObject * s)
+{
+ return Py_BuildValue("i", rpmdsColor(s->ds));
+}
+
+static PyObject *
+rpmds_iternext(rpmdsObject * s)
+{
+ PyObject * result = NULL;
+
+ /* Reset loop indices on 1st entry. */
+ if (!s->active) {
+ s->ds = rpmdsInit(s->ds);
+ s->active = 1;
+ }
+
+ /* If more to do, return a (N, EVR, Flags) tuple. */
+ if (rpmdsNext(s->ds) >= 0) {
+ result = rpmds_Wrap(Py_TYPE(s), rpmdsCurrent(s->ds));
+ } else
+ s->active = 0;
+
+ return result;
+}
+
+static PyObject *
+rpmds_SetNoPromote(rpmdsObject * s, PyObject * args, PyObject * kwds)
+{
+ int nopromote;
+ char * kwlist[] = {"noPromote", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetNoPromote", kwlist,
+ &nopromote))
+ return NULL;
+
+ 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)
+{
+ /* XXX sort on (N,EVR,F) here. */
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+rpmds_Find(rpmdsObject * s, PyObject * arg)
+{
+ rpmdsObject * o;
+
+ if (!PyArg_Parse(arg, "O!:Find", &rpmds_Type, &o))
+ return NULL;
+
+ /* XXX make sure ods index is valid, real fix in lib/rpmds.c. */
+ if (rpmdsIx(o->ds) == -1) rpmdsSetIx(o->ds, 0);
+
+ return Py_BuildValue("i", rpmdsFind(s->ds, o->ds));
+}
+
+static PyObject *
+rpmds_Merge(rpmdsObject * s, PyObject * arg)
+{
+ rpmdsObject * o;
+
+ if (!PyArg_Parse(arg, "O!:Merge", &rpmds_Type, &o))
+ return NULL;
+
+ return Py_BuildValue("i", rpmdsMerge(&s->ds, o->ds));
+}
+static PyObject *
+rpmds_Search(rpmdsObject * s, PyObject * arg)
+{
+ rpmdsObject * o;
+
+ if (!PyArg_Parse(arg, "O!:Merge", &rpmds_Type, &o))
+ return NULL;
+
+ return Py_BuildValue("i", rpmdsSearch(s->ds, o->ds));
+}
+
+static PyObject *rpmds_Compare(rpmdsObject * s, PyObject * o)
+{
+ rpmdsObject * ods;
+
+ if (!PyArg_Parse(o, "O!:Compare", &rpmds_Type, &ods))
+ return NULL;
+
+ return PyBool_FromLong(rpmdsCompare(s->ds, ods->ds));
+}
+
+static PyObject *rpmds_Instance(rpmdsObject * s)
+{
+ return Py_BuildValue("i", rpmdsInstance(s->ds));
+}
+
+static PyObject * rpmds_Rpmlib(rpmdsObject * s)
+{
+ rpmds ds = NULL;
+ int xx;
+
+ /* XXX check return code, permit arg (NULL uses system default). */
+ xx = rpmdsRpmlib(&ds, NULL);
+
+ return rpmds_Wrap(&rpmds_Type, ds);
+}
+
+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" },
+ {"DNEVR", (PyCFunction)rpmds_DNEVR, METH_NOARGS,
+ "ds.DNEVR -> DNEVR - Return current DNEVR.\n" },
+ {"N", (PyCFunction)rpmds_N, METH_NOARGS,
+ "ds.N -> N - Return current N.\n" },
+ {"EVR", (PyCFunction)rpmds_EVR, METH_NOARGS,
+ "ds.EVR -> EVR - Return current EVR.\n" },
+ {"Flags", (PyCFunction)rpmds_Flags, METH_NOARGS,
+ "ds.Flags -> Flags - Return current Flags.\n" },
+ {"TagN", (PyCFunction)rpmds_TagN, METH_NOARGS,
+ "ds.TagN -> TagN - Return current TagN.\n" },
+ {"Color", (PyCFunction)rpmds_Color, METH_NOARGS,
+ "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},
+ {"Sort", (PyCFunction)rpmds_Sort, METH_NOARGS,
+ NULL},
+ {"Find", (PyCFunction)rpmds_Find, METH_O,
+ NULL},
+ {"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"},
+ {"Compare", (PyCFunction)rpmds_Compare, METH_O,
+ NULL},
+ {"Instance", (PyCFunction)rpmds_Instance, METH_NOARGS,
+ NULL},
+ {NULL, NULL} /* sentinel */
+};
+
+/* ---------- */
+
+static void
+rpmds_dealloc(rpmdsObject * s)
+{
+ s->ds = rpmdsFree(s->ds);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static Py_ssize_t rpmds_length(rpmdsObject * s)
+{
+ return rpmdsCount(s->ds);
+}
+
+static PyObject *
+rpmds_subscript(rpmdsObject * s, PyObject * key)
+{
+ int ix;
+
+ if (!PyInt_Check(key)) {
+ PyErr_SetString(PyExc_TypeError, "integer expected");
+ return NULL;
+ }
+
+ ix = (int) PyInt_AsLong(key);
+ rpmdsSetIx(s->ds, ix);
+ return Py_BuildValue("s", rpmdsDNEVR(s->ds));
+}
+
+static PyMappingMethods rpmds_as_mapping = {
+ (lenfunc) rpmds_length, /* mp_length */
+ (binaryfunc) rpmds_subscript, /* mp_subscript */
+ (objobjargproc)0, /* mp_ass_subscript */
+};
+
+static int rpmds_init(rpmdsObject * s, PyObject *args, PyObject *kwds)
+{
+ s->active = 0;
+ return 0;
+}
+
+static int depflags(PyObject *o, rpmsenseFlags *senseFlags)
+{
+ int ok = 0;
+ PyObject *str = NULL;
+ rpmsenseFlags flags = RPMSENSE_ANY;
+
+ if (PyInt_Check(o)) {
+ ok = 1;
+ flags = PyInt_AsLong(o);
+ } else if (utf8FromPyObject(o, &str)) {
+ ok = 1;
+ for (const char *s = PyBytes_AsString(str); *s; s++) {
+ switch (*s) {
+ case '=':
+ flags |= RPMSENSE_EQUAL;
+ break;
+ case '<':
+ flags |= RPMSENSE_LESS;
+ break;
+ case '>':
+ flags |= RPMSENSE_GREATER;
+ break;
+ default:
+ ok = 0;
+ break;
+ }
+ }
+ Py_DECREF(str);
+ }
+
+ if (flags == (RPMSENSE_EQUAL|RPMSENSE_LESS|RPMSENSE_GREATER))
+ ok = 0;
+
+ if (ok)
+ *senseFlags = flags;
+
+ return ok;
+}
+
+static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+ rpmTagVal tagN = RPMTAG_REQUIRENAME;
+ rpmds ds = NULL;
+ Header h = NULL;
+ char * kwlist[] = {"obj", "tag", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:rpmds_new", kwlist,
+ &obj, tagNumFromPyObject, &tagN))
+ return NULL;
+
+ if (PyTuple_Check(obj)) {
+ const char *name = NULL;
+ const char *evr = NULL;
+ 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);
+ } 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);
+ } else {
+ ds = rpmdsNew(h, tagN, 0);
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError, "header or tuple expected");
+ return NULL;
+ }
+
+ return rpmds_Wrap(subtype, ds);
+}
+
+static char rpmds_doc[] =
+"";
+
+PyTypeObject rpmds_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.ds", /* tp_name */
+ sizeof(rpmdsObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor) rpmds_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ &rpmds_as_mapping, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmds_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmds_iternext, /* tp_iternext */
+ rpmds_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 */
+ (initproc) rpmds_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc) rpmds_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+/* ---------- */
+
+rpmds dsFromDs(rpmdsObject * s)
+{
+ return s->ds;
+}
+
+PyObject * rpmds_Wrap(PyTypeObject *subtype, rpmds ds)
+{
+ rpmdsObject * s = (rpmdsObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->ds = ds;
+ s->active = 0;
+ return (PyObject *) s;
+}
+
diff --git a/python/rpmds-py.h b/python/rpmds-py.h
new file mode 100644
index 0000000..ffbdef4
--- /dev/null
+++ b/python/rpmds-py.h
@@ -0,0 +1,16 @@
+#ifndef H_RPMDS_PY
+#define H_RPMDS_PY
+
+#include <rpm/rpmds.h>
+
+typedef struct rpmdsObject_s rpmdsObject;
+
+extern PyTypeObject rpmds_Type;
+
+#define rpmdsObject_Check(v) ((v)->ob_type == &rpmds_Type)
+
+rpmds dsFromDs(rpmdsObject * ds);
+
+PyObject * rpmds_Wrap(PyTypeObject *subtype, rpmds ds);
+
+#endif
diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c
new file mode 100644
index 0000000..f3536ea
--- /dev/null
+++ b/python/rpmfd-py.c
@@ -0,0 +1,354 @@
+
+#include "rpmsystem-py.h"
+#include <rpm/rpmstring.h>
+#include "header-py.h" /* XXX for utf8FromPyObject() only */
+#include "rpmfd-py.h"
+
+struct rpmfdObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ FD_t fd;
+};
+
+FD_t rpmfdGetFd(rpmfdObject *fdo)
+{
+ return fdo->fd;
+}
+
+int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop)
+{
+ rpmfdObject *fdo = NULL;
+
+ if (rpmfdObject_Check(obj)) {
+ Py_INCREF(obj);
+ fdo = (rpmfdObject *) obj;
+ } else {
+ fdo = (rpmfdObject *) PyObject_Call((PyObject *)&rpmfd_Type,
+ Py_BuildValue("(O)", obj), NULL);
+ }
+ if (fdo == NULL) return 0;
+
+ if (Ferror(fdo->fd)) {
+ Py_DECREF(fdo);
+ PyErr_SetString(PyExc_IOError, Fstrerror(fdo->fd));
+ return 0;
+ }
+ *fdop = fdo;
+ return 1;
+}
+
+static PyObject *err_closed(void)
+{
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
+ return NULL;
+}
+
+static FD_t openPath(const char *path, const char *mode, const char *flags)
+{
+ FD_t fd;
+ char *m = rstrscat(NULL, mode, ".", flags, NULL);
+ Py_BEGIN_ALLOW_THREADS
+ fd = Fopen(path, m);
+ Py_END_ALLOW_THREADS;
+ free(m);
+ return fd;
+}
+
+static PyObject *rpmfd_new(PyTypeObject *subtype,
+ PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = { "obj", "mode", "flags", NULL };
+ char *mode = "r";
+ char *flags = "ufdio";
+ PyObject *fo = NULL;
+ rpmfdObject *s = NULL;
+ FD_t fd = NULL;
+ int fdno;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss", kwlist,
+ &fo, &mode, &flags))
+ return NULL;
+
+ if (PyBytes_Check(fo)) {
+ fd = openPath(PyBytes_AsString(fo), mode, flags);
+ } else if (PyUnicode_Check(fo)) {
+ PyObject *enc = NULL;
+ int rc;
+#if PY_MAJOR_VERSION >= 3
+ rc = PyUnicode_FSConverter(fo, &enc);
+#else
+ rc = utf8FromPyObject(fo, &enc);
+#endif
+ if (rc == 0)
+ return NULL;
+
+ fd = openPath(PyBytes_AsString(enc), mode, flags);
+ Py_DECREF(enc);
+
+ } else if ((fdno = PyObject_AsFileDescriptor(fo)) >= 0) {
+ fd = fdDup(fdno);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "path or file object expected");
+ return NULL;
+ }
+
+ if (Ferror(fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(fd));
+ return NULL;
+ }
+
+ if ((s = (rpmfdObject *)subtype->tp_alloc(subtype, 0)) == NULL) {
+ Fclose(fd);
+ return NULL;
+ }
+ /* TODO: remember our filename, mode & flags */
+ s->fd = fd;
+ return (PyObject*) s;
+}
+
+static PyObject *do_close(rpmfdObject *s)
+{
+ /* mimic python fileobject: close on closed file is not an error */
+ if (s->fd) {
+ Py_BEGIN_ALLOW_THREADS
+ Fclose(s->fd);
+ Py_END_ALLOW_THREADS
+ s->fd = NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfd_close(rpmfdObject *s)
+{
+ return do_close(s);
+}
+
+static void rpmfd_dealloc(rpmfdObject *s)
+{
+ PyObject *res = do_close(s);
+ Py_XDECREF(res);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject *rpmfd_fileno(rpmfdObject *s)
+{
+ int fno;
+ if (s->fd == NULL) return err_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ fno = Fileno(s->fd);
+ Py_END_ALLOW_THREADS
+
+ if (Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ return NULL;
+ }
+ return Py_BuildValue("i", fno);
+}
+
+static PyObject *rpmfd_flush(rpmfdObject *s)
+{
+ int rc;
+
+ if (s->fd == NULL) return err_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = Fflush(s->fd);
+ Py_END_ALLOW_THREADS
+
+ if (rc || Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfd_isatty(rpmfdObject *s)
+{
+ int fileno;
+ if (s->fd == NULL) return err_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ fileno = Fileno(s->fd);
+ Py_END_ALLOW_THREADS
+
+ if (Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ return NULL;
+ }
+ return PyBool_FromLong(isatty(fileno));
+}
+
+static PyObject *rpmfd_seek(rpmfdObject *s, PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = { "offset", "whence", NULL };
+ off_t offset;
+ int whence = SEEK_SET;
+ int rc = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwlist,
+ &offset, &whence))
+ return NULL;
+
+ if (s->fd == NULL) return err_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = Fseek(s->fd, offset, whence);
+ Py_END_ALLOW_THREADS
+ if (rc < 0 || Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfd_tell(rpmfdObject *s)
+{
+ off_t offset;
+ Py_BEGIN_ALLOW_THREADS
+ offset = Ftell(s->fd);
+ Py_END_ALLOW_THREADS
+ return Py_BuildValue("L", offset);
+
+}
+
+static PyObject *rpmfd_read(rpmfdObject *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->fd == NULL) return err_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 = Fread(buf, 1, chunksize, s->fd);
+ Py_END_ALLOW_THREADS
+
+ if (nb > 0) {
+ PyObject *tmp = PyBytes_FromStringAndSize(buf, nb);
+ PyString_ConcatAndDel(&res, tmp);
+ left -= nb;
+ }
+ } while (nb > 0);
+
+ if (Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ Py_XDECREF(res);
+ return NULL;
+ } else {
+ return res;
+ }
+}
+
+static PyObject *rpmfd_write(rpmfdObject *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->fd == NULL) return err_closed();
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = Fwrite(buf, 1, size, s->fd);
+ Py_END_ALLOW_THREADS
+
+ if (Ferror(s->fd)) {
+ PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
+ return NULL;
+ }
+ return Py_BuildValue("n", rc);
+}
+
+static char rpmfd_doc[] = "";
+
+static struct PyMethodDef rpmfd_methods[] = {
+ { "close", (PyCFunction) rpmfd_close, METH_NOARGS,
+ NULL },
+ { "fileno", (PyCFunction) rpmfd_fileno, METH_NOARGS,
+ NULL },
+ { "flush", (PyCFunction) rpmfd_flush, METH_NOARGS,
+ NULL },
+ { "isatty", (PyCFunction) rpmfd_isatty, METH_NOARGS,
+ NULL },
+ { "read", (PyCFunction) rpmfd_read, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "seek", (PyCFunction) rpmfd_seek, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "tell", (PyCFunction) rpmfd_tell, METH_NOARGS,
+ NULL },
+ { "write", (PyCFunction) rpmfd_write, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { NULL, NULL }
+};
+
+static PyObject *rpmfd_get_closed(rpmfdObject *s)
+{
+ return PyBool_FromLong((s->fd == NULL));
+}
+
+static PyGetSetDef rpmfd_getseters[] = {
+ { "closed", (getter)rpmfd_get_closed, NULL, NULL },
+ { NULL },
+};
+
+PyTypeObject rpmfd_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.fd", /* tp_name */
+ sizeof(rpmfdObject), /* tp_size */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor) rpmfd_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmfd_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmfd_methods, /* tp_methods */
+ 0, /* tp_members */
+ rpmfd_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)0, /* tp_init */
+ (allocfunc)0, /* tp_alloc */
+ (newfunc) rpmfd_new, /* tp_new */
+ (freefunc)0, /* tp_free */
+ 0, /* tp_is_gc */
+};
diff --git a/python/rpmfd-py.h b/python/rpmfd-py.h
new file mode 100644
index 0000000..b84e174
--- /dev/null
+++ b/python/rpmfd-py.h
@@ -0,0 +1,17 @@
+#ifndef H_RPMFD_PY
+#define H_RPMFD_PY
+
+#include <rpm/rpmio.h>
+
+typedef struct rpmfdObject_s rpmfdObject;
+
+extern PyTypeObject rpmfd_Type;
+
+#define rpmfdObject_Check(v) ((v)->ob_type == &rpmfd_Type)
+
+FD_t rpmfdGetFd(rpmfdObject *fdo);
+
+int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop);
+
+
+#endif
diff --git a/python/rpmfi-py.c b/python/rpmfi-py.c
new file mode 100644
index 0000000..52a2a3a
--- /dev/null
+++ b/python/rpmfi-py.c
@@ -0,0 +1,378 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmpgp.h>
+
+#include "header-py.h"
+#include "rpmfi-py.h"
+
+#include "debug.h"
+
+struct rpmfiObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ int active;
+ rpmfi fi;
+};
+
+static PyObject *
+rpmfi_FC(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFC(s->fi));
+}
+
+static PyObject *
+rpmfi_FX(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFX(s->fi));
+}
+
+static PyObject *
+rpmfi_DC(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiDC(s->fi));
+}
+
+static PyObject *
+rpmfi_DX(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiDX(s->fi));
+}
+
+static PyObject *
+rpmfi_BN(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiBN(s->fi));
+}
+
+static PyObject *
+rpmfi_DN(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiDN(s->fi));
+}
+
+static PyObject *
+rpmfi_FN(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiFN(s->fi));
+}
+
+static PyObject *
+rpmfi_FFlags(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFFlags(s->fi));
+}
+
+static PyObject *
+rpmfi_VFlags(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiVFlags(s->fi));
+}
+
+static PyObject *
+rpmfi_FMode(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFMode(s->fi));
+}
+
+static PyObject *
+rpmfi_FState(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFState(s->fi));
+}
+
+/* XXX rpmfiFDigest */
+static PyObject *
+rpmfi_Digest(rpmfiObject * s)
+{
+ char *digest = rpmfiFDigestHex(s->fi, NULL);
+ if (digest) {
+ PyObject *dig = Py_BuildValue("s", digest);
+ free(digest);
+ return dig;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject *
+rpmfi_FLink(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiFLink(s->fi));
+}
+
+static PyObject *
+rpmfi_FSize(rpmfiObject * s)
+{
+ return Py_BuildValue("L", rpmfiFSize(s->fi));
+}
+
+static PyObject *
+rpmfi_FRdev(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFRdev(s->fi));
+}
+
+static PyObject *
+rpmfi_FMtime(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFMtime(s->fi));
+}
+
+static PyObject *
+rpmfi_FUser(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiFUser(s->fi));
+}
+
+static PyObject *
+rpmfi_FGroup(rpmfiObject * s)
+{
+ return Py_BuildValue("s", rpmfiFGroup(s->fi));
+}
+
+static PyObject *
+rpmfi_FColor(rpmfiObject * s)
+{
+ return Py_BuildValue("i", rpmfiFColor(s->fi));
+}
+
+static PyObject *
+rpmfi_FClass(rpmfiObject * s)
+{
+ const char * FClass;
+
+ if ((FClass = rpmfiFClass(s->fi)) == NULL)
+ FClass = "";
+ return Py_BuildValue("s", FClass);
+}
+
+static PyObject *
+rpmfi_iternext(rpmfiObject * s)
+{
+ PyObject * result = NULL;
+
+ /* Reset loop indices on 1st entry. */
+ if (!s->active) {
+ s->fi = rpmfiInit(s->fi, 0);
+ s->active = 1;
+ }
+
+ /* If more to do, return the file tuple. */
+ if (rpmfiNext(s->fi) >= 0) {
+ const char * FN = rpmfiFN(s->fi);
+ rpm_loff_t FSize = rpmfiFSize(s->fi);
+ int FMode = rpmfiFMode(s->fi);
+ int FMtime = rpmfiFMtime(s->fi);
+ int FFlags = rpmfiFFlags(s->fi);
+ int FRdev = rpmfiFRdev(s->fi);
+ int FInode = rpmfiFInode(s->fi);
+ int FNlink = rpmfiFNlink(s->fi);
+ int FState = rpmfiFState(s->fi);
+ int VFlags = rpmfiVFlags(s->fi);
+ const char * FUser = rpmfiFUser(s->fi);
+ const char * FGroup = rpmfiFGroup(s->fi);
+
+ result = PyTuple_New(13);
+ if (FN == NULL) {
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(result, 0, Py_None);
+ } else
+ PyTuple_SET_ITEM(result, 0, Py_BuildValue("s", FN));
+ PyTuple_SET_ITEM(result, 1, PyLong_FromLongLong(FSize));
+ PyTuple_SET_ITEM(result, 2, PyInt_FromLong(FMode));
+ PyTuple_SET_ITEM(result, 3, PyInt_FromLong(FMtime));
+ PyTuple_SET_ITEM(result, 4, PyInt_FromLong(FFlags));
+ PyTuple_SET_ITEM(result, 5, PyInt_FromLong(FRdev));
+ PyTuple_SET_ITEM(result, 6, PyInt_FromLong(FInode));
+ PyTuple_SET_ITEM(result, 7, PyInt_FromLong(FNlink));
+ PyTuple_SET_ITEM(result, 8, PyInt_FromLong(FState));
+ PyTuple_SET_ITEM(result, 9, PyInt_FromLong(VFlags));
+ if (FUser == NULL) {
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(result, 10, Py_None);
+ } else
+ PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
+ if (FGroup == NULL) {
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(result, 11, Py_None);
+ } else
+ PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
+ PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s));
+
+ } else
+ s->active = 0;
+
+ return result;
+}
+
+static struct PyMethodDef rpmfi_methods[] = {
+ {"FC", (PyCFunction)rpmfi_FC, METH_NOARGS,
+ NULL},
+ {"FX", (PyCFunction)rpmfi_FX, METH_NOARGS,
+ NULL},
+ {"DC", (PyCFunction)rpmfi_DC, METH_NOARGS,
+ NULL},
+ {"DX", (PyCFunction)rpmfi_DX, METH_NOARGS,
+ NULL},
+ {"BN", (PyCFunction)rpmfi_BN, METH_NOARGS,
+ NULL},
+ {"DN", (PyCFunction)rpmfi_DN, METH_NOARGS,
+ NULL},
+ {"FN", (PyCFunction)rpmfi_FN, METH_NOARGS,
+ NULL},
+ {"FFlags", (PyCFunction)rpmfi_FFlags, METH_NOARGS,
+ NULL},
+ {"VFlags", (PyCFunction)rpmfi_VFlags, METH_NOARGS,
+ NULL},
+ {"FMode", (PyCFunction)rpmfi_FMode, METH_NOARGS,
+ NULL},
+ {"FState", (PyCFunction)rpmfi_FState, METH_NOARGS,
+ NULL},
+ {"MD5", (PyCFunction)rpmfi_Digest, METH_NOARGS,
+ NULL},
+ {"Digest", (PyCFunction)rpmfi_Digest, METH_NOARGS,
+ NULL},
+ {"FLink", (PyCFunction)rpmfi_FLink, METH_NOARGS,
+ NULL},
+ {"FSize", (PyCFunction)rpmfi_FSize, METH_NOARGS,
+ NULL},
+ {"FRdev", (PyCFunction)rpmfi_FRdev, METH_NOARGS,
+ NULL},
+ {"FMtime", (PyCFunction)rpmfi_FMtime, METH_NOARGS,
+ NULL},
+ {"FUser", (PyCFunction)rpmfi_FUser, METH_NOARGS,
+ NULL},
+ {"FGroup", (PyCFunction)rpmfi_FGroup, METH_NOARGS,
+ NULL},
+ {"FColor", (PyCFunction)rpmfi_FColor, METH_NOARGS,
+ NULL},
+ {"FClass", (PyCFunction)rpmfi_FClass, METH_NOARGS,
+ NULL},
+ {NULL, NULL} /* sentinel */
+};
+
+/* ---------- */
+
+static void
+rpmfi_dealloc(rpmfiObject * s)
+{
+ s->fi = rpmfiFree(s->fi);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static int
+rpmfi_length(rpmfiObject * s)
+{
+ return rpmfiFC(s->fi);
+}
+
+static PyObject *
+rpmfi_subscript(rpmfiObject * s, PyObject * key)
+{
+ int ix;
+
+ if (!PyInt_Check(key)) {
+ PyErr_SetString(PyExc_TypeError, "integer expected");
+ return NULL;
+ }
+
+ ix = (int) PyInt_AsLong(key);
+ rpmfiSetFX(s->fi, ix);
+ return Py_BuildValue("s", rpmfiFN(s->fi));
+}
+
+static PyMappingMethods rpmfi_as_mapping = {
+ (lenfunc) rpmfi_length, /* mp_length */
+ (binaryfunc) rpmfi_subscript, /* mp_subscript */
+ (objobjargproc)0, /* mp_ass_subscript */
+};
+
+static int rpmfi_init(rpmfiObject * s, PyObject *args, PyObject *kwds)
+{
+ s->active = 0;
+ return 0;
+}
+
+static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+{
+ PyObject * to = NULL;
+ Header h = NULL;
+ rpmfi fi = NULL;
+ rpmTagVal tagN = RPMTAG_BASENAMES;
+ int flags = 0;
+ char * kwlist[] = {"header", "tag", "flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|Oi:rpmfi_init", kwlist,
+ hdrFromPyObject, &h, &to, &flags))
+ return NULL;
+
+ fi = rpmfiNew(NULL, h, tagN, flags);
+
+ return rpmfi_Wrap(subtype, fi);
+}
+
+static char rpmfi_doc[] =
+"";
+
+PyTypeObject rpmfi_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.fi", /* tp_name */
+ sizeof(rpmfiObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor) rpmfi_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ &rpmfi_as_mapping, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmfi_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmfi_iternext, /* tp_iternext */
+ rpmfi_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 */
+ (initproc) rpmfi_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc) rpmfi_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+/* ---------- */
+
+rpmfi fiFromFi(rpmfiObject * s)
+{
+ return s->fi;
+}
+
+PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi)
+{
+ rpmfiObject *s = (rpmfiObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->fi = fi;
+ s->active = 0;
+ return (PyObject *) s;
+}
+
diff --git a/python/rpmfi-py.h b/python/rpmfi-py.h
new file mode 100644
index 0000000..604bf71
--- /dev/null
+++ b/python/rpmfi-py.h
@@ -0,0 +1,16 @@
+#ifndef H_RPMFI_PY
+#define H_RPMFI_PY
+
+#include <rpm/rpmfi.h>
+
+typedef struct rpmfiObject_s rpmfiObject;
+
+extern PyTypeObject rpmfi_Type;
+
+#define rpmfiObject_Check(v) ((v)->ob_type == &rpmfi_Type)
+
+rpmfi fiFromFi(rpmfiObject * fi);
+
+PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi);
+
+#endif
diff --git a/python/rpmii-py.c b/python/rpmii-py.c
new file mode 100644
index 0000000..82817d8
--- /dev/null
+++ b/python/rpmii-py.c
@@ -0,0 +1,158 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmdb.h>
+
+#include "rpmii-py.h"
+#include "header-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \class Rpmii
+ * \brief A python rpm.ii key iterator object represents the keys of a
+ * database index.
+ *
+ * The rpm.ii class conains the following methods:
+ * - next() -> key Return the next key.
+ *
+ * To obtain a rpm.ii object to query the database used by a transaction,
+ * the ts.dbIndex(tag) method is used.
+ *
+ * Here's an example that prints the name of all installed packages:
+ * \code
+ * import rpm
+ * ts = rpm.TransactionSet()
+ * for name in ts.dbIndex("conflictname"):
+ * print name
+ * \endcode
+ *
+ * ts.dbIndex() can be used to get the packages containing the keys of interest
+ */
+
+/** \ingroup python
+ * \name Class: Rpmii
+ */
+
+struct rpmiiObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ PyObject *ref; /* for db/ts refcounting */
+ rpmdbIndexIterator ii;
+};
+
+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;
+ }
+ return PyBytes_FromStringAndSize(key, keylen);
+};
+
+static PyObject *
+rpmii_instances(rpmiiObject * s)
+{
+ int entries = rpmdbIndexIteratorNumPkgs(s->ii);
+ PyObject * list = PyList_New(0);
+ PyObject * tuple;
+ for (int i = 0; i < entries; i++) {
+ tuple = PyTuple_New(2);
+ PyTuple_SET_ITEM(tuple, 0,
+ PyInt_FromLong(rpmdbIndexIteratorPkgOffset(s->ii, i)));
+ PyTuple_SET_ITEM(tuple, 1,
+ PyInt_FromLong(rpmdbIndexIteratorTagNum(s->ii, i)));
+ PyList_Append(list, tuple);
+ }
+ return list;
+}
+
+static struct PyMethodDef rpmii_methods[] = {
+ {"instances", (PyCFunction) rpmii_instances, METH_NOARGS, NULL},
+ {NULL, NULL} /* sentinel */
+};
+
+static void rpmii_dealloc(rpmiiObject * s)
+{
+ s->ii = rpmdbIndexIteratorFree(s->ii);
+ Py_DECREF(s->ref);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static int rpmii_bool(rpmiiObject *s)
+{
+ return (s->ii != NULL);
+}
+
+static PyNumberMethods rpmii_as_number = {
+ 0, /* nb_add */
+ 0, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_divide */
+ 0, /* nb_remainder */
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ (inquiry)rpmii_bool, /* nb_bool/nonzero */
+};
+
+static char rpmii_doc[] =
+"";
+
+PyTypeObject rpmii_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.ii", /* tp_name */
+ sizeof(rpmiiObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmii_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ &rpmii_as_number, /* 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 */
+ rpmii_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmii_iternext, /* tp_iternext */
+ rpmii_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 * rpmii_Wrap(PyTypeObject *subtype, rpmdbIndexIterator ii, PyObject *s)
+{
+ rpmiiObject * iio = (rpmiiObject *)subtype->tp_alloc(subtype, 0);
+ if (iio == NULL) return NULL;
+
+ iio->ii = ii;
+ iio->ref = s;
+ Py_INCREF(iio->ref);
+ return (PyObject *) iio;
+}
diff --git a/python/rpmii-py.h b/python/rpmii-py.h
new file mode 100644
index 0000000..bcfc5ff
--- /dev/null
+++ b/python/rpmii-py.h
@@ -0,0 +1,12 @@
+#ifndef H_RPMII_PY
+#define H_RPMII_PY
+
+typedef struct rpmiiObject_s rpmiiObject;
+
+extern PyTypeObject rpmii_Type;
+
+#define rpmiiObject_Check(v) ((v)->ob_type == &rpmii_Type)
+
+PyObject * rpmii_Wrap(PyTypeObject *subtype, rpmdbIndexIterator ii, PyObject *s);
+
+#endif
diff --git a/python/rpmkeyring-py.c b/python/rpmkeyring-py.c
new file mode 100644
index 0000000..d5f131e
--- /dev/null
+++ b/python/rpmkeyring-py.c
@@ -0,0 +1,202 @@
+#include "rpmsystem-py.h"
+#include <rpm/rpmkeyring.h>
+#include "rpmkeyring-py.h"
+
+struct rpmPubkeyObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmPubkey pubkey;
+};
+
+static void rpmPubkey_dealloc(rpmPubkeyObject * s)
+{
+ s->pubkey = rpmPubkeyFree(s->pubkey);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject *rpmPubkey_new(PyTypeObject *subtype,
+ PyObject *args, PyObject *kwds)
+{
+ PyObject *key;
+ char *kwlist[] = { "key", NULL };
+ rpmPubkey pubkey = NULL;
+ uint8_t *pkt;
+ size_t pktlen;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S", kwlist, &key))
+ return NULL;
+
+ if (pgpParsePkts(PyBytes_AsString(key), &pkt, &pktlen) <= 0) {
+ PyErr_SetString(PyExc_ValueError, "invalid pubkey");
+ return NULL;
+ }
+ pubkey = rpmPubkeyNew(pkt, pktlen);
+
+ return rpmPubkey_Wrap(subtype, pubkey);
+}
+
+static PyObject * rpmPubkey_Base64(rpmPubkeyObject *s)
+{
+ char *b64 = rpmPubkeyBase64(s->pubkey);
+ PyObject *res = Py_BuildValue("s", b64);
+ free(b64);
+ return res;
+}
+
+static struct PyMethodDef rpmPubkey_methods[] = {
+ { "base64", (PyCFunction) rpmPubkey_Base64, METH_NOARGS, NULL },
+ { NULL }
+};
+
+static char rpmPubkey_doc[] = "";
+
+PyTypeObject rpmPubkey_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.pubkey", /* tp_name */
+ sizeof(rpmPubkeyObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmPubkey_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 */
+ 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 */
+ rpmPubkey_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmPubkey_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 */
+ rpmPubkey_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+struct rpmKeyringObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmKeyring keyring;
+};
+
+static void rpmKeyring_dealloc(rpmKeyringObject * s)
+{
+ rpmKeyringFree(s->keyring);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject *rpmKeyring_new(PyTypeObject *subtype,
+ PyObject *args, PyObject *kwds)
+{
+ rpmKeyring keyring = rpmKeyringNew();
+ return rpmKeyring_Wrap(subtype, keyring);
+}
+
+static PyObject *rpmKeyring_addKey(rpmKeyringObject *s, PyObject *arg)
+{
+ rpmPubkeyObject *pubkey = NULL;
+
+ if (!PyArg_Parse(arg, "O!", &rpmPubkey_Type, &pubkey))
+ return NULL;
+
+ return Py_BuildValue("i", rpmKeyringAddKey(s->keyring, pubkey->pubkey));
+};
+
+static struct PyMethodDef rpmKeyring_methods[] = {
+ { "addKey", (PyCFunction) rpmKeyring_addKey, METH_O,
+ NULL },
+ {NULL, NULL} /* sentinel */
+};
+
+static char rpmKeyring_doc[] =
+"";
+
+PyTypeObject rpmKeyring_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.keyring", /* tp_name */
+ sizeof(rpmKeyringObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmKeyring_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 */
+ rpmKeyring_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmKeyring_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 */
+ rpmKeyring_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject * rpmPubkey_Wrap(PyTypeObject *subtype, rpmPubkey pubkey)
+{
+ rpmPubkeyObject *s = (rpmPubkeyObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->pubkey = pubkey;
+ return (PyObject*) s;
+}
+
+PyObject * rpmKeyring_Wrap(PyTypeObject *subtype, rpmKeyring keyring)
+{
+ rpmKeyringObject *s = (rpmKeyringObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->keyring = keyring;
+ return (PyObject*) s;
+}
+
+int rpmKeyringFromPyObject(PyObject *item, rpmKeyring *keyring)
+{
+ rpmKeyringObject *kro;
+ if (!PyArg_Parse(item, "O!", &rpmKeyring_Type, &kro))
+ return 0;
+ *keyring = kro->keyring;
+ return 1;
+}
diff --git a/python/rpmkeyring-py.h b/python/rpmkeyring-py.h
new file mode 100644
index 0000000..4ba017c
--- /dev/null
+++ b/python/rpmkeyring-py.h
@@ -0,0 +1,16 @@
+#ifndef H_RPMKEYRING_PY
+#define H_RPMKEYRING_PY
+
+#include <rpm/rpmtypes.h>
+
+typedef struct rpmPubkeyObject_s rpmPubkeyObject;
+typedef struct rpmKeyringObject_s rpmKeyringObject;
+
+extern PyTypeObject rpmKeyring_Type;
+extern PyTypeObject rpmPubkey_Type;
+
+PyObject * rpmPubkey_Wrap(PyTypeObject *subtype, rpmPubkey pubkey);
+PyObject * rpmKeyring_Wrap(PyTypeObject *subtype, rpmKeyring keyring);
+
+int rpmKeyringFromPyObject(PyObject *item, rpmKeyring *keyring);
+#endif
diff --git a/python/rpmmacro-py.c b/python/rpmmacro-py.c
new file mode 100644
index 0000000..dec8de0
--- /dev/null
+++ b/python/rpmmacro-py.c
@@ -0,0 +1,58 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmmacro.h>
+
+#include "rpmmacro-py.h"
+
+#include "debug.h"
+
+PyObject *
+rpmmacro_AddMacro(PyObject * self, PyObject * args, PyObject * kwds)
+{
+ char * name, * val;
+ char * kwlist[] = {"name", "value", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss:AddMacro", kwlist,
+ &name, &val))
+ return NULL;
+
+ addMacro(NULL, name, NULL, val, -1);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *
+rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds)
+{
+ char * name;
+ char * kwlist[] = {"name", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:DelMacro", kwlist, &name))
+ return NULL;
+
+ delMacro(NULL, name);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *
+rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds)
+{
+ char *macro;
+ PyObject *res;
+ int num = 0;
+ char * kwlist[] = {"macro", "numeric", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &macro, &num))
+ return NULL;
+
+ if (num) {
+ res = Py_BuildValue("i", rpmExpandNumeric(macro));
+ } else {
+ char *str = rpmExpand(macro, NULL);
+ res = Py_BuildValue("s", str);
+ free(str);
+ }
+ return res;
+}
+
diff --git a/python/rpmmacro-py.h b/python/rpmmacro-py.h
new file mode 100644
index 0000000..c9abffe
--- /dev/null
+++ b/python/rpmmacro-py.h
@@ -0,0 +1,8 @@
+#ifndef H_RPMMACRO_PY
+#define H_RPMMACRO_PY
+
+PyObject * rpmmacro_AddMacro(PyObject * self, PyObject * args, PyObject * kwds);
+PyObject * rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds);
+PyObject * rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds);
+
+#endif
diff --git a/python/rpmmi-py.c b/python/rpmmi-py.c
new file mode 100644
index 0000000..0b1c27a
--- /dev/null
+++ b/python/rpmmi-py.c
@@ -0,0 +1,220 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmdb.h>
+
+#include "rpmmi-py.h"
+#include "header-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \class Rpmmi
+ * \brief A python rpm.mi match iterator object represents the result of a
+ * database query.
+ *
+ * Instances of the rpm.mi object provide access to headers that match
+ * certain criteria. Typically, a primary index is accessed to find
+ * a set of headers that contain a key, and each header is returned
+ * serially.
+ *
+ * The rpm.mi class conains the following methods:
+ * - next() -> hdr Return the next header that matches.
+ *
+ * - pattern(tag,mire,pattern) Specify secondary match criteria.
+ *
+ * To obtain a rpm.mi object to query the database used by a transaction,
+ * the ts.match(tag,key,len) method is used.
+ *
+ * Here's an example that prints the name of all installed packages:
+ * \code
+ * import rpm
+ * ts = rpm.TransactionSet()
+ * for h in ts.dbMatch():
+ * print h['name']
+ * \endcode
+ *
+ * Here's a more typical example that uses the Name index to retrieve
+ * all installed kernel(s):
+ * \code
+ * import rpm
+ * ts = rpm.TransactionSet()
+ * mi = ts.dbMatch('name', "kernel")
+ * for h in mi:
+ * 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*":
+ * \code
+ * import rpm
+ * ts = rpm.TransactionSet()
+ * mi = ts.dbMatch()
+ * mi.pattern('name', rpm.RPMMIRE_GLOB, "XFree*")
+ * for h in mi:
+ * print "%s-%s-%s" % (h['name'], h['version'], h['release'])
+ * \endcode
+ *
+ */
+
+/** \ingroup python
+ * \name Class: Rpmmi
+ */
+
+struct rpmmiObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ PyObject *ref; /* for db/ts refcounting */
+ rpmdbMatchIterator mi;
+} ;
+
+static PyObject *
+rpmmi_iternext(rpmmiObject * s)
+{
+ Header h;
+
+ if (s->mi == NULL || (h = rpmdbNextIterator(s->mi)) == NULL) {
+ s->mi = rpmdbFreeIterator(s->mi);
+ return NULL;
+ }
+ return hdr_Wrap(&hdr_Type, h);
+}
+
+static PyObject *
+rpmmi_Instance(rpmmiObject * s)
+{
+ int rc = 0;
+
+ if (s->mi != NULL)
+ rc = rpmdbGetIteratorOffset(s->mi);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmmi_Count(rpmmiObject * s)
+{
+ DEPRECATED_METHOD("use len(mi) instead");
+ return Py_BuildValue("i", PyMapping_Size((PyObject *)s));
+}
+
+static PyObject *
+rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds)
+{
+ int type;
+ char * pattern;
+ rpmTagVal tag;
+ char * kwlist[] = {"tag", "type", "patern", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&is:Pattern", kwlist,
+ tagNumFromPyObject, &tag, &type, &pattern))
+ return NULL;
+
+ rpmdbSetIteratorRE(s->mi, tag, type, pattern);
+
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef rpmmi_methods[] = {
+ {"instance", (PyCFunction) rpmmi_Instance, METH_NOARGS,
+ NULL },
+ {"count", (PyCFunction) rpmmi_Count, METH_NOARGS,
+"Deprecated, use len(mi) instead.\n" },
+ {"pattern", (PyCFunction) rpmmi_Pattern, METH_VARARGS|METH_KEYWORDS,
+"mi.pattern(TagN, mire_type, pattern)\n\
+- Set a secondary match pattern on tags from retrieved header.\n" },
+ {NULL, NULL} /* sentinel */
+};
+
+static void rpmmi_dealloc(rpmmiObject * s)
+{
+ s->mi = rpmdbFreeIterator(s->mi);
+ Py_DECREF(s->ref);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static Py_ssize_t rpmmi_length(rpmmiObject * s)
+{
+ return s->mi ? rpmdbGetIteratorCount(s->mi) : 0;
+}
+
+static int rpmmi_bool(rpmmiObject *s)
+{
+ return (s->mi != NULL);
+}
+
+PyMappingMethods rpmmi_as_mapping = {
+ (lenfunc) rpmmi_length, /* mp_length */
+ 0,
+};
+
+static PyNumberMethods rpmmi_as_number = {
+ 0, /* nb_add */
+ 0, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_divide */
+ 0, /* nb_remainder */
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ (inquiry)rpmmi_bool, /* nb_bool/nonzero */
+};
+
+static char rpmmi_doc[] =
+"";
+
+PyTypeObject rpmmi_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.mi", /* tp_name */
+ sizeof(rpmmiObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmmi_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ &rpmmi_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ &rpmmi_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 */
+ rpmmi_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmmi_iternext, /* tp_iternext */
+ rpmmi_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 * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s)
+{
+ rpmmiObject * mio = (rpmmiObject *)subtype->tp_alloc(subtype, 0);
+ if (mio == NULL) return NULL;
+
+ mio->mi = mi;
+ mio->ref = s;
+ Py_INCREF(mio->ref);
+ return (PyObject *) mio;
+}
+
diff --git a/python/rpmmi-py.h b/python/rpmmi-py.h
new file mode 100644
index 0000000..ef07c72
--- /dev/null
+++ b/python/rpmmi-py.h
@@ -0,0 +1,12 @@
+#ifndef H_RPMMI_PY
+#define H_RPMMI_PY
+
+typedef struct rpmmiObject_s rpmmiObject;
+
+extern PyTypeObject rpmmi_Type;
+
+#define rpmmiObject_Check(v) ((v)->ob_type == &rpmmi_Type)
+
+PyObject * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s);
+
+#endif
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
new file mode 100644
index 0000000..0b69d4f
--- /dev/null
+++ b/python/rpmmodule.c
@@ -0,0 +1,504 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmlib.h> /* rpmMachineScore, rpmReadConfigFiles */
+#include <rpm/rpmtag.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmsq.h>
+#include <rpm/rpmlog.h>
+
+#include "header-py.h"
+#include "rpmds-py.h"
+#include "rpmfd-py.h"
+#include "rpmfi-py.h"
+#include "rpmkeyring-py.h"
+#include "rpmmi-py.h"
+#include "rpmii-py.h"
+#include "rpmps-py.h"
+#include "rpmmacro-py.h"
+#include "rpmtd-py.h"
+#include "rpmte-py.h"
+#include "rpmts-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \name Module: rpm
+ */
+
+PyObject * pyrpmError;
+
+static PyObject * archScore(PyObject * self, PyObject * arg)
+{
+ char * arch;
+
+ if (!PyArg_Parse(arg, "s", &arch))
+ return NULL;
+
+ return Py_BuildValue("i", rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch));
+}
+
+static PyObject * signalCaught(PyObject *self, PyObject *o)
+{
+ int signo;
+ if (!PyArg_Parse(o, "i", &signo)) return NULL;
+
+ return PyBool_FromLong(rpmsqIsCaught(signo));
+}
+
+static PyObject * checkSignals(PyObject * self)
+{
+ rpmdbCheckSignals();
+ Py_RETURN_NONE;
+}
+
+static PyObject * setLogFile (PyObject * self, PyObject *arg)
+{
+ FILE *fp;
+ int fdno = PyObject_AsFileDescriptor(arg);
+
+ if (fdno >= 0) {
+ /* XXX we dont know the mode here.. guessing append for now */
+ fp = fdopen(fdno, "a");
+ if (fp == NULL) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ } else if (arg == Py_None) {
+ fp = NULL;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "file object or None expected");
+ return NULL;
+ }
+
+ (void) rpmlogSetFile(fp);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+setVerbosity (PyObject * self, PyObject * arg)
+{
+ int level;
+
+ if (!PyArg_Parse(arg, "i", &level))
+ return NULL;
+
+ rpmSetVerbosity(level);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+setEpochPromote (PyObject * self, PyObject * arg)
+{
+ if (!PyArg_Parse(arg, "i", &_rpmds_nopromote))
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * setStats (PyObject * self, PyObject * arg)
+{
+ if (!PyArg_Parse(arg, "i", &_rpmts_stats))
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * doLog(PyObject * self, PyObject * args, PyObject *kwds)
+{
+ int code;
+ const char *msg;
+ char * kwlist[] = {"code", "msg", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &code, &msg))
+ return NULL;
+
+ rpmlog(code, "%s", msg);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef rpmModuleMethods[] = {
+ { "addMacro", (PyCFunction) rpmmacro_AddMacro, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "delMacro", (PyCFunction) rpmmacro_DelMacro, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "expandMacro", (PyCFunction) rpmmacro_ExpandMacro, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+
+ { "archscore", (PyCFunction) archScore, METH_O,
+ NULL },
+
+ { "signalCaught", (PyCFunction) signalCaught, METH_O,
+ NULL },
+ { "checkSignals", (PyCFunction) checkSignals, METH_NOARGS,
+ NULL },
+
+ { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+
+ { "log", (PyCFunction) doLog, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "setLogFile", (PyCFunction) setLogFile, METH_O,
+ NULL },
+
+ { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "setVerbosity", (PyCFunction) setVerbosity, METH_O,
+ NULL },
+ { "setEpochPromote", (PyCFunction) setEpochPromote, METH_O,
+ NULL },
+ { "setStats", (PyCFunction) setStats, METH_O,
+ NULL },
+
+ { NULL }
+} ;
+
+/*
+* Force clean up of open iterators and dbs on exit.
+*/
+static void rpm_exithook(void)
+{
+ rpmdbCheckTerminate(1);
+}
+
+static char rpm__doc__[] =
+"";
+
+/*
+ * Add rpm tag dictionaries to the module
+ */
+static void addRpmTags(PyObject *module)
+{
+ PyObject *pyval, *pyname, *dict = PyDict_New();
+ rpmtd names = rpmtdNew();
+ rpmTagGetNames(names, 1);
+ const char *tagname, *shortname;
+ rpmTagVal tagval;
+
+ while ((tagname = rpmtdNextString(names))) {
+ shortname = tagname + strlen("RPMTAG_");
+ tagval = rpmTagGetValue(shortname);
+
+ PyModule_AddIntConstant(module, tagname, tagval);
+ pyval = PyInt_FromLong(tagval);
+ pyname = Py_BuildValue("s", shortname);
+ PyDict_SetItem(dict, pyval, pyname);
+ Py_DECREF(pyval);
+ Py_DECREF(pyname);
+ }
+ PyModule_AddObject(module, "tagnames", dict);
+ rpmtdFreeData(names);
+ rpmtdFree(names);
+}
+
+/*
+ Do any common preliminary work before python 2 vs python 3 module creation:
+*/
+static int prepareInitModule(void)
+{
+ if (PyType_Ready(&hdr_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(&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 0
+ if (PyType_Ready(&rpmtd_Type) < 0) return 0;
+#endif
+ if (PyType_Ready(&rpmte_Type) < 0) return 0;
+ if (PyType_Ready(&rpmts_Type) < 0) return 0;
+
+ return 1;
+}
+static int initModule(PyObject *m);
+
+#if PY_MAJOR_VERSION >= 3
+static int rpmModuleTraverse(PyObject *m, visitproc visit, void *arg) {
+ Py_VISIT(pyrpmError);
+ return 0;
+}
+
+static int rpmModuleClear(PyObject *m) {
+ Py_CLEAR(pyrpmError);
+ return 0;
+}
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_rpm", /* m_name */
+ rpm__doc__, /* m_doc */
+ 0, /* m_size */
+ rpmModuleMethods,
+ NULL, /* m_reload */
+ rpmModuleTraverse,
+ rpmModuleClear,
+ NULL /* m_free */
+};
+
+PyObject *
+PyInit__rpm(void);
+
+PyObject *
+PyInit__rpm(void)
+{
+ PyObject * m;
+ if (!prepareInitModule()) return NULL;
+ m = PyModule_Create(&moduledef);
+ initModule(m);
+ return m;
+}
+#else
+void init_rpm(void); /* XXX eliminate gcc warning */
+void init_rpm(void)
+{
+ PyObject * m;
+
+ if (!prepareInitModule()) return;
+ m = Py_InitModule3("_rpm", rpmModuleMethods, rpm__doc__);
+ if (m == NULL)
+ return;
+ initModule(m);
+}
+#endif
+
+/* Shared python2/3 module initialization: */
+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);
+
+ d = PyModule_GetDict(m);
+
+ pyrpmError = PyErr_NewException("_rpm.error", NULL, NULL);
+ if (pyrpmError != NULL)
+ PyDict_SetItemString(d, "error", pyrpmError);
+
+ Py_INCREF(&hdr_Type);
+ PyModule_AddObject(m, "hdr", (PyObject *) &hdr_Type);
+
+ Py_INCREF(&rpmds_Type);
+ PyModule_AddObject(m, "ds", (PyObject *) &rpmds_Type);
+
+ Py_INCREF(&rpmfd_Type);
+ PyModule_AddObject(m, "fd", (PyObject *) &rpmfd_Type);
+
+ Py_INCREF(&rpmfi_Type);
+ PyModule_AddObject(m, "fi", (PyObject *) &rpmfi_Type);
+
+ Py_INCREF(&rpmKeyring_Type);
+ PyModule_AddObject(m, "keyring", (PyObject *) &rpmKeyring_Type);
+
+ Py_INCREF(&rpmmi_Type);
+ PyModule_AddObject(m, "mi", (PyObject *) &rpmmi_Type);
+
+ Py_INCREF(&rpmii_Type);
+ PyModule_AddObject(m, "ii", (PyObject *) &rpmii_Type);
+
+ Py_INCREF(&rpmProblem_Type);
+ PyModule_AddObject(m, "prob", (PyObject *) &rpmProblem_Type);
+
+ Py_INCREF(&rpmPubkey_Type);
+ PyModule_AddObject(m, "pubkey", (PyObject *) &rpmPubkey_Type);
+
+#if 0
+ Py_INCREF(&rpmtd_Type);
+ PyModule_AddObject(m, "td", (PyObject *) &rpmtd_Type);
+#endif
+
+ Py_INCREF(&rpmte_Type);
+ PyModule_AddObject(m, "te", (PyObject *) &rpmte_Type);
+
+ Py_INCREF(&rpmts_Type);
+ PyModule_AddObject(m, "ts", (PyObject *) &rpmts_Type);
+
+ addRpmTags(m);
+
+ PyModule_AddStringConstant(m, "__version__", RPMVERSION);
+
+#define REGISTER_ENUM(val) PyModule_AddIntConstant(m, #val, val)
+
+ REGISTER_ENUM(RPMTAG_NOT_FOUND);
+
+ REGISTER_ENUM(RPMRC_OK);
+ REGISTER_ENUM(RPMRC_NOTFOUND);
+ REGISTER_ENUM(RPMRC_FAIL);
+ REGISTER_ENUM(RPMRC_NOTTRUSTED);
+ REGISTER_ENUM(RPMRC_NOKEY);
+
+ REGISTER_ENUM(RPMFILE_STATE_NORMAL);
+ REGISTER_ENUM(RPMFILE_STATE_REPLACED);
+ REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
+ REGISTER_ENUM(RPMFILE_STATE_NETSHARED);
+ REGISTER_ENUM(RPMFILE_STATE_WRONGCOLOR);
+
+ REGISTER_ENUM(RPMFILE_CONFIG);
+ REGISTER_ENUM(RPMFILE_DOC);
+ REGISTER_ENUM(RPMFILE_MISSINGOK);
+ REGISTER_ENUM(RPMFILE_NOREPLACE);
+ REGISTER_ENUM(RPMFILE_GHOST);
+ REGISTER_ENUM(RPMFILE_LICENSE);
+ REGISTER_ENUM(RPMFILE_README);
+ REGISTER_ENUM(RPMFILE_EXCLUDE);
+ REGISTER_ENUM(RPMFILE_UNPATCHED);
+ REGISTER_ENUM(RPMFILE_PUBKEY);
+
+ REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
+ REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
+
+ REGISTER_ENUM(RPMSENSE_ANY);
+ REGISTER_ENUM(RPMSENSE_LESS);
+ REGISTER_ENUM(RPMSENSE_GREATER);
+ REGISTER_ENUM(RPMSENSE_EQUAL);
+ REGISTER_ENUM(RPMSENSE_PREREQ);
+ REGISTER_ENUM(RPMSENSE_INTERP);
+ REGISTER_ENUM(RPMSENSE_SCRIPT_PRE);
+ REGISTER_ENUM(RPMSENSE_SCRIPT_POST);
+ REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN);
+ REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN);
+ REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY);
+ REGISTER_ENUM(RPMSENSE_FIND_REQUIRES);
+ REGISTER_ENUM(RPMSENSE_FIND_PROVIDES);
+ REGISTER_ENUM(RPMSENSE_TRIGGERIN);
+ REGISTER_ENUM(RPMSENSE_TRIGGERUN);
+ REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN);
+ REGISTER_ENUM(RPMSENSE_RPMLIB);
+ REGISTER_ENUM(RPMSENSE_TRIGGERPREIN);
+ REGISTER_ENUM(RPMSENSE_KEYRING);
+ REGISTER_ENUM(RPMSENSE_CONFIG);
+
+ REGISTER_ENUM(RPMTRANS_FLAG_TEST);
+ REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
+ REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
+ REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
+ REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
+ REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOCONTEXTS);
+ REGISTER_ENUM(RPMTRANS_FLAG_REPACKAGE);
+ REGISTER_ENUM(RPMTRANS_FLAG_REVERSE);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPRE);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPOST);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERPREIN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERIN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERUN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPREUN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOPOSTUN);
+ REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERPOSTUN);
+ 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(RPMPROB_FILTER_IGNOREOS);
+ REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
+ REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
+ REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
+ REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
+ REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
+ REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
+ REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
+ REGISTER_ENUM(RPMPROB_FILTER_DISKNODES);
+
+ REGISTER_ENUM(RPMCALLBACK_UNKNOWN);
+ REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
+ REGISTER_ENUM(RPMCALLBACK_INST_START);
+ REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
+ REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
+ REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
+ REGISTER_ENUM(RPMCALLBACK_TRANS_START);
+ REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
+ REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
+ REGISTER_ENUM(RPMCALLBACK_UNINST_START);
+ REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
+ REGISTER_ENUM(RPMCALLBACK_REPACKAGE_PROGRESS);
+ REGISTER_ENUM(RPMCALLBACK_REPACKAGE_START);
+ REGISTER_ENUM(RPMCALLBACK_REPACKAGE_STOP);
+ REGISTER_ENUM(RPMCALLBACK_UNPACK_ERROR);
+ REGISTER_ENUM(RPMCALLBACK_CPIO_ERROR);
+ REGISTER_ENUM(RPMCALLBACK_SCRIPT_ERROR);
+
+ REGISTER_ENUM(RPMPROB_BADARCH);
+ REGISTER_ENUM(RPMPROB_BADOS);
+ REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
+ REGISTER_ENUM(RPMPROB_BADRELOCATE);
+ REGISTER_ENUM(RPMPROB_REQUIRES);
+ REGISTER_ENUM(RPMPROB_CONFLICT);
+ REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
+ REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
+ REGISTER_ENUM(RPMPROB_OLDPACKAGE);
+ REGISTER_ENUM(RPMPROB_DISKSPACE);
+ REGISTER_ENUM(RPMPROB_DISKNODES);
+ REGISTER_ENUM(RPMPROB_OBSOLETES);
+
+ REGISTER_ENUM(VERIFY_DIGEST);
+ REGISTER_ENUM(VERIFY_SIGNATURE);
+
+ REGISTER_ENUM(RPMLOG_EMERG);
+ REGISTER_ENUM(RPMLOG_ALERT);
+ REGISTER_ENUM(RPMLOG_CRIT);
+ REGISTER_ENUM(RPMLOG_ERR);
+ REGISTER_ENUM(RPMLOG_WARNING);
+ REGISTER_ENUM(RPMLOG_NOTICE);
+ REGISTER_ENUM(RPMLOG_INFO);
+ REGISTER_ENUM(RPMLOG_DEBUG);
+
+ REGISTER_ENUM(RPMMIRE_DEFAULT);
+ REGISTER_ENUM(RPMMIRE_STRCMP);
+ REGISTER_ENUM(RPMMIRE_REGEX);
+ REGISTER_ENUM(RPMMIRE_GLOB);
+
+ REGISTER_ENUM(RPMVSF_DEFAULT);
+ REGISTER_ENUM(RPMVSF_NOHDRCHK);
+ REGISTER_ENUM(RPMVSF_NEEDPAYLOAD);
+ REGISTER_ENUM(RPMVSF_NOSHA1HEADER);
+ REGISTER_ENUM(RPMVSF_NOMD5HEADER);
+ REGISTER_ENUM(RPMVSF_NODSAHEADER);
+ REGISTER_ENUM(RPMVSF_NORSAHEADER);
+ REGISTER_ENUM(RPMVSF_NOSHA1);
+ REGISTER_ENUM(RPMVSF_NOMD5);
+ REGISTER_ENUM(RPMVSF_NODSA);
+ REGISTER_ENUM(RPMVSF_NORSA);
+ REGISTER_ENUM(_RPMVSF_NODIGESTS);
+ REGISTER_ENUM(_RPMVSF_NOSIGNATURES);
+ REGISTER_ENUM(_RPMVSF_NOHEADER);
+ REGISTER_ENUM(_RPMVSF_NOPAYLOAD);
+
+ REGISTER_ENUM(TR_ADDED);
+ REGISTER_ENUM(TR_REMOVED);
+
+ REGISTER_ENUM(RPMDBI_PACKAGES);
+ REGISTER_ENUM(RPMDBI_LABEL);
+ REGISTER_ENUM(RPMDBI_NAME);
+ REGISTER_ENUM(RPMDBI_BASENAMES);
+ REGISTER_ENUM(RPMDBI_GROUP);
+ REGISTER_ENUM(RPMDBI_REQUIRENAME);
+ REGISTER_ENUM(RPMDBI_PROVIDENAME);
+ REGISTER_ENUM(RPMDBI_CONFLICTNAME);
+ REGISTER_ENUM(RPMDBI_OBSOLETENAME);
+ REGISTER_ENUM(RPMDBI_TRIGGERNAME);
+ REGISTER_ENUM(RPMDBI_DIRNAMES);
+ REGISTER_ENUM(RPMDBI_INSTALLTID);
+ REGISTER_ENUM(RPMDBI_SIGMD5);
+ REGISTER_ENUM(RPMDBI_SHA1HEADER);
+
+ REGISTER_ENUM(HEADERCONV_EXPANDFILELIST);
+ REGISTER_ENUM(HEADERCONV_COMPRESSFILELIST);
+ REGISTER_ENUM(HEADERCONV_RETROFIT_V3);
+
+ return 1;
+}
+
diff --git a/python/rpmps-py.c b/python/rpmps-py.c
new file mode 100644
index 0000000..fa7e91e
--- /dev/null
+++ b/python/rpmps-py.c
@@ -0,0 +1,141 @@
+#include "rpmsystem-py.h"
+
+#include "rpmps-py.h"
+
+#include "debug.h"
+
+struct rpmProblemObject_s {
+ PyObject_HEAD
+ PyObject *md_dict;
+ rpmProblem prob;
+};
+
+static char rpmprob_doc[] =
+"";
+
+static PyObject *rpmprob_get_type(rpmProblemObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmProblemGetType(s->prob));
+}
+
+static PyObject *rpmprob_get_pkgnevr(rpmProblemObject *s, void *closure)
+{
+ return Py_BuildValue("s", rpmProblemGetPkgNEVR(s->prob));
+}
+
+static PyObject *rpmprob_get_altnevr(rpmProblemObject *s, void *closure)
+{
+ return Py_BuildValue("s", rpmProblemGetAltNEVR(s->prob));
+}
+
+static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure)
+{
+ fnpyKey key = rpmProblemGetKey(s->prob);
+ if (key) {
+ return Py_BuildValue("O", rpmProblemGetKey(s->prob));
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject *rpmprob_get_str(rpmProblemObject *s, void *closure)
+{
+ return Py_BuildValue("s", rpmProblemGetStr(s->prob));
+}
+
+static PyObject *rpmprob_get_num(rpmProblemObject *s, void *closure)
+{
+ return Py_BuildValue("L", rpmProblemGetDiskNeed(s->prob));
+}
+
+static PyGetSetDef rpmprob_getseters[] = {
+ { "type", (getter)rpmprob_get_type, NULL, NULL },
+ { "pkgNEVR", (getter)rpmprob_get_pkgnevr, NULL, NULL },
+ { "altNEVR", (getter)rpmprob_get_altnevr, NULL, NULL },
+ { "key", (getter)rpmprob_get_key, NULL, NULL },
+ { "_str", (getter)rpmprob_get_str, NULL, NULL },
+ { "_num", (getter)rpmprob_get_num, NULL, NULL },
+ { NULL }
+};
+
+static PyObject *rpmprob_str(rpmProblemObject *s)
+{
+ char *str = rpmProblemString(s->prob);
+ PyObject *res = Py_BuildValue("s", str);
+ free(str);
+ return res;
+}
+
+static void rpmprob_dealloc(rpmProblemObject *s)
+{
+ s->prob = rpmProblemFree(s->prob);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+PyTypeObject rpmProblem_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.prob", /* tp_name */
+ sizeof(rpmProblemObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)rpmprob_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)rpmprob_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmprob_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ rpmprob_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 */
+ (newfunc)0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject *rpmprob_Wrap(PyTypeObject *subtype, rpmProblem prob)
+{
+ rpmProblemObject * s = (rpmProblemObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->prob = rpmProblemLink(prob);
+ return (PyObject *) s;
+}
+
+PyObject *rpmps_AsList(rpmps ps)
+{
+ PyObject *problems = PyList_New(0);
+ rpmpsi psi = rpmpsInitIterator(ps);
+ rpmProblem prob;
+
+ while ((prob = rpmpsiNext(psi))) {
+ PyObject *pyprob = rpmprob_Wrap(&rpmProblem_Type, prob);
+ PyList_Append(problems, pyprob);
+ Py_DECREF(pyprob);
+ }
+ rpmpsFreeIterator(psi);
+ return problems;
+}
diff --git a/python/rpmps-py.h b/python/rpmps-py.h
new file mode 100644
index 0000000..4d7efc8
--- /dev/null
+++ b/python/rpmps-py.h
@@ -0,0 +1,16 @@
+#ifndef H_RPMPS_PY
+#define H_RPMPS_PY
+
+#include <rpm/rpmps.h>
+
+typedef struct rpmProblemObject_s rpmProblemObject;
+
+extern PyTypeObject rpmProblem_Type;
+
+#define rpmProblemObject_Check(v) ((v)->ob_type == &rpmProblem_Type)
+
+PyObject * rpmprob_Wrap(PyTypeObject *subtype, rpmProblem prob);
+
+PyObject *rpmps_AsList(rpmps ps);
+
+#endif
diff --git a/python/rpmsmodule.c b/python/rpmsmodule.c
new file mode 100644
index 0000000..e0b1b66
--- /dev/null
+++ b/python/rpmsmodule.c
@@ -0,0 +1,97 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmsign.h>
+
+#include "debug.h"
+
+static char rpms__doc__[] =
+"";
+
+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;
+
+ memset(&sig, 0, sizeof(sig));
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|si", kwlist,
+ &path, &passPhrase, &sig.keyid, &sig.hashalgo))
+ return NULL;
+
+ if (sig.keyid || sig.hashalgo)
+ sigp = &sig;
+
+ return PyBool_FromLong(rpmPkgSign(path, sigp, passPhrase) == 0);
+}
+
+static PyObject * delSign(PyObject * self, PyObject * args, PyObject *kwds)
+{
+ const char *path = NULL;
+ char * kwlist[] = { "path", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &path))
+ return NULL;
+
+ return PyBool_FromLong(rpmPkgDelSign(path) == 0);
+}
+
+/*
+ Do any common preliminary work before python 2 vs python 3 module creation:
+*/
+static int prepareInitModule(void)
+{
+ return 1;
+}
+
+static int initModule(PyObject *m)
+{
+ return 1;
+}
+
+static PyMethodDef modMethods[] = {
+ { "addSign", (PyCFunction) addSign, METH_VARARGS|METH_KEYWORDS, NULL },
+ { "delSign", (PyCFunction) delSign, METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL },
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_rpms", /* m_name */
+ rpms__doc__, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+};
+
+PyObject * PyInit__rpm(void); /* XXX eliminate gcc warning */
+PyObject * PyInit__rpm(void)
+{
+ PyObject *m;
+
+ if (!prepareInitModule())
+ return NULL;
+ m = PyModule_Create(&moduledef);
+ if (m == NULL || !initModule(m)) {
+ Py_XDECREF(m);
+ m = NULL;
+ }
+ return m;
+}
+#else
+void init_rpms(void); /* XXX eliminate gcc warning */
+void init_rpms(void)
+{
+ PyObject *m;
+
+ if (!prepareInitModule())
+ return;
+
+ m = Py_InitModule3("_rpms", modMethods, rpms__doc__);
+ if (m) initModule(m);
+}
+#endif
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
new file mode 100644
index 0000000..78d1fa8
--- /dev/null
+++ b/python/rpmsystem-py.h
@@ -0,0 +1,45 @@
+#ifndef H_SYSTEM_PYTHON
+#define H_SYSTEM_PYTHON
+
+#if defined(__APPLE__)
+#include <sys/types.h>
+#endif
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "../system.h"
+
+#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0205
+typedef ssize_t Py_ssize_t;
+typedef Py_ssize_t (*lenfunc)(PyObject *);
+#endif
+
+/* Compatibility macros for Python < 2.6 */
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(type, size) \
+ PyObject_HEAD_INIT(type) size,
+#endif
+
+#ifndef Py_TYPE
+#define Py_TYPE(o) ((o)->ob_type)
+#endif
+
+#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0206
+#define PyBytes_Check PyString_Check
+#define PyBytes_FromString PyString_FromString
+#define PyBytes_FromStringAndSize PyString_FromStringAndSize
+#define PyBytes_Size PyString_Size
+#define PyBytes_AsString PyString_AsString
+#endif
+
+/* For Python 3, use the PyLong type throughout in place of PyInt */
+#if PY_MAJOR_VERSION >= 3
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_AsLong
+#define PyInt_FromLong PyLong_FromLong
+#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
+#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+#endif
+
+#endif /* H_SYSTEM_PYTHON */
diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c
new file mode 100644
index 0000000..8232127
--- /dev/null
+++ b/python/rpmtd-py.c
@@ -0,0 +1,214 @@
+/** \ingroup py_c
+ * \file python/rpmtd-py.c
+ */
+
+#include "rpmsystem-py.h"
+#include <rpm/rpmtd.h>
+#include <rpm/header.h>
+#include "rpmtd-py.h"
+#include "header-py.h"
+
+/*
+ * Convert single tag data item to python object of suitable type
+ */
+static PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
+{
+ PyObject *res = NULL;
+
+ switch (tclass) {
+ case RPM_STRING_CLASS:
+ res = PyBytes_FromString(rpmtdGetString(td));
+ break;
+ case RPM_NUMERIC_CLASS:
+ res = PyLong_FromLongLong(rpmtdGetNumber(td));
+ break;
+ case RPM_BINARY_CLASS:
+ res = PyBytes_FromStringAndSize(td->data, td->count);
+ break;
+ default:
+ PyErr_SetString(PyExc_KeyError, "unknown data type");
+ break;
+ }
+ return res;
+}
+
+PyObject *rpmtd_AsPyobj(rpmtd td)
+{
+ PyObject *res = NULL;
+ int array = (rpmTagGetReturnType(td->tag) == RPM_ARRAY_RETURN_TYPE);
+ rpmTagClass tclass = rpmtdClass(td);
+
+ if (!array && rpmtdCount(td) < 1) {
+ Py_RETURN_NONE;
+ }
+
+ if (array) {
+ res = PyList_New(0);
+ while (rpmtdNext(td) >= 0) {
+ PyObject *item = rpmtd_ItemAsPyobj(td, tclass);
+ PyList_Append(res, item);
+ Py_DECREF(item);
+ }
+ } else {
+ res = rpmtd_ItemAsPyobj(td, tclass);
+ }
+ 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)
+ "rpm.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, "rpm.td type expected");
+ return 0;
+ }
+}
+#endif
diff --git a/python/rpmtd-py.h b/python/rpmtd-py.h
new file mode 100644
index 0000000..4c95e89
--- /dev/null
+++ b/python/rpmtd-py.h
@@ -0,0 +1,14 @@
+#ifndef H_RPMTD_PY
+#define H_RPMTD_PY
+
+typedef struct rpmtdObject_s rpmtdObject;
+
+extern PyTypeObject rpmtd_Type;
+
+#define rpmtdObject_Check(v) ((v)->ob_type == &rpmtd_Type)
+
+PyObject * rpmtd_AsPyobj(rpmtd td);
+
+int rpmtdFromPyObject(PyObject *obj, rpmtd *td);
+
+#endif
diff --git a/python/rpmte-py.c b/python/rpmte-py.c
new file mode 100644
index 0000000..e017264
--- /dev/null
+++ b/python/rpmte-py.c
@@ -0,0 +1,302 @@
+#include "rpmsystem-py.h"
+
+#include "header-py.h" /* XXX tagNumFromPyObject */
+#include "rpmds-py.h"
+#include "rpmfi-py.h"
+#include "rpmte-py.h"
+#include "rpmps-py.h"
+
+#include "debug.h"
+
+
+/** \ingroup python
+ * \name Class: Rpmte
+ * \class Rpmte
+ * \brief An python rpm.te object represents an element of a transaction set.
+ *
+ * Elements of a transaction set are accessible after being added. Each
+ * element carries descriptive information about the added element as well
+ * as a file info set and dependency sets for each of the 4 types of dependency.
+ *
+ * The rpmte class contains the following methods:
+ *
+ * - te.Type() Return transaction element type (TR_ADDED|TR_REMOVED).
+ * - te.N() Return package name.
+ * - te.E() Return package epoch.
+ * - te.V() Return package version.
+ * - te.R() Return package release.
+ * - te.A() Return package architecture.
+ * - te.O() Return package operating system.
+ * - te.NEVR() Return package name-version-release.
+ * - te.Color() Return package color bits.
+ * - te.PkgFileSize() Return no. of bytes in package file (approx).
+ * - te.Parent() Return the parent element index.
+ * - te.Problems() Return problems associated with this element.
+ * - te.AddedKey() Return the added package index (TR_ADDED).
+ * - te.DependsOnKey() Return the package index for the added package (TR_REMOVED).
+ * - te.DBOffset() Return the Packages database instance number (TR_REMOVED)
+ * - 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.
+ * @param tag 'Basenames'
+ */
+
+struct rpmteObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ rpmte te;
+};
+
+static PyObject *
+rpmte_TEType(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteType(s->te));
+}
+
+static PyObject *
+rpmte_N(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteN(s->te));
+}
+
+static PyObject *
+rpmte_E(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteE(s->te));
+}
+
+static PyObject *
+rpmte_V(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteV(s->te));
+}
+
+static PyObject *
+rpmte_R(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteR(s->te));
+}
+
+static PyObject *
+rpmte_A(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteA(s->te));
+}
+
+static PyObject *
+rpmte_O(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteO(s->te));
+}
+
+static PyObject *
+rpmte_NEVR(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteNEVR(s->te));
+}
+
+static PyObject *
+rpmte_NEVRA(rpmteObject * s)
+{
+ return Py_BuildValue("s", rpmteNEVRA(s->te));
+}
+
+static PyObject *
+rpmte_Color(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteColor(s->te));
+}
+
+static PyObject *
+rpmte_PkgFileSize(rpmteObject * s)
+{
+ return Py_BuildValue("L", rpmtePkgFileSize(s->te));
+}
+
+static PyObject *
+rpmte_Parent(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteParent(s->te));
+}
+
+static PyObject * rpmte_Failed(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteFailed(s->te));
+}
+
+static PyObject * rpmte_Problems(rpmteObject * s)
+{
+ rpmps ps = rpmteProblems(s->te);
+ PyObject *problems = rpmps_AsList(ps);
+ rpmpsFree(ps);
+ return problems;
+}
+
+/*
+static PyObject *
+rpmte_DependsOnKey(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteDependsOnKey(s->te));
+}
+*/
+
+static PyObject *
+rpmte_DBOffset(rpmteObject * s)
+{
+ return Py_BuildValue("i", rpmteDBOffset(s->te));
+}
+
+static PyObject *
+rpmte_Key(rpmteObject * s)
+{
+ PyObject * Key;
+
+ /* XXX how to insure this is a PyObject??? */
+ Key = (PyObject *) rpmteKey(s->te);
+ if (Key == NULL)
+ Key = Py_None;
+ Py_INCREF(Key);
+ return Key;
+}
+
+static PyObject *
+rpmte_DS(rpmteObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmds ds;
+ rpmTagVal tag;
+ char * kwlist[] = {"tag", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:DS", kwlist,
+ tagNumFromPyObject, &tag))
+ return NULL;
+
+ ds = rpmteDS(s->te, tag);
+ if (ds == NULL) {
+ Py_RETURN_NONE;
+ }
+ return rpmds_Wrap(&rpmds_Type, rpmdsLink(ds));
+}
+
+static PyObject *
+rpmte_FI(rpmteObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmfi fi;
+
+ fi = rpmteFI(s->te);
+ if (fi == NULL) {
+ Py_RETURN_NONE;
+ }
+ return rpmfi_Wrap(&rpmfi_Type, rpmfiLink(fi));
+}
+
+static struct PyMethodDef rpmte_methods[] = {
+ {"Type", (PyCFunction)rpmte_TEType, METH_NOARGS,
+"te.Type() -> Type\n\
+- Return element type (rpm.TR_ADDED | rpm.TR_REMOVED).\n" },
+ {"N", (PyCFunction)rpmte_N, METH_NOARGS,
+"te.N() -> N\n\
+- Return element name.\n" },
+ {"E", (PyCFunction)rpmte_E, METH_NOARGS,
+"te.E() -> E\n\
+- Return element epoch.\n" },
+ {"V", (PyCFunction)rpmte_V, METH_NOARGS,
+"te.V() -> V\n\
+- Return element version.\n" },
+ {"R", (PyCFunction)rpmte_R, METH_NOARGS,
+"te.R() -> R\n\
+- Return element release.\n" },
+ {"A", (PyCFunction)rpmte_A, METH_NOARGS,
+"te.A() -> A\n\
+- Return element arch.\n" },
+ {"O", (PyCFunction)rpmte_O, METH_NOARGS,
+"te.O() -> O\n\
+- Return element os.\n" },
+ {"NEVR", (PyCFunction)rpmte_NEVR, METH_NOARGS,
+"te.NEVR() -> NEVR\n\
+- 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" },
+ {"Color",(PyCFunction)rpmte_Color, METH_NOARGS,
+ NULL},
+ {"PkgFileSize",(PyCFunction)rpmte_PkgFileSize, METH_NOARGS,
+ NULL},
+ {"Parent", (PyCFunction)rpmte_Parent, METH_NOARGS,
+ NULL},
+ {"Problems",(PyCFunction)rpmte_Problems, METH_NOARGS,
+ NULL},
+/* {"DependsOnKey",(PyCFunction)rpmte_DependsOnKey, METH_NOARGS,
+ NULL}, */
+ {"DBOffset",(PyCFunction)rpmte_DBOffset, METH_NOARGS,
+ NULL},
+ {"Failed", (PyCFunction)rpmte_Failed, METH_NOARGS,
+ NULL},
+ {"Key", (PyCFunction)rpmte_Key, METH_NOARGS,
+ NULL},
+ {"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" },
+ {"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" },
+ {NULL, NULL} /* sentinel */
+};
+
+/* ---------- */
+
+static char rpmte_doc[] =
+"";
+
+PyTypeObject rpmte_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.te", /* tp_name */
+ sizeof(rpmteObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor)0, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)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 */
+ rpmte_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ rpmte_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 * rpmte_Wrap(PyTypeObject *subtype, rpmte te)
+{
+ rpmteObject *s = (rpmteObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->te = te;
+ return (PyObject *) s;
+}
diff --git a/python/rpmte-py.h b/python/rpmte-py.h
new file mode 100644
index 0000000..28bc0e3
--- /dev/null
+++ b/python/rpmte-py.h
@@ -0,0 +1,14 @@
+#ifndef H_RPMTE_PY
+#define H_RPMTE_PY
+
+#include <rpm/rpmte.h>
+
+typedef struct rpmteObject_s rpmteObject;
+
+extern PyTypeObject rpmte_Type;
+
+#define rpmteObject_Check(v) ((v)->ob_type == &rpmte_Type)
+
+PyObject * rpmte_Wrap(PyTypeObject *subtype, rpmte te);
+
+#endif
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
new file mode 100644
index 0000000..1e8a09a
--- /dev/null
+++ b/python/rpmts-py.c
@@ -0,0 +1,904 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmlib.h> /* rpmReadPackageFile, headerCheck */
+#include <rpm/rpmtag.h>
+#include <rpm/rpmpgp.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmbuild.h>
+
+#include "header-py.h"
+#include "rpmds-py.h" /* XXX for rpmdsNew */
+#include "rpmfd-py.h"
+#include "rpmkeyring-py.h"
+#include "rpmfi-py.h" /* XXX for rpmfiNew */
+#include "rpmmi-py.h"
+#include "rpmii-py.h"
+#include "rpmps-py.h"
+#include "rpmte-py.h"
+
+#include "rpmts-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \name Class: Rpmts
+ * \class Rpmts
+ * \brief A python rpm.ts object represents an RPM transaction set.
+ *
+ * The transaction set is the workhorse of RPM. It performs the
+ * installation and upgrade of packages. The rpm.ts object is
+ * instantiated by the TransactionSet function in the rpm module.
+ *
+ * The TransactionSet function takes two optional arguments. The first
+ * argument is the root path. The second is the verify signature disable flags,
+ * a set of the following bits:
+ *
+ * - rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers
+ * - rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible)
+ * - rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest
+ * - rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature
+ * - rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest
+ * - rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature
+ * - rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature
+ *
+ * For convenience, there are the following masks:
+ * - rpm._RPMVSF_NODIGESTS if set, don't check digest(s).
+ * - rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s).
+ *
+ * A rpm.ts object has the following methods:
+ *
+ * - addInstall(hdr,data,mode) Add an install element to a transaction set.
+ * @param hdr the header to be added
+ * @param data user data that will be passed to the transaction callback
+ * during transaction execution
+ * @param mode optional argument that specifies if this package should
+ * be installed ('i'), upgraded ('u').
+ *
+ * - addErase(name) Add an erase element to a transaction set.
+ * @param name the package name to be erased
+ *
+ * - check() Perform a dependency check on the transaction set. After
+ * headers have been added to a transaction set, a dependency
+ * check can be performed to make sure that all package
+ * dependencies are satisfied.
+ * @return None If there are no unresolved dependencies
+ * Otherwise a list of complex tuples is returned, one tuple per
+ * unresolved dependency, with
+ * The format of the dependency tuple is:
+ * ((packageName, packageVersion, packageRelease),
+ * (reqName, reqVersion),
+ * needsFlags,
+ * suggestedPackage,
+ * sense)
+ * packageName, packageVersion, packageRelease are the name,
+ * version, and release of the package that has the unresolved
+ * dependency or conflict.
+ * The reqName and reqVersion are the name and version of the
+ * requirement or conflict.
+ * The needsFlags is a bitfield that describes the versioned
+ * nature of a requirement or conflict. The constants
+ * rpm.RPMSENSE_LESS, rpm.RPMSENSE_GREATER, and
+ * rpm.RPMSENSE_EQUAL can be logical ANDed with the needsFlags
+ * to get versioned dependency information.
+ * suggestedPackage is a tuple if the dependency check was aware
+ * of a package that solves this dependency problem when the
+ * dependency check was run. Packages that are added to the
+ * transaction set as "available" are examined during the
+ * dependency check as possible dependency solvers. The tuple
+ * contains two values, (header, suggestedName). These are set to
+ * the header of the suggested package and its name, respectively.
+ * If there is no known package to solve the dependency problem,
+ * suggestedPackage is None.
+ * The constants rpm.RPMDEP_SENSE_CONFLICTS and
+ * rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a
+ * requirement or a conflict.
+ *
+ * - ts.order() Do a topological sort of added element relations.
+ * @return None
+ *
+ * - ts.setFlags(transFlags) Set transaction set flags.
+ * @param transFlags - bit(s) to controll 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_NOTRIGGERS - do not run trigger scripts
+ * - rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc
+ * - rpm.RPMTRANS_FLAG_ALLFILES - create all files, even if a
+ * file is marked %config(missingok) and an upgrade is
+ * being performed.
+ * - rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted
+ * packages.
+ * @return previous transFlags
+ *
+ * - ts.setProbFilter(ignoreSet) Set transaction set problem filter.
+ * @param problemSetFilter - control bit(s) to ignore classes of problems,
+ * a logical or of one or more of the following bit(s):
+ * - rpm.RPMPROB_FILTER_IGNOREOS -
+ * - rpm.RPMPROB_FILTER_IGNOREARCH -
+ * - rpm.RPMPROB_FILTER_REPLACEPKG -
+ * - rpm.RPMPROB_FILTER_FORCERELOCATE -
+ * - rpm.RPMPROB_FILTER_REPLACENEWFILES -
+ * - rpm.RPMPROB_FILTER_REPLACEOLDFILES -
+ * - rpm.RPMPROB_FILTER_OLDPACKAGE -
+ * - rpm.RPMPROB_FILTER_DISKSPACE -
+ * @return previous ignoreSet
+ *
+ * - ts.run(callback,data) Attempt to execute a transaction set.
+ * After the transaction set has been populated with install/upgrade or
+ * erase actions, the transaction set can be executed by invoking
+ * the ts.run() method.
+ */
+
+struct rpmtsObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ rpmfdObject *scriptFd;
+ PyObject *keyList;
+ rpmts ts;
+ rpmtsi tsi;
+};
+
+struct rpmtsCallbackType_s {
+ PyObject * cb;
+ PyObject * data;
+ rpmtsObject * tso;
+ PyThreadState *_save;
+};
+
+RPM_GNUC_NORETURN
+static void die(PyObject *cb)
+{
+ char *pyfn = NULL;
+ PyObject *r;
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+ if ((r = PyObject_Repr(cb)) != NULL) {
+ pyfn = PyBytes_AsString(r);
+ }
+ fprintf(stderr, _("error: python callback %s failed, aborting!\n"),
+ pyfn ? pyfn : "???");
+ rpmdbCheckTerminate(1);
+ exit(EXIT_FAILURE);
+}
+
+static PyObject *
+rpmts_AddInstall(rpmtsObject * s, PyObject * args)
+{
+ Header h = NULL;
+ PyObject * key;
+ int how = 0;
+ int rc;
+
+ if (!PyArg_ParseTuple(args, "O&Oi:AddInstall",
+ hdrFromPyObject, &h, &key, &how))
+ return NULL;
+
+ rc = rpmtsAddInstallElement(s->ts, h, key, how, NULL);
+ if (key && rc == 0) {
+ PyList_Append(s->keyList, key);
+ }
+ return PyBool_FromLong((rc == 0));
+}
+
+static PyObject *
+rpmts_AddErase(rpmtsObject * s, PyObject * args)
+{
+ Header h;
+
+ if (!PyArg_ParseTuple(args, "O&:AddErase", hdrFromPyObject, &h))
+ return NULL;
+
+ return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, -1) == 0);
+}
+
+static int
+rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
+{
+ struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
+ PyObject * args, * result;
+ int res = 1;
+
+ if (cbInfo->tso == NULL) return res;
+ if (cbInfo->cb == Py_None) return res;
+
+ PyEval_RestoreThread(cbInfo->_save);
+
+ args = Py_BuildValue("(Oissi)", cbInfo->tso,
+ rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
+ result = PyEval_CallObject(cbInfo->cb, args);
+ Py_DECREF(args);
+
+ if (!result) {
+ die(cbInfo->cb);
+ } else {
+ if (PyInt_Check(result))
+ res = PyInt_AsLong(result);
+ Py_DECREF(result);
+ }
+
+ cbInfo->_save = PyEval_SaveThread();
+
+ return res;
+}
+
+static PyObject *
+rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ struct rpmtsCallbackType_s cbInfo;
+ int rc;
+ char * kwlist[] = {"callback", NULL};
+
+ memset(&cbInfo, 0, sizeof(cbInfo));
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist,
+ &cbInfo.cb))
+ return NULL;
+
+ if (cbInfo.cb != NULL) {
+ if (!PyCallable_Check(cbInfo.cb)) {
+ PyErr_SetString(PyExc_TypeError, "expected a callable");
+ return NULL;
+ }
+ rc = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
+ }
+
+ cbInfo.tso = s;
+ cbInfo._save = PyEval_SaveThread();
+
+ rc = rpmtsCheck(s->ts);
+
+ PyEval_RestoreThread(cbInfo._save);
+
+ return PyBool_FromLong((rc == 0));
+}
+
+static PyObject *
+rpmts_Order(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsOrder(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_Clean(rpmtsObject * s)
+{
+ rpmtsClean(s->ts);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+rpmts_OpenDB(rpmtsObject * s)
+{
+ int dbmode;
+
+ dbmode = rpmtsGetDBMode(s->ts);
+ if (dbmode == -1)
+ dbmode = O_RDONLY;
+
+ return Py_BuildValue("i", rpmtsOpenDB(s->ts, dbmode));
+}
+
+static PyObject *
+rpmts_CloseDB(rpmtsObject * s)
+{
+ int rc;
+
+ rc = rpmtsCloseDB(s->ts);
+ rpmtsSetDBMode(s->ts, -1); /* XXX disable lazy opens */
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_InitDB(rpmtsObject * s)
+{
+ int rc;
+
+ rc = rpmtsInitDB(s->ts, O_RDONLY);
+ if (rc == 0)
+ rc = rpmtsCloseDB(s->ts);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_RebuildDB(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsRebuildDB(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_VerifyDB(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsVerifyDB(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_HdrFromFdno(rpmtsObject * s, PyObject *arg)
+{
+ PyObject *ho = NULL;
+ rpmfdObject *fdo = NULL;
+ Header h;
+ rpmRC rpmrc;
+
+ if (!PyArg_Parse(arg, "O&:HdrFromFdno", rpmfdFromPyObject, &fdo))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ rpmrc = rpmReadPackageFile(s->ts, rpmfdGetFd(fdo), "rpmts_HdrFromFdno", &h);
+ Py_END_ALLOW_THREADS;
+ Py_XDECREF(fdo);
+
+ 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;
+ }
+ return Py_BuildValue("(iN)", rpmrc, ho);
+}
+
+static PyObject *
+rpmts_HdrCheck(rpmtsObject * s, PyObject *obj)
+{
+ PyObject * blob;
+ char * msg = NULL;
+ const void * uh;
+ int uc;
+ rpmRC rpmrc;
+
+ if (!PyArg_Parse(obj, "S:HdrCheck", &blob))
+ return NULL;
+
+ uh = PyBytes_AsString(blob);
+ uc = PyBytes_Size(blob);
+
+ Py_BEGIN_ALLOW_THREADS;
+ rpmrc = headerCheck(s->ts, uh, uc, &msg);
+ Py_END_ALLOW_THREADS;
+
+ return Py_BuildValue("(is)", rpmrc, msg);
+}
+
+static PyObject *
+rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject * blob;
+ unsigned char * pkt;
+ unsigned int pktlen;
+ int rc;
+ char * kwlist[] = {"octets", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpPrtPkts", kwlist, &blob))
+ return NULL;
+
+ pkt = (unsigned char *)PyBytes_AsString(blob);
+ pktlen = PyBytes_Size(blob);
+
+ rc = pgpPrtPkts(pkt, pktlen, NULL, 1);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject * blob;
+ unsigned char * pkt;
+ unsigned int pktlen;
+ int rc;
+ char * kwlist[] = {"pubkey", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpImportPubkey",
+ kwlist, &blob))
+ return NULL;
+
+ pkt = (unsigned char *)PyBytes_AsString(blob);
+ pktlen = PyBytes_Size(blob);
+
+ rc = rpmtsImportPubkey(s->ts, pkt, pktlen);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *rpmts_setKeyring(rpmtsObject *s, PyObject *arg)
+{
+ rpmKeyring keyring = NULL;
+ if (arg == Py_None || rpmKeyringFromPyObject(arg, &keyring)) {
+ return PyBool_FromLong(rpmtsSetKeyring(s->ts, keyring) == 0);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "rpm.keyring or None expected");
+ return NULL;
+ }
+}
+
+static PyObject *rpmts_getKeyring(rpmtsObject *s, PyObject *args, PyObject *kwds)
+{
+ rpmKeyring keyring = NULL;
+ int autoload = 1;
+ char * kwlist[] = { "autoload", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:getKeyring",
+ kwlist, &autoload))
+ return NULL;
+
+ keyring = rpmtsGetKeyring(s->ts, autoload);
+ if (keyring) {
+ return rpmKeyring_Wrap(&rpmKeyring_Type, keyring);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static void *
+rpmtsCallback(const void * hd, const rpmCallbackType what,
+ const rpm_loff_t amount, const rpm_loff_t total,
+ const void * pkgKey, rpmCallbackData data)
+{
+ Header h = (Header) hd;
+ struct rpmtsCallbackType_s * cbInfo = data;
+ PyObject * pkgObj = (PyObject *) pkgKey;
+ PyObject * args, * result;
+ static FD_t fd;
+
+ if (cbInfo->cb == Py_None) return NULL;
+
+ /* Synthesize a python object for callback (if necessary). */
+ if (pkgObj == NULL) {
+ if (h) {
+ pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME));
+ } else {
+ pkgObj = Py_None;
+ Py_INCREF(pkgObj);
+ }
+ } else
+ Py_INCREF(pkgObj);
+
+ PyEval_RestoreThread(cbInfo->_save);
+
+ args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
+ result = PyEval_CallObject(cbInfo->cb, args);
+ Py_DECREF(args);
+ Py_DECREF(pkgObj);
+
+ if (!result) {
+ die(cbInfo->cb);
+ }
+
+ if (what == RPMCALLBACK_INST_OPEN_FILE) {
+ int fdno;
+
+ if (!PyArg_Parse(result, "i", &fdno)) {
+ die(cbInfo->cb);
+ }
+ Py_DECREF(result);
+ cbInfo->_save = PyEval_SaveThread();
+
+ fd = fdDup(fdno);
+ fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);
+
+ return fd;
+ } else
+ if (what == RPMCALLBACK_INST_CLOSE_FILE) {
+ Fclose (fd);
+ }
+
+ Py_DECREF(result);
+ cbInfo->_save = PyEval_SaveThread();
+
+ return NULL;
+}
+
+static PyObject *
+rpmts_Problems(rpmtsObject * s)
+{
+ rpmps ps = rpmtsProblems(s->ts);
+ PyObject *problems = rpmps_AsList(ps);
+ rpmpsFree(ps);
+ return problems;
+}
+
+static PyObject *
+rpmts_Run(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ int rc;
+ struct rpmtsCallbackType_s cbInfo;
+ rpmprobFilterFlags ignoreSet;
+ char * kwlist[] = {"callback", "data", "ignoreSet", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOi:Run", kwlist,
+ &cbInfo.cb, &cbInfo.data, &ignoreSet))
+ return NULL;
+
+ cbInfo.tso = s;
+ cbInfo._save = PyEval_SaveThread();
+
+ if (cbInfo.cb != NULL) {
+ if (!PyCallable_Check(cbInfo.cb)) {
+ PyErr_SetString(PyExc_TypeError, "expected a callable");
+ return NULL;
+ }
+ (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo);
+ }
+
+ rc = rpmtsRun(s->ts, NULL, ignoreSet);
+
+ if (cbInfo.cb)
+ (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL);
+
+ PyEval_RestoreThread(cbInfo._save);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_iternext(rpmtsObject * s)
+{
+ PyObject * result = NULL;
+ rpmte te;
+
+ /* Reset iterator on 1st entry. */
+ if (s->tsi == NULL) {
+ s->tsi = rpmtsiInit(s->ts);
+ if (s->tsi == NULL)
+ return NULL;
+ }
+
+ te = rpmtsiNext(s->tsi, 0);
+ if (te != NULL) {
+ result = rpmte_Wrap(&rpmte_Type, te);
+ } else {
+ s->tsi = rpmtsiFree(s->tsi);
+ }
+
+ return result;
+}
+
+static PyObject *
+rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject *Key = NULL;
+ PyObject *str = NULL;
+ PyObject *mio = NULL;
+ char *key = NULL;
+/* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */
+ int lkey = 0;
+ int len = 0;
+ rpmDbiTagVal tag = RPMDBI_PACKAGES;
+ char * kwlist[] = {"tagNumber", "key", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&O:Match", kwlist,
+ tagNumFromPyObject, &tag, &Key))
+ return NULL;
+
+ if (Key) {
+ if (PyInt_Check(Key)) {
+ lkey = PyInt_AsLong(Key);
+ key = (char *)&lkey;
+ len = sizeof(lkey);
+ } else if (utf8FromPyObject(Key, &str)) {
+ key = PyBytes_AsString(str);
+ len = PyBytes_Size(str);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "unknown key type");
+ return NULL;
+ }
+ /* One of the conversions above failed, exception is set already */
+ if (PyErr_Occurred()) goto exit;
+ }
+
+ /* XXX If not already opened, open the database O_RDONLY now. */
+ /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */
+ if (rpmtsGetRdb(s->ts) == NULL) {
+ int rc = rpmtsOpenDB(s->ts, O_RDONLY);
+ if (rc || rpmtsGetRdb(s->ts) == NULL) {
+ PyErr_SetString(pyrpmError, "rpmdb open failed");
+ goto exit;
+ }
+ }
+
+ mio = rpmmi_Wrap(&rpmmi_Type, rpmtsInitIterator(s->ts, tag, key, len), (PyObject*)s);
+
+exit:
+ Py_XDECREF(str);
+ return mio;
+}
+static PyObject *
+rpmts_index(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmDbiTagVal tag;
+ PyObject *mio = NULL;
+ char * kwlist[] = {"tag", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:Keys", kwlist,
+ tagNumFromPyObject, &tag))
+ return NULL;
+
+ /* XXX If not already opened, open the database O_RDONLY now. */
+ if (rpmtsGetRdb(s->ts) == NULL) {
+ int rc = rpmtsOpenDB(s->ts, O_RDONLY);
+ if (rc || rpmtsGetRdb(s->ts) == NULL) {
+ PyErr_SetString(pyrpmError, "rpmdb open failed");
+ goto exit;
+ }
+ }
+
+ rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(s->ts), tag);
+ if (ii == NULL) {
+ PyErr_SetString(PyExc_KeyError, "No index for this tag");
+ return NULL;
+ }
+ mio = rpmii_Wrap(&rpmii_Type, ii, (PyObject*)s);
+
+exit:
+ return mio;
+}
+
+static struct PyMethodDef rpmts_methods[] = {
+ {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS,
+ NULL },
+ {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"order", (PyCFunction) rpmts_Order, METH_NOARGS,
+ NULL },
+ {"problems", (PyCFunction) rpmts_Problems, METH_NOARGS,
+"ts.problems() -> ps\n\
+- Return current problem set.\n" },
+ {"run", (PyCFunction) rpmts_Run, METH_VARARGS|METH_KEYWORDS,
+"ts.run(callback, data) -> (problems)\n\
+- 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 },
+ {"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" },
+ {"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" },
+ {"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS,
+"ts.initDB() -> None\n\
+- Initialize the default transaction rpmdb.\n\
+ Note: ts.initDB() is seldom needed anymore.\n" },
+ {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS,
+"ts.rebuildDB() -> None\n\
+- Rebuild the default transaction rpmdb.\n" },
+ {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS,
+"ts.verifyDB() -> None\n\
+- Verify the default transaction rpmdb.\n" },
+ {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_O,
+"ts.hdrFromFdno(fdno) -> hdr\n\
+- Read a package header from a file descriptor.\n" },
+ {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_O,
+ NULL },
+ {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"getKeyring", (PyCFunction) rpmts_getKeyring, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"setKeyring", (PyCFunction) rpmts_setKeyring, METH_O,
+ NULL },
+ {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS,
+"ts.dbMatch([TagN, [key]]) -> mi\n\
+- Create a match iterator for the default transaction rpmdb.\n" },
+ {"dbIndex", (PyCFunction) rpmts_index, METH_VARARGS|METH_KEYWORDS,
+"ts.dbIndex(TagN) -> ii\n\
+- Create a key iterator for the default transaction rpmdb.\n" },
+ {NULL, NULL} /* sentinel */
+};
+
+static void rpmts_dealloc(rpmtsObject * s)
+{
+
+ s->ts = rpmtsFree(s->ts);
+ Py_XDECREF(s->scriptFd);
+ Py_XDECREF(s->keyList);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+{
+ rpmtsObject * s = (rpmtsObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->ts = rpmtsCreate();
+ s->scriptFd = NULL;
+ s->tsi = NULL;
+ s->keyList = PyList_New(0);
+ return (PyObject *) s;
+}
+
+static int rpmts_init(rpmtsObject *s, PyObject *args, PyObject *kwds)
+{
+ char * rootDir = "/";
+ rpmVSFlags vsflags = rpmExpandNumeric("%{?__vsflags}");
+ char * kwlist[] = {"rootdir", "vsflags", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_new", kwlist,
+ &rootDir, &vsflags))
+ return -1;
+
+ (void) rpmtsSetRootDir(s->ts, rootDir);
+ /* XXX: make this use common code with rpmts_SetVSFlags() to check the
+ * python objects */
+ (void) rpmtsSetVSFlags(s->ts, vsflags);
+
+ return 0;
+}
+
+static PyObject *rpmts_get_tid(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsGetTid(s->ts));
+}
+
+static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("s", rpmtsRootDir(s->ts));
+}
+
+static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmfdObject *fdo = NULL;
+ int rc = 0;
+ if (PyArg_Parse(value, "O&", rpmfdFromPyObject, &fdo)) {
+ Py_XDECREF(s->scriptFd);
+ s->scriptFd = fdo;
+ rpmtsSetScriptFd(s->ts, rpmfdGetFd(s->scriptFd));
+ } else if (value == Py_None) {
+ Py_XDECREF(s->scriptFd);
+ s->scriptFd = NULL;
+ rpmtsSetScriptFd(s->ts, NULL);
+ } else {
+ rc = -1;
+ }
+ return rc;
+}
+
+static PyObject *rpmts_get_color(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsColor(s->ts));
+}
+
+static PyObject *rpmts_get_prefcolor(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsPrefColor(s->ts));
+}
+
+static int rpmts_set_color(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpm_color_t color;
+ if (!PyArg_Parse(value, "i", &color)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetColor(s->ts, color);
+ return 0;
+}
+
+static int rpmts_set_prefcolor(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpm_color_t color;
+ if (!PyArg_Parse(value, "i", &color)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetPrefColor(s->ts, color);
+ return 0;
+}
+
+static int rpmts_set_flags(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmtransFlags flags;
+ if (!PyArg_Parse(value, "i", &flags)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetFlags(s->ts, flags);
+ return 0;
+}
+
+static int rpmts_set_vsflags(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmVSFlags flags;
+ if (!PyArg_Parse(value, "i", &flags)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetVSFlags(s->ts, flags);
+ return 0;
+}
+
+static PyObject *rpmts_get_flags(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsFlags(s->ts));
+}
+
+static PyObject *rpmts_get_vsflags(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsVSFlags(s->ts));
+}
+
+static char rpmts_doc[] =
+"";
+
+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 },
+ {"_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},
+ {"_vsflags", (getter)rpmts_get_vsflags, (setter)rpmts_set_vsflags, NULL},
+ { NULL }
+};
+
+PyTypeObject rpmts_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.ts", /* tp_name */
+ sizeof(rpmtsObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmts_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)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 */
+ rpmts_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmts_iternext, /* tp_iternext */
+ rpmts_methods, /* tp_methods */
+ 0, /* tp_members */
+ rpmts_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) rpmts_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc) rpmts_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
diff --git a/python/rpmts-py.h b/python/rpmts-py.h
new file mode 100644
index 0000000..e4fabfe
--- /dev/null
+++ b/python/rpmts-py.h
@@ -0,0 +1,18 @@
+#ifndef H_RPMTS_PY
+#define H_RPMTS_PY
+
+#include <rpm/rpmts.h>
+
+typedef struct rpmtsObject_s rpmtsObject;
+
+extern PyTypeObject rpmts_Type;
+
+#define rpmtsObject_Check(v) ((v)->ob_type == &rpmts_Type)
+
+/* XXX These names/constants have been removed from the rpmlib API. */
+enum {
+ RPMDEP_SENSE_REQUIRES, /*!< requirement not satisfied. */
+ RPMDEP_SENSE_CONFLICTS /*!< conflict was found. */
+};
+
+#endif
diff --git a/python/spec-py.c b/python/spec-py.c
new file mode 100644
index 0000000..a829539
--- /dev/null
+++ b/python/spec-py.c
@@ -0,0 +1,304 @@
+#include "rpmsystem-py.h"
+
+#include "header-py.h"
+#include "spec-py.h"
+
+/** \ingroup python
+ * \name Class: Rpmspec
+ * \class Rpmspec
+ * \brief A python rpm.spec object represents an RPM spec file set.
+ *
+ * The spec file is at the heart of RPM's packaging building process. Similar
+ * in concept to a makefile, it contains information required by RPM to build
+ * the package, as well as instructions telling RPM how to build it. The spec
+ * file also dictates exactly what files are a part of the package, and where
+ * they should be installed.
+ *
+ * The rpm.spec object represents a parsed specfile to aid extraction of data.
+ *
+ * For example
+ * \code
+ * import rpm
+ * rpm.addMacro("_topdir","/path/to/topdir")
+ * s=rpm.spec("foo.spec")
+ * print s.prep()
+ * \endcode
+ *
+ * Macros set using add macro will be used allowing testing of conditional builds
+ *
+ */
+
+/* Header objects are in another module, some hoop jumping required... */
+static PyObject *makeHeader(Header h)
+{
+ PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
+ if (rpmmod == NULL) return NULL;
+
+ PyObject *ptr = PyCObject_FromVoidPtr(h, NULL);
+ PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
+ Py_XDECREF(ptr);
+ Py_XDECREF(rpmmod);
+ return hdr;
+}
+
+struct specPkgObject_s {
+ PyObject_HEAD
+ /*type specific fields */
+ rpmSpecPkg pkg;
+};
+
+static char specPkg_doc[] =
+"";
+
+static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
+{
+ return makeHeader(rpmSpecPkgHeader(s->pkg));
+}
+
+static PyGetSetDef specpkg_getseters[] = {
+ { "header", (getter) specpkg_get_header, NULL, NULL },
+ { NULL } /* sentinel */
+};
+
+PyTypeObject specPkg_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.specpkg", /* tp_name */
+ sizeof(specPkgObject), /* tp_size */
+ 0, /* tp_itemsize */
+ 0, /* 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 */
+ specPkg_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ specpkg_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 */
+};
+
+struct specObject_s {
+ PyObject_HEAD
+ /*type specific fields */
+ rpmSpec spec;
+};
+
+static void
+spec_dealloc(specObject * s)
+{
+ if (s->spec) {
+ s->spec=rpmSpecFree(s->spec);
+ }
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject * getSection(rpmSpec spec, int section)
+{
+ const char *sect = rpmSpecGetSection(spec, section);
+ if (sect) {
+ return Py_BuildValue("s", sect);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+spec_get_prep(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_PREP);
+}
+
+static PyObject *
+spec_get_build(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_BUILD);
+}
+
+static PyObject * spec_get_install(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_INSTALL);
+}
+
+static PyObject * spec_get_clean(specObject * s, void *closure)
+{
+ return getSection(s->spec, RPMBUILD_CLEAN);
+}
+
+static PyObject * spec_get_sources(specObject *s, void *closure)
+{
+ PyObject *sourceList = PyList_New(0);
+ rpmSpecSrc source;
+
+ rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
+ while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
+ PyObject *srcUrl = Py_BuildValue("(sii)",
+ rpmSpecSrcFilename(source, 1),
+ rpmSpecSrcNum(source),
+ rpmSpecSrcFlags(source));
+ PyList_Append(sourceList, srcUrl);
+ Py_DECREF(srcUrl);
+ }
+ rpmSpecSrcIterFree(iter);
+
+ return sourceList;
+
+}
+
+static PyObject * spec_get_packages(specObject *s, void *closure)
+{
+ rpmSpecPkg pkg;
+ PyObject *pkgList = PyList_New(0);
+ rpmSpecPkgIter iter = rpmSpecPkgIterInit(s->spec);
+
+ while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
+ PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
+ PyList_Append(pkgList, po);
+ Py_DECREF(po);
+ }
+ rpmSpecPkgIterFree(iter);
+ return pkgList;
+}
+
+static PyObject * spec_get_source_header(specObject *s, void *closure)
+{
+ return makeHeader(rpmSpecSourceHeader(s->spec));
+}
+
+static char spec_doc[] = "RPM Spec file object";
+
+static PyGetSetDef spec_getseters[] = {
+ {"sources", (getter) spec_get_sources, NULL, NULL },
+ {"prep", (getter) spec_get_prep, NULL, NULL },
+ {"build", (getter) spec_get_build, NULL, NULL },
+ {"install", (getter) spec_get_install, NULL, NULL },
+ {"clean", (getter) spec_get_clean, NULL, NULL },
+ {"packages", (getter) spec_get_packages, NULL, NULL },
+ {"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
+ {NULL} /* Sentinel */
+};
+
+static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
+{
+ char * kwlist[] = {"specfile", "flags", NULL};
+ const char * specfile;
+ rpmSpec spec = NULL;
+ /* XXX This is a dumb default but anything else breaks compatibility... */
+ rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
+ &specfile, &flags))
+ return NULL;
+
+ spec = rpmSpecParse(specfile, flags, NULL);
+ if (spec == NULL) {
+ PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
+ return NULL;
+ }
+
+ return spec_Wrap(subtype, spec);
+}
+
+static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
+{
+ char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
+ struct rpmBuildArguments_s ba = { 0 };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
+ kwlist, &ba.buildAmount, &ba.pkgFlags))
+ return NULL;
+
+ return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
+}
+
+static struct PyMethodDef spec_methods[] = {
+ { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL, NULL }
+};
+
+PyTypeObject spec_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.spec", /*tp_name*/
+ sizeof(specObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) spec_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*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ spec_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ spec_methods, /* tp_methods */
+ 0, /* tp_members */
+ spec_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 */
+ spec_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject *
+spec_Wrap(PyTypeObject *subtype, rpmSpec spec)
+{
+ specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->spec = spec;
+ return (PyObject *) s;
+}
+
+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg)
+{
+ specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->pkg = pkg;
+ return (PyObject *) s;
+}
+
diff --git a/python/spec-py.h b/python/spec-py.h
new file mode 100644
index 0000000..558fbf2
--- /dev/null
+++ b/python/spec-py.h
@@ -0,0 +1,18 @@
+#ifndef RPMPYTHON_SPEC
+#define RPMPYTHON_SPEC
+
+#include <rpm/rpmbuild.h>
+
+typedef struct specPkgObject_s specPkgObject;
+typedef struct specObject_s specObject;
+
+extern PyTypeObject spec_Type;
+extern PyTypeObject specPkg_Type;
+
+#define specObject_Check(v) ((v)->ob_type == &spec_Type)
+#define specPkgObject_Check(v) ((v)->ob_type == &specPkg_Type)
+
+PyObject * spec_Wrap(PyTypeObject *subtype, rpmSpec spec);
+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg);
+
+#endif /* RPMPYTHON_SPEC */