From a4e69e11e544844034c3fbdc6789d5573f802117 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 25 Jun 2009 18:31:00 +0200 Subject: python: Fix some build warnings. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 2afd0708..85f4c889 100755 --- a/setup.py +++ b/setup.py @@ -12,12 +12,12 @@ from DistUtilsExtra.command import build_extra, build_i18n # The apt_pkg module files = map(lambda source: "python/"+source, - parse_makefile("python/makefile")["APT_PKG_SRC"].split()) + sorted(parse_makefile("python/makefile")["APT_PKG_SRC"].split())) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module files = map(lambda source: "python/"+source, - parse_makefile("python/makefile")["APT_INST_SRC"].split()) + sorted(parse_makefile("python/makefile")["APT_INST_SRC"].split())) apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -- cgit v1.2.3 From 7581c5fb8a8d8e1e0a79c343cbd23725475f846c Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 17:02:34 +0200 Subject: Simplify the whole building, build all Python versions with setup.py --- debian/changelog | 1 + debian/control | 4 +-- debian/python-apt.doc-base | 3 -- debian/python-apt.docs | 3 +- debian/rules | 35 +++------------------ po/python-apt.pot | 2 +- python/makefile | 27 ---------------- setup.py | 73 ++++++++++++++++++++----------------------- setup3.py | 77 ---------------------------------------------- 9 files changed, 43 insertions(+), 182 deletions(-) delete mode 100644 python/makefile mode change 100755 => 100644 setup.py delete mode 100644 setup3.py (limited to 'setup.py') diff --git a/debian/changelog b/debian/changelog index 70157470..5e3ec667 100644 --- a/debian/changelog +++ b/debian/changelog @@ -38,6 +38,7 @@ python-apt (0.7.92) UNRELEASED; urgency=low * Upgrade to debhelper 7 and remove debian/tmp in python-apt.install, to work around a bug in debhelper. * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 + * Simplify the whole building, build all Python versions with setup.py [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/debian/control b/debian/control index 9e0fe3ea..36a4d8d8 100644 --- a/debian/control +++ b/debian/control @@ -8,13 +8,13 @@ XS-Python-Version: >= 2.5 Build-Depends: apt-utils, cdbs, debhelper (>= 7), - libapt-pkg-dev (>= 0.7.22~), + libapt-pkg-dev (>= 0.7.12~), python-all-dbg (>= 2.5.4-3), python-all-dev (>= 2.5.4-3), python3.1-dev, python3.1-dbg, python-central (>= 0.5), - python-distutils-extra (>= 1.9.0), + python-distutils-extra (>= 2.0), python-gtk2, python-sphinx (>= 0.5), python-vte diff --git a/debian/python-apt.doc-base b/debian/python-apt.doc-base index d25926b7..e9b2040c 100644 --- a/debian/python-apt.doc-base +++ b/debian/python-apt.doc-base @@ -6,6 +6,3 @@ Section: Programming/Python Format: HTML Index: /usr/share/doc/python-apt/html/index.html Files: /usr/share/doc/python-apt/html/* - -Format: Text -Files: /usr/share/doc/python-apt/text/* diff --git a/debian/python-apt.docs b/debian/python-apt.docs index 6ba083f5..29219341 100644 --- a/debian/python-apt.docs +++ b/debian/python-apt.docs @@ -1,5 +1,4 @@ README apt/README.apt data/templates/README.templates -build/doc/html/ -build/doc/text/ +build/sphinx/html/ diff --git a/debian/rules b/debian/rules index f9b08384..967da911 100755 --- a/debian/rules +++ b/debian/rules @@ -11,56 +11,29 @@ DEB_PYTHON_PACKAGES_EXCLUDE=python-apt-dbg include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/python-distutils.mk -PY3K_VERSIONS := $(shell find /usr/bin/python3.? | sed s/.*python//) -2TO3_VERSION := $(lastword $(PY3K_VERSIONS)) +# Add python3 versions to the list of python versions +cdbs_python_build_versions += $(shell find /usr/bin/python3.? | sed s/.*python//) + -PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv DEB_PYTHON_INSTALL_ARGS_ALL=--no-compile --install-layout=deb -DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) # Define COMPAT_0_7 to get all the deprecated interfaces. export CFLAGS+=-DCOMPAT_0_7 -Wno-write-strings export DEBVER -build/python-apt:: - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i setup3.py build; \ - done - -install/python-apt:: - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i ./setup3.py install --root $(CURDIR)/debian/python-apt \ - --install-layout=deb --no-compile; \ - done - -ifneq ($(PY3K_VERSIONS),) - find $(CURDIR)/debian/python-apt/usr/lib/python3*/dist-packages/ -name '*.py' \ - | xargs 2to3-$(2TO3_VERSION)| patch -p0 -endif - build/python-apt-dbg:: set -e; \ for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py build; \ done - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i-dbg setup3.py build; \ - done - install/python-apt-dbg:: for i in $(cdbs_python_build_versions); do \ python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg \ - --no-compile; \ + $(DEB_PYTHON_INSTALL_ARGS_ALL); \ done - - set -e; for i in $(PY3K_VERSIONS); do \ - python$$i-dbg ./setup3.py install --root $(CURDIR)/debian/python-apt-dbg \ - --install-layout=deb --no-compile; \ - done - find debian/python-apt-dbg \ ! -type d ! -name '*_d.so' | xargs rm -f find debian/python-apt-dbg -depth -empty -exec rmdir {} \; diff --git a/po/python-apt.pot b/po/python-apt.pot index 3f4fbb6b..3becb5e1 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-07-15 15:17+0200\n" +"POT-Creation-Date: 2009-07-15 16:51+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/python/makefile b/python/makefile deleted file mode 100644 index fff3a2e8..00000000 --- a/python/makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -*- make -*- -BASE=.. -SUBDIR=python - -# Bring in the default rules -include ../buildlib/defaults.mak - -# The apt_pkg module -MODULE=apt_pkg -SLIBS = -lapt-pkg -LIB_MAKES = apt-pkg/makefile -APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ - cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ - depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc hashstring.cc indexrecords.cc \ - policy.cc hashes.cc -SOURCE := $(APT_PKG_SRC) -include $(PYTHON_H) progress.h - -# The apt_int module.. -MODULE=apt_inst -SLIBS = -lapt-inst -lapt-pkg -LIB_MAKES = apt-inst/makefile -APT_INST_SRC = apt_instmodule.cc tar.cc generic.cc -SOURCE := $(APT_INST_SRC) -include $(PYTHON_H) - diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 85f4c889..77853a4e --- a/setup.py +++ b/setup.py @@ -1,50 +1,59 @@ -#! /usr/bin/env python +#!/usr/bin/python +# Builds on python2.X and python3 # $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $ import glob import os -import shutil import sys from distutils.core import setup, Extension -from distutils.sysconfig import parse_makefile -from DistUtilsExtra.command import build_extra, build_i18n +cmdclass = {} +try: + from DistUtilsExtra.command import build_extra, build_i18n + from DistUtilsExtra.auto import clean_build_tree + cmdclass['build'] = build_extra.build_extra + cmdclass['build_i18n'] = build_i18n.build_i18n + cmdclass['clean'] = clean_build_tree + build_extra.build_extra.sub_commands.append(("build_sphinx", + lambda x: 'build_sphinx' in cmdclass)) +except ImportError: + print('W: [python%s] DistUtilsExtra import error.' % sys.version[:3]) -# The apt_pkg module -files = map(lambda source: "python/"+source, - sorted(parse_makefile("python/makefile")["APT_PKG_SRC"].split())) +try: + from sphinx.setup_command import BuildDoc + cmdclass['build_sphinx'] = BuildDoc +except ImportError: + print('W: [python%s] Sphinx import error.' % sys.version[:3]) + +if sys.version_info[0] == 3: + from distutils.command.build_py import build_py_2to3 + cmdclass['build_py'] = build_py_2to3 + +# The apt_pkg module. +files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', + 'configuration.c', 'depcache.cc', 'generic.cc', 'hashes.cc', + 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', + 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', + 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc'] +files = ['python/' + fname for fname in files] apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -files = map(lambda source: "python/"+source, - sorted(parse_makefile("python/makefile")["APT_INST_SRC"].split())) +files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc"] apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -templates = [] - -# build doc if len(sys.argv) > 1 and sys.argv[1] == "build": if not os.path.exists("build/data/templates/"): os.makedirs("build/data/templates") for template in glob.glob('data/templates/*.info.in'): source = open(template, "r") - build = open(os.path.join("build", template[:-3]), "w") - lines = source.readlines() - for line in lines: + build = open("build/" + template[:-3], "w") + for line in source: build.write(line.lstrip("_")) source.close() build.close() - -if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv: - for dirname in "build/doc", "doc/build", "build/data", "build/mo": - if os.path.exists(dirname): - print "Removing", dirname - shutil.rmtree(dirname) - else: - print "Not removing", dirname, "because it does not exist" - setup(name="python-apt", description="Python bindings for APT", version=os.environ.get('DEBVER'), @@ -56,20 +65,6 @@ setup(name="python-apt", glob.glob('build/data/templates/*.info')), ('share/python-apt/templates', glob.glob('data/templates/*.mirrors'))], - cmdclass = {"build": build_extra.build_extra, - "build_i18n": build_i18n.build_i18n}, + cmdclass = cmdclass, license = 'GNU GPL', platforms = 'posix') - -if len(sys.argv) > 1 and sys.argv[1] == "build": - import sphinx - try: - import pygtk - except ImportError: - print >> sys.stderr, ('W: Not building documentation because python-' - 'gtk2 is not available at the moment.') - sys.exit(0) - sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/html"]) - sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/text"]) diff --git a/setup3.py b/setup3.py deleted file mode 100644 index a3cbdc8e..00000000 --- a/setup3.py +++ /dev/null @@ -1,77 +0,0 @@ -#! /usr/bin/env python3 -# $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $ -import glob -import os -import shutil -import sys - -from distutils.core import setup, Extension -from distutils.sysconfig import parse_makefile -#from DistUtilsExtra.command import build_extra, build_i18n - - -# The apt_pkg module -files = ["python/"+source for source in parse_makefile("python/makefile")["APT_PKG_SRC"].split()] -apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) - -# The apt_inst module -files = ["python/"+source for source in parse_makefile("python/makefile")["APT_INST_SRC"].split()] -apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) - -# Replace the leading _ that is used in the templates for translation -templates = [] - -# build doc -if len(sys.argv) > 1 and sys.argv[1] == "build": - if not os.path.exists("build/data/templates/"): - os.makedirs("build/data/templates") - for template in glob.glob('data/templates/*.info.in'): - source = open(template, "r") - build = open(os.path.join("build", template[:-3]), "w") - lines = source.readlines() - for line in lines: - build.write(line.lstrip("_")) - source.close() - build.close() - - -if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv: - for dirname in "build/doc", "doc/build", "build/data", "build/mo": - if os.path.exists(dirname): - print("Removing", dirname) - shutil.rmtree(dirname) - else: - print("Not removing", dirname, "because it does not exist") - -setup(name="python-apt", - description="Python bindings for APT", - version=os.environ.get('DEBVER'), - author="APT Development Team", - author_email="deity@lists.debian.org", - ext_modules=[apt_pkg, apt_inst], - packages=['apt', 'apt.progress', 'aptsources'], - data_files = [('share/python-apt/templates', - glob.glob('build/data/templates/*.info')), - ('share/python-apt/templates', - glob.glob('data/templates/*.mirrors'))], -# cmdclass = {"build": build_extra.build_extra, -# "build_i18n": build_i18n.build_i18n}, - license = 'GNU GPL', - platforms = 'posix') - -if len(sys.argv) > 1 and sys.argv[1] == "build": - try: - import sphinx - except ImportError: - print(('W: Sphinx not available - Not building' - 'documentation'), file=sys.stderr) - try: - import pygtk - except ImportError: - print(('W: Not building documentation because python-' - 'gtk2 is not available at the moment.'), file=sys.stderr) - sys.exit(0) - sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/html"]) - sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees", - os.path.abspath("doc/source"), "build/doc/text"]) -- cgit v1.2.3 From 2a08f9a8fec67e535d91d00fea7be2c1f2090fbd Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 17:12:04 +0200 Subject: setup.py: Add missing 'c' to configuration.cc --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 77853a4e..af373632 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ if sys.version_info[0] == 3: # The apt_pkg module. files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', - 'configuration.c', 'depcache.cc', 'generic.cc', 'hashes.cc', + 'configuration.cc', 'depcache.cc', 'generic.cc', 'hashes.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc'] -- cgit v1.2.3 From aaf5907863bed9a044fa0e3e2eacd1ca2de53c59 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 15 Jul 2009 21:36:58 +0200 Subject: Introduce new progress (base) classes in apt_pkg: - apt_pkg.AcquireProgress - apt_pkg.OpProgress --- debian/changelog | 3 + python/acquireprogress.cc | 198 ++++++++++++++++++++++++++++++++++++++++++++++ python/apt_pkgmodule.cc | 2 + python/apt_pkgmodule.h | 2 + python/opprogress.cc | 173 ++++++++++++++++++++++++++++++++++++++++ python/progress.cc | 14 +++- setup.py | 5 +- 7 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 python/acquireprogress.cc create mode 100644 python/opprogress.cc (limited to 'setup.py') diff --git a/debian/changelog b/debian/changelog index 5e3ec667..b2936ba1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -39,6 +39,9 @@ python-apt (0.7.92) UNRELEASED; urgency=low work around a bug in debhelper. * Build-Depend on python-all-dev (>= 2.5.4-3), so we build for Python 2.6 * Simplify the whole building, build all Python versions with setup.py + * Introduce new progress (base) classes in apt_pkg: + - apt_pkg.AcquireProgress + - apt_pkg.OpProgress [ Sebastian Heinlein ] * apt/progress.py: Extract the package name from the status message diff --git a/python/acquireprogress.cc b/python/acquireprogress.cc new file mode 100644 index 00000000..ac3b8fd9 --- /dev/null +++ b/python/acquireprogress.cc @@ -0,0 +1,198 @@ +/* acquireprogress.cc - Base class for FetchProgress classes. + * + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "generic.h" +#include +#include + +typedef struct { + PyObject_HEAD + double last_bytes; + double current_cps; + double current_bytes; + double total_bytes; + double fetched_bytes; + unsigned long elapsed_time; + unsigned long total_items; + unsigned long current_items; +} PyAcquireProgressObject; + + +// DUMMY IMPLEMENTATIONS. +static char *acquireprogress_media_change_doc = + "media_change(media: str, drive: str) -> bool\n\n" + "Invoked when the user should be prompted to change the inserted\n" + "removable media.\n\n" + "This method should not return until the user has confirmed to the user\n" + "interface that the media change is complete.\n\n" + ":param:media The name of the media type that should be changed.\n" + ":param:drive The identifying name of the drive whose media should be\n" + " changed.\n\n" + "Return True if the user confirms the media change, False if it is\n" + "cancelled."; +static PyObject *acquireprogress_media_change(PyObject *self, PyObject *args) +{ + Py_RETURN_FALSE; +} + +static char *acquireprogress_ims_hit_doc = "ims_hit(item: AcquireItemDesc)\n\n" + "Invoked when an item is confirmed to be up-to-date. For instance,\n" + "when an HTTP download is informed that the file on the server was\n" + "not modified."; +static PyObject *acquireprogress_ims_hit(PyObject *self, PyObject *arg) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_fetch_doc = "fetch(item: AcquireItemDesc)\n\n" + "Invoked when some of an item's data is fetched."; +static PyObject *acquireprogress_fetch(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_done_doc = "done(item: AcquireItemDesc)\n\n" + "Invoked when an item is successfully and completely fetched."; +static PyObject *acquireprogress_done(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_fail_doc = "fail(item: AcquireItemDesc)\n\n" + "Invoked when the process of fetching an item encounters a fatal error."; +static PyObject *acquireprogress_fail(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_NONE; +} + +static char *acquireprogress_pulse_doc = "pulse(owner: Acquire) -> bool\n\n" + "Periodically invoked while the Acquire process is underway.\n\n" + "Return False if the user asked to cancel the whole Acquire process."; +static PyObject *acquireprogress_pulse(PyObject *self, PyObject *args) +{ + // TODO: Add type check. + Py_RETURN_TRUE; +} + +static char *acquireprogress_start_doc = "start()\n\n" + "Invoked when the Acquire process starts running."; +static PyObject *acquireprogress_start(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static char *acquireprogress_stop_doc = "stop()\n\n" + "Invoked when the Acquire process stops running."; +static PyObject *acquireprogress_stop(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyMethodDef acquireprogress_methods[] = { + {"media_change", acquireprogress_media_change, METH_VARARGS, + acquireprogress_media_change_doc}, + {"ims_hit",acquireprogress_ims_hit,METH_VARARGS, + acquireprogress_ims_hit_doc}, + {"fetch",acquireprogress_fetch,METH_VARARGS,acquireprogress_fetch_doc}, + {"done",acquireprogress_done,METH_VARARGS,acquireprogress_done_doc}, + {"fail",acquireprogress_fail,METH_VARARGS,acquireprogress_fail_doc}, + {"pulse",acquireprogress_pulse,METH_VARARGS,acquireprogress_pulse_doc}, + {"start",acquireprogress_start,METH_NOARGS,acquireprogress_start_doc}, + {"stop",acquireprogress_stop,METH_NOARGS,acquireprogress_stop_doc}, + {NULL} +}; + +static PyMemberDef acquireprogress_members[] = { + {"last_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, last_bytes), 0, + "The number of bytes fetched as of the previous call to pulse(),\n" + "including local items."}, + {"current_cps", T_DOUBLE, offsetof(PyAcquireProgressObject, current_cps), 0, + "The current rate of download, in bytes per second."}, + {"current_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, current_bytes), + 0, "The number of bytes fetched."}, + {"total_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, total_bytes), 0, + "The total number of bytes that need to be fetched. This member is\n" + "inaccurate, as new items might be enqueued while the download is\n" + "in progress!"}, + {"fetched_bytes", T_DOUBLE,offsetof(PyAcquireProgressObject, fetched_bytes), + 0, "The total number of bytes accounted for by items that were\n" + "successfully fetched."}, + {"elapsed_time", T_ULONG, offsetof(PyAcquireProgressObject, elapsed_time),0, + "The amount of time that has elapsed since the download started."}, + {"total_items", T_ULONG, offsetof(PyAcquireProgressObject, total_items),0, + "The total number of items that need to be fetched. This member is\n" + "inaccurate, as new items might be enqueued while the download is\n" + "in progress!"}, + {"current_items", T_ULONG, offsetof(PyAcquireProgressObject, current_items), + 0, "The number of items that have been successfully downloaded."}, + {NULL} +}; + +static char *acquireprogress_doc = "AcquireProgress()\n\n" + "A monitor object for downloads controlled by the Acquire class. This is\n" + "an mostly abstract class. You should subclass it and implement the\n" + "methods to get something useful."; + +PyTypeObject PyAcquireProgress_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireProgress", // tp_name + sizeof(PyAcquireProgressObject), // tp_basicsize + 0, // tp_itemsize + // Methods + 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 + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE, + acquireprogress_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + acquireprogress_methods, // tp_methods + acquireprogress_members, // 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 + PyType_GenericNew, // tp_new +}; diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index bc2f4258..4f948847 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -621,6 +621,8 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"HashString",&PyHashString_Type); ADDTYPE(Module,"Policy",&PyPolicy_Type); ADDTYPE(Module,"Hashes",&PyHashes_Type); + ADDTYPE(Module,"OpProgress",&PyOpProgress_Type); + ADDTYPE(Module,"AcquireProgress",&PyAcquireProgress_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 97be5d5c..34bc2ae5 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -112,6 +112,8 @@ extern PyTypeObject PyIndexRecords_Type; // Policy extern PyTypeObject PyPolicy_Type; extern PyTypeObject PyHashes_Type; +extern PyTypeObject PyOpProgress_Type; +extern PyTypeObject PyAcquireProgress_Type; #include "python-apt.h" #endif diff --git a/python/opprogress.cc b/python/opprogress.cc new file mode 100644 index 00000000..450e290a --- /dev/null +++ b/python/opprogress.cc @@ -0,0 +1,173 @@ +/* op-progress.cc - Base class for OpProgress classes. + * + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "generic.h" +#include +#include + +typedef struct { + PyObject_HEAD + PyObject *op; + PyObject *subop; + int major_change; + float percent; +} PyOpProgressObject; + +static PyObject *opprogress_update(PyObject *Self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyObject *opprogress_done(PyObject *Self, PyObject *args) +{ + Py_RETURN_NONE; +} + +static PyObject *opprogress_get_op(PyOpProgressObject *self, void *closure) +{ + return self->op; +} + +static int opprogress_set_op(PyOpProgressObject *self, PyObject *value, + void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'op'"); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError,"'op' must be a string."); + return -1; + } + Py_DECREF(self->op); + Py_INCREF(value); + + self->op = value; + return 0; +} + +static PyObject *opprogress_get_subop(PyOpProgressObject *self, void *closure) +{ + return self->subop; +} + +static int opprogress_set_subop(PyOpProgressObject *self, PyObject *value, + void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'subop'."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError,"'subop' must be a string."); + return -1; + } + Py_DECREF(self->subop); + Py_INCREF(value); + self->subop = value; + return 0; +} + +static PyMethodDef opprogress_methods[] = { + {"update",opprogress_update,METH_NOARGS,"update()\n\nCalled periodically."}, + {"done",opprogress_done,METH_NOARGS,"update()\n\nCalled when done."}, + {NULL}, +}; + +static PyMemberDef opprogress_members[] = { + {"major_change", T_INT, offsetof(PyOpProgressObject, major_change), 0, + "Boolean value indicating whether the change is a major change."}, + {"percent", T_FLOAT, offsetof(PyOpProgressObject, percent), 0, + "Percentage of completion (float value)."}, + {NULL} +}; + +static PyGetSetDef opprogress_getset[] = { + {"op", (getter)opprogress_get_op, (setter)opprogress_set_op, + "Description of the current operation"}, + {"subop", (getter)opprogress_get_subop, (setter)opprogress_set_subop, + "Description of the current sub-operation"}, + {NULL}, +}; + +static void opprogress_dealloc(PyObject *self) +{ + Py_XDECREF(((PyOpProgressObject *)self)->op); + Py_XDECREF(((PyOpProgressObject *)self)->subop); + self->ob_type->tp_free(self); +} + +static PyObject *opprogress_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) +{ + PyOpProgressObject *res = (PyOpProgressObject *)type->tp_alloc(type, 0); + res->op = PyString_FromString(""); + res->subop = PyString_FromString(""); + return (PyObject *)res; +} + +static char *opprogress_doc = "OpProgress()\n\n" + "A base class for writing custom operation progress classes. Subclasses\n" + "should override all the methods (and call the parent ones) but shall\n" + "not override any of the inherited descriptors because they may be\n" + "ignored."; + +PyTypeObject PyOpProgress_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.OpProgress", // tp_name + sizeof(PyOpProgressObject), // tp_basicsize + 0, // tp_itemsize + // Methods + opprogress_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 | // tp_flags + Py_TPFLAGS_BASETYPE, + opprogress_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + opprogress_methods, // tp_methods + opprogress_members, // tp_members + opprogress_getset, // 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 + opprogress_new, // tp_new +}; diff --git a/python/progress.cc b/python/progress.cc index 44f27b0c..b1845f0a 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -15,6 +15,7 @@ #include #include "progress.h" #include "generic.h" +#include "apt_pkgmodule.h" // generic bool PyCallbackObj::RunSimpleCallback(const char* method_name, @@ -75,11 +76,20 @@ void PyOpProgress::Update() PyObject_SetAttrString(callbackInst, "majorChange", o); Py_XDECREF(o); + + // Build up the argument list... if(CheckChange(0.05)) { - PyObject *arglist = Py_BuildValue("(f)", Percent); - RunSimpleCallback("update", arglist); + if (PyObject_TypeCheck(callbackInst, &PyOpProgress_Type)) { + o = Py_BuildValue("f", Percent); + PyObject_SetAttrString(callbackInst, "percent", o); + RunSimpleCallback("update"); + Py_XDECREF(o); + } else { + PyObject *arglist = Py_BuildValue("(f)", Percent); + RunSimpleCallback("update", arglist); + } } }; diff --git a/setup.py b/setup.py index af373632..b6dde3f9 100644 --- a/setup.py +++ b/setup.py @@ -34,8 +34,9 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'configuration.cc', 'depcache.cc', 'generic.cc', 'hashes.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', - 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc'] -files = ['python/' + fname for fname in files] + 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', + 'opprogress.cc', 'acquireprogress.cc'] +files = sorted(['python/' + fname for fname in files]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -- cgit v1.2.3 From a9cf6b4405a83bc0615cd313a8a7f1c23db3b402 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 19 Jul 2009 16:01:09 +0200 Subject: setup.py: Compile cdromprogress.cc. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index b6dde3f9..5cfe3bdc 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'opprogress.cc', 'acquireprogress.cc'] + 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc'] files = sorted(['python/' + fname for fname in files]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) -- cgit v1.2.3 From 652a7312b21aa7121c0075c3c970d5f68fcdf648 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 20 Jul 2009 18:04:19 +0200 Subject: python/lock.cc: Introduce apt_pkg.SystemLock context manager. This is the new alternative to pkgsystem_lock() and pkgsystem_unlock(), and is the recommended one. --- python/apt_pkgmodule.cc | 1 + python/apt_pkgmodule.h | 1 + python/lock.cc | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 python/lock.cc (limited to 'setup.py') diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index cbf88294..d4c23d2f 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -651,6 +651,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"AcquireProgress",&PyAcquireProgress_Type); ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type); ADDTYPE(Module,"CdromProgress",&PyCdromProgress_Type); + ADDTYPE(Module,"SystemLock",&PySystemLock_Type); // Tag file constants PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", CharCharToList(TFRewritePackageOrder)); diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 1277ab60..de70c056 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -117,6 +117,7 @@ extern PyTypeObject PyAcquireProgress_Type; extern PyTypeObject PyCdromProgress_Type; extern PyTypeObject PyAcquireItemDesc_Type; extern PyTypeObject PyAcquireWorker_Type; +extern PyTypeObject PySystemLock_Type; #include "python-apt.h" #endif diff --git a/python/lock.cc b/python/lock.cc new file mode 100644 index 00000000..aac2d25a --- /dev/null +++ b/python/lock.cc @@ -0,0 +1,123 @@ +/* + * lock.cc - Context managers for implementing locking. + * + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include "generic.h" + +static PyObject *systemlock_exit(PyObject *self, PyObject *args) +{ + + PyObject *exc_type = 0; + PyObject *exc_value = 0; + PyObject *traceback = 0; + if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value, + &traceback)) { + return 0; + } + if ((! exc_type || exc_type == Py_None) && _system->UnLock() == 0) { + return HandleErrors(); + } + Py_RETURN_FALSE; +} + +static PyObject *systemlock_enter(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + if (!_system->Lock()) + return HandleErrors(); + return self; +} + +static PyObject *systemlock_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) +{ + if (_system == 0) { + PyErr_SetString(PyExc_ValueError,"_system not initialized"); + return 0; + } + return PyType_GenericNew(type,args,kwds); +} + +static PyMethodDef systemlock_methods[] = { + {"__enter__",systemlock_enter,METH_VARARGS,"Lock the system."}, + {"__exit__",systemlock_exit,METH_VARARGS,"Unlock the system."}, + {NULL} +}; + +static char *systemlock_doc = "SystemLock()\n\n" + "Context manager for locking the package system. The lock is established\n" + "as soon as the method __enter__() is called. It is released when\n" + "__exit__() is called.\n\n" + "This should be used via the 'with' statement, e.g.::\n\n" + " with apt_pkg.SystemLock():\n" + " ...\n\n" + "Once the block is left, the lock is released automatically. The object\n" + "can be used multiple times::\n\n" + " lock = apt_pkg.SystemLock()\n" + " with lock:\n" + " ...\n" + " with lock:\n" + " ...\n\n"; + +PyTypeObject PySystemLock_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.SystemLock", // tp_name + 0, // tp_basicsize + 0, // tp_itemsize + // Methods + 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 + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), + systemlock_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + systemlock_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 + systemlock_new, // tp_new +}; diff --git a/setup.py b/setup.py index 5cfe3bdc..e07bd83b 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc'] + 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc', 'lock.cc'] files = sorted(['python/' + fname for fname in files]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) -- cgit v1.2.3 From 6ba42d2e31f161fc0ebe5405cf63b616c3e822b4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 22 Jul 2009 17:21:08 +0200 Subject: python: First step of fixing acquire stuff. Basically, we only want to have on PyAcquireItem per pkgAcquire::Item, and one PyAcquireItemDesc per pkgAcquire::ItemDesc. Therefore, we store them so we can return them at a later time. --- python/acquire-item.cc | 357 ++++++++++++++++++++++++++++++++++++++++++++++++ python/acquire.cc | 356 ++++++----------------------------------------- python/apt_pkgmodule.cc | 32 +++++ python/progress.cc | 12 +- python/progress.h | 7 + setup.py | 3 +- 6 files changed, 451 insertions(+), 316 deletions(-) create mode 100644 python/acquire-item.cc (limited to 'setup.py') diff --git a/python/acquire-item.cc b/python/acquire-item.cc new file mode 100644 index 00000000..cf0a628e --- /dev/null +++ b/python/acquire-item.cc @@ -0,0 +1,357 @@ +/* + * acquire-item.cc - Wrapper around pkgAcquire::Item and pkgAcqFile. + * + * Copyright 2004-2009 Canonical Ltd. + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "generic.h" +#include "apt_pkgmodule.h" + +#include +#include + +using namespace std; + + + +struct PyAcquireItems { + CppOwnedPyObject *file; + CppOwnedPyObject *item; + CppOwnedPyObject *desc; +}; + +typedef map item_map; + +// Keep a vector to PyAcquireItemObject pointers, so we can set the Object +// pointers to NULL when deallocating the main object (mostly AcquireFile). +struct PyAcquireObject : public CppPyObject { + item_map items; +}; + +inline pkgAcquire::Item *acquireitem_tocpp(PyObject *self) +{ + pkgAcquire::Item *itm = GetCpp(self); + if (itm == 0) + PyErr_SetString(PyExc_ValueError, "Acquire() has been shut down or " + "the AcquireFile() object has been deallocated."); + return itm; +} + +static PyObject *acquireitem_get_complete(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? PyBool_FromLong(item->Complete) : 0; +} + +static PyObject *acquireitem_get_desc_uri(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? CppPyString(item->DescURI()) : 0; +} + +static PyObject *acquireitem_get_destfile(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? CppPyString(item->DestFile) : 0; +} + + +static PyObject *acquireitem_get_error_text(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? CppPyString(item->ErrorText) : 0; +} + +static PyObject *acquireitem_get_filesize(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("i", item->FileSize) : 0; +} + +static PyObject *acquireitem_get_id(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("k", item->ID) : 0; +} + +static PyObject *acquireitem_get_mode(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("s", item->Mode) : 0; +} + +static PyObject *acquireitem_get_is_trusted(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? PyBool_FromLong(item->IsTrusted()) : 0; +} + +static PyObject *acquireitem_get_local(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? PyBool_FromLong(item->Local) : 0; +} + +static PyObject *acquireitem_get_status(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("i", item->Status) : 0; +} + +static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure) +{ + pkgAcquire::Item *Itm = acquireitem_tocpp(self); + if (Itm == 0) + return -1; + if (PyLong_Check(value)) { + Itm->ID = PyLong_AsLong(value); + } + else if (PyInt_Check(value)) { + Itm->ID = PyInt_AsLong(value); + } + else { + PyErr_SetString(PyExc_TypeError, "value must be integer."); + return -1; + } + return 0; +} + + +static PyGetSetDef acquireitem_getset[] = { + {"complete",acquireitem_get_complete}, + {"desc_uri",acquireitem_get_desc_uri}, + {"destfile",acquireitem_get_destfile}, + {"error_text",acquireitem_get_error_text}, + {"filesize",acquireitem_get_filesize}, + {"id",acquireitem_get_id,acquireitem_set_id}, + {"mode",acquireitem_get_mode}, + {"is_trusted",acquireitem_get_is_trusted}, + {"local",acquireitem_get_local}, + {"status",acquireitem_get_status}, +#ifdef COMPAT_0_7 + {"Complete",acquireitem_get_complete}, + {"DescURI",acquireitem_get_desc_uri}, + {"DestFile",acquireitem_get_destfile}, + {"ErrorText",acquireitem_get_error_text}, + {"FileSize",acquireitem_get_filesize}, + {"ID",acquireitem_get_id}, + {"IsTrusted",acquireitem_get_is_trusted}, + {"Local",acquireitem_get_local}, + {"Status",acquireitem_get_status}, +#endif + {} +}; + +static PyObject *acquireitem_repr(PyObject *Self) +{ + pkgAcquire::Item *Itm = acquireitem_tocpp(Self); + if (Itm == 0) + return 0; + + return PyString_FromFormat("<%s object: " + "Status: %i Complete: %i Local: %i IsTrusted: %i " + "FileSize: %lu DestFile:'%s' " + "DescURI: '%s' ID:%lu ErrorText: '%s'>", + Self->ob_type->tp_name, + Itm->Status, Itm->Complete, Itm->Local, Itm->IsTrusted(), + Itm->FileSize, Itm->DestFile.c_str(), Itm->DescURI().c_str(), + Itm->ID,Itm->ErrorText.c_str()); +} + +static void acquireitem_dealloc(PyObject *self) +{ + // TODO: Unregister the object in the owner. + if (!((CppOwnedPyObject*)self)->NoDelete) { + pkgAcquire::Item *item = PyAcquireItem_ToCpp(self); + PyAcquireObject *Owner = (PyAcquireObject *)GetOwner(self); + + PyAcquireItems item_struct = Owner->items[item]; + + if (item_struct.file != 0 && item_struct.file != self) + item_struct.file->Object = 0; + if (item_struct.item != 0 && item_struct.item != self) { + item_struct.item->Object = 0; + Py_DECREF(item_struct.item); + } + if (item_struct.desc != 0) { + item_struct.desc->Object = 0; + Py_DECREF(item_struct.desc); + } + Owner->items.erase(item); + } + + CppOwnedDeallocPtr(self); +} + +PyTypeObject PyAcquireItem_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireItem", // tp_name + sizeof(CppOwnedPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + acquireitem_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + acquireitem_repr, // 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, // tp_flags + "AcquireItem Object", // 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 + acquireitem_getset, // tp_getset +}; + +static PyObject *acquirefile_new(PyTypeObject *type, PyObject *Args, PyObject * kwds) +{ + PyObject *pyfetcher; + char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; + int size = 0; + uri = md5 = descr = shortDescr = destDir = destFile = ""; + + char *kwlist[] = {"owner","uri", "md5", "size", "descr", "short_descr", + "destdir", "destfile", NULL + }; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, + &PyAcquire_Type, &pyfetcher, &uri, &md5, + &size, &descr, &shortDescr, &destDir, &destFile) == 0) + return 0; + + pkgAcquire *fetcher = GetCpp(pyfetcher); + pkgAcqFile *af = new pkgAcqFile(fetcher, // owner + uri, // uri + md5, // md5 + size, // size + descr, // descr + shortDescr, + destDir, + destFile); // short-desc + CppOwnedPyObject *AcqFileObj = CppOwnedPyObject_NEW(pyfetcher, type); + AcqFileObj->Object = af; + + + ((PyAcquireObject *)pyfetcher)->items[af].file = AcqFileObj; + return AcqFileObj; +} + + +static char *acquirefile_doc = + "AcquireFile(owner, uri[, md5, size, descr, short_descr, destdir," + "destfile]) -> New AcquireFile() object\n\n" + "The parameter *owner* refers to an apt_pkg.Acquire() object. You can use\n" + "*destdir* OR *destfile* to specify the destination directory/file."; + +PyTypeObject PyAcquireFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireFile", // tp_name + sizeof(CppOwnedPyObject),// tp_basicsize + 0, // tp_itemsize + // Methods + acquireitem_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 | // tp_flags + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, + acquirefile_doc, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + &PyAcquireItem_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + acquirefile_new, // tp_new +}; + +#ifdef COMPAT_0_7 +char *doc_GetPkgAcqFile = + "GetPkgAcqFile(pkgAquire, uri[, md5, size, descr, shortDescr, destDir, destFile]) -> PkgAcqFile\n"; +PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) +{ + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgAcqFile() is " + "deprecated. Please see apt_pkg.AcquireFile() for the " + "replacement", 1); + PyObject *pyfetcher; + char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; + int size = 0; + uri = md5 = descr = shortDescr = destDir = destFile = ""; + + char * kwlist[] = {"owner","uri", "md5", "size", "descr", "shortDescr", + "destDir", "destFile", NULL + }; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, + &PyAcquire_Type, &pyfetcher, &uri, &md5, + &size, &descr, &shortDescr, &destDir, &destFile) == 0) + return 0; + + pkgAcquire *fetcher = GetCpp(pyfetcher); + pkgAcqFile *af = new pkgAcqFile(fetcher, // owner + uri, // uri + md5, // md5 + size, // size + descr, // descr + shortDescr, + destDir, + destFile); // short-desc + CppPyObject *AcqFileObj = CppPyObject_NEW(&PyAcquireFile_Type); + AcqFileObj->Object = af; + AcqFileObj->NoDelete = true; + + return AcqFileObj; +} +#endif diff --git a/python/acquire.cc b/python/acquire.cc index 78bd016e..5e03586e 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -13,23 +13,22 @@ #include #include -typedef CppOwnedPyObject PyAcquireItemObject; -typedef CppOwnedPyObject PyAcquireItemDescObject; -typedef CppOwnedPyObject PyAcquireFileObject; -typedef CppOwnedPyObject PyAcquireWorkerObject; - +typedef CppOwnedPyObject PyAcquireWorkerObject; struct PyAcquireItems { - PyAcquireFileObject *file; - PyAcquireItemObject *item; + CppOwnedPyObject *file; + CppOwnedPyObject *item; + CppOwnedPyObject *desc; }; +typedef map item_map; +typedef map worker_map; + // Keep a vector to PyAcquireItemObject pointers, so we can set the Object // pointers to NULL when deallocating the main object (mostly AcquireFile). struct PyAcquireObject : public CppPyObject { - map item_map; - map itemdesc_map; - map worker_map; + item_map items; + worker_map workers; }; @@ -47,18 +46,20 @@ static PyObject *acquireworker_get_current_item(PyObject *self, void *closure) PyObject *PyItem; // FIXME: PyAcquire_FromCpp needs to initialize item_map. - if (PyAcquire && false && PyAcquire->item_map[Item].item) { + if (PyAcquire && false && PyAcquire->items[Item].item) { Py_INCREF(PyItem); - PyItem = PyAcquire->item_map[Item].item; + PyItem = PyAcquire->items[Item].item; } else { PyItem = PyAcquireItem_FromCpp(Item,false,PyAcquire); // FIXME: PyAcquire_FromCpp needs to initialize item_map. if (PyAcquire && false) - PyAcquire->item_map[Item].item = (PyAcquireItemObject*)PyItem; + PyAcquire->items[Item].item = (CppOwnedPyObject*)PyItem; } - return PyAcquireItemDesc_FromCpp(worker->CurrentItem,false,PyItem); + PyObject *ret = PyAcquireItemDesc_FromCpp(worker->CurrentItem,false,PyItem); + Py_DECREF(PyItem); + return ret; } static PyObject *acquireworker_get_status(PyObject *self, void *closure) @@ -208,168 +209,6 @@ PyTypeObject PyAcquireItemDesc_Type = 0, // tp_new }; -inline pkgAcquire::Item *acquireitem_tocpp(PyObject *self) { - pkgAcquire::Item *itm = GetCpp(self); - if (itm == 0) - PyErr_SetString(PyExc_ValueError, "Acquire() has been shut down or " - "the AcquireFile() object has been deallocated."); - return itm; -} - -#define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \ -{ \ - pkgAcquire::Item *Itm = acquireitem_tocpp(Self); \ - if (Itm == 0) \ - return 0; \ - return Ret; \ -} - -// Define our getters -MkGet(AcquireItemGetComplete,Py_BuildValue("i",Itm->Complete)); -MkGet(AcquireItemGetDescURI,Safe_FromString(Itm->DescURI().c_str())); -MkGet(AcquireItemGetDestFile,Safe_FromString(Itm->DestFile.c_str())); -MkGet(AcquireItemGetErrorText,Safe_FromString(Itm->ErrorText.c_str())); -MkGet(AcquireItemGetFileSize,Py_BuildValue("i",Itm->FileSize)); -MkGet(AcquireItemGetID,Py_BuildValue("k",Itm->ID)); -MkGet(AcquireItemGetMode,Py_BuildValue("s",Itm->Mode)); -MkGet(AcquireItemGetIsTrusted,Py_BuildValue("i",Itm->IsTrusted())); -MkGet(AcquireItemGetLocal,Py_BuildValue("i",Itm->Local)); -MkGet(AcquireItemGetStatus,Py_BuildValue("i",Itm->Status)); - -// Constants -MkGet(AcquireItemGetStatIdle,Py_BuildValue("i", pkgAcquire::Item::StatIdle)); -MkGet(AcquireItemGetStatFetching,Py_BuildValue("i", pkgAcquire::Item::StatFetching)); -MkGet(AcquireItemGetStatDone,Py_BuildValue("i", pkgAcquire::Item::StatDone)); -MkGet(AcquireItemGetStatError,Py_BuildValue("i", pkgAcquire::Item::StatError)); -MkGet(AcquireItemGetStatAuthError,Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); -#undef MkGet - -static int AcquireItemSetID(PyObject *self, PyObject *value, void *closure) -{ - pkgAcquire::Item *Itm = acquireitem_tocpp(self); - if (Itm == 0) - return -1; - if (PyLong_Check(value)) { - Itm->ID = PyLong_AsLong(value); - } - else if (PyInt_Check(value)) { - Itm->ID = PyInt_AsLong(value); - } - else { - PyErr_SetString(PyExc_TypeError, "value must be integer."); - return -1; - } - return 0; -} - - -static PyGetSetDef AcquireItemGetSet[] = { - {"complete",AcquireItemGetComplete}, - {"desc_uri",AcquireItemGetDescURI}, - {"destfile",AcquireItemGetDestFile}, - {"error_text",AcquireItemGetErrorText}, - {"filesize",AcquireItemGetFileSize}, - {"id",AcquireItemGetID,AcquireItemSetID}, - {"mode",AcquireItemGetMode}, - {"is_trusted",AcquireItemGetIsTrusted}, - {"local",AcquireItemGetLocal}, - {"status",AcquireItemGetStatus}, - {"stat_idle",AcquireItemGetStatIdle}, - {"stat_fetching",AcquireItemGetStatFetching}, - {"stat_done",AcquireItemGetStatDone}, - {"stat_error",AcquireItemGetStatError}, - {"stat_auth_error",AcquireItemGetStatAuthError}, -#ifdef COMPAT_0_7 - {"Complete",AcquireItemGetComplete}, - {"DescURI",AcquireItemGetDescURI}, - {"DestFile",AcquireItemGetDestFile}, - {"ErrorText",AcquireItemGetErrorText}, - {"FileSize",AcquireItemGetFileSize}, - {"ID",AcquireItemGetID}, - {"IsTrusted",AcquireItemGetIsTrusted}, - {"Local",AcquireItemGetLocal}, - {"Status",AcquireItemGetStatus}, - {"StatIdle",AcquireItemGetStatIdle}, - {"StatFetching",AcquireItemGetStatFetching}, - {"StatDone",AcquireItemGetStatDone}, - {"StatError",AcquireItemGetStatError}, - {"StatAuthError",AcquireItemGetStatAuthError}, -#endif - {} -}; - - - -static PyObject *AcquireItemRepr(PyObject *Self) -{ - pkgAcquire::Item *Itm = acquireitem_tocpp(Self); - if (Itm == 0) - return 0; - - return PyString_FromFormat("<%s object: " - "Status: %i Complete: %i Local: %i IsTrusted: %i " - "FileSize: %lu DestFile:'%s' " - "DescURI: '%s' ID:%lu ErrorText: '%s'>", - Self->ob_type->tp_name, - Itm->Status, Itm->Complete, Itm->Local, Itm->IsTrusted(), - Itm->FileSize, Itm->DestFile.c_str(), Itm->DescURI().c_str(), - Itm->ID,Itm->ErrorText.c_str()); -} - -static void AcquireItemDealloc(PyObject *self) { - pkgAcquire::Item *file = GetCpp(self); - PyAcquireObject *owner = (PyAcquireObject *)GetOwner(self); - - // Simply deallocate the object if we have no owner. - if (owner != NULL && !((CppPyObject *)self)->NoDelete) { - PyAcquireItems &items = owner->item_map[file]; - - if (items.item && items.item != self) - items.item->Object = NULL; - if (items.file && items.item != self) - items.file->Object = NULL; - owner->item_map.erase(file); - } - - CppOwnedDeallocPtr(self); -} - - - -PyTypeObject PyAcquireItem_Type = -{ - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.AcquireItem", // tp_name - sizeof(CppOwnedPyObject), // tp_basicsize - 0, // tp_itemsize - // Methods - AcquireItemDealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - AcquireItemRepr, // 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, // tp_flags - "AcquireItem Object", // 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 - AcquireItemGetSet, // tp_getset -}; @@ -396,15 +235,20 @@ static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) fetcher->Shutdown(); // TODO: Delete all objects here - map items = ((PyAcquireObject *)Self)->item_map; - for (map::iterator I = items.begin(); - I != items.end(); I++) { - (*I).second.file->Object = NULL; - (*I).second.item->Object = NULL; + item_map &items = ((PyAcquireObject *)Self)->items; + for (item_map::iterator I = items.begin(); I != items.end(); I++) { + if ((*I).second.file) + (*I).second.file->Object = NULL; + if ((*I).second.item) { + (*I).second.item->Object = NULL; + Py_DECREF((*I).second.item); + } + if ((*I).second.desc) { + (*I).second.desc->Object = NULL; + Py_DECREF((*I).second.desc); + } } - - - + items.clear(); Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -442,6 +286,7 @@ static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure) PyWorker = CppOwnedPyObject_NEW(self,&PyAcquireWorker_Type, Worker); PyWorker->NoDelete = true; PyList_Append(List, PyWorker); + Py_DECREF(PyWorker); } return List; } @@ -449,19 +294,22 @@ static PyObject *PkgAcquireGetItems(PyObject *Self,void*) { pkgAcquire *fetcher = GetCpp(Self); PyObject *List = PyList_New(0); - PyAcquireItemObject *Obj; + CppOwnedPyObject *Obj; for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); I != fetcher->ItemsEnd(); I++) { - if (((PyAcquireObject *)Self)->item_map[*I].item) - PyList_Append(List, ((PyAcquireObject *)Self)->item_map[*I].item); + if (((PyAcquireObject *)Self)->items[*I].item) + PyList_Append(List, ((PyAcquireObject *)Self)->items[*I].item); else { Obj = CppOwnedPyObject_NEW(Self,&PyAcquireItem_Type,*I); Obj->NoDelete = true; + PyList_Append(List,Obj); - ((PyAcquireObject *)Self)->item_map[*I].item = Obj; - Py_DECREF(Obj); + ((PyAcquireObject *)Self)->items[*I].item = Obj; + + + // Not DECREFING it, we want to manage it somewhere else. } } return List; @@ -506,9 +354,10 @@ static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) if (PyArg_ParseTupleAndKeywords(Args,kwds,"|O",kwlist,&pyFetchProgressInst) == 0) return 0; + PyFetchProgress *progress = 0; if (pyFetchProgressInst != NULL) { // FIXME: memleak? - PyFetchProgress *progress = new PyFetchProgress(); + progress = new PyFetchProgress(); progress->setCallbackInst(pyFetchProgressInst); fetcher = new pkgAcquire(progress); } else { @@ -518,8 +367,11 @@ static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) PyAcquireObject *FetcherObj = (PyAcquireObject *) CppPyObject_NEW(type, fetcher); + if (progress != 0) + progress->setPyAcquire(FetcherObj); // prepare our map of items. - new (&FetcherObj->item_map) map(); + new (&FetcherObj->items) item_map(); + new (&FetcherObj->workers) worker_map(); return FetcherObj; } @@ -581,125 +433,3 @@ PyObject *GetAcquire(PyObject *Self,PyObject *Args) } #endif -static PyObject *PkgAcquireFileNew(PyTypeObject *type, PyObject *Args, PyObject * kwds) -{ - PyObject *pyfetcher; - char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; - int size = 0; - uri = md5 = descr = shortDescr = destDir = destFile = ""; - - char * kwlist[] = {"owner","uri", "md5", "size", "descr", "short_descr", - "destdir", "destfile", NULL}; - - if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, - &PyAcquire_Type, &pyfetcher, &uri, &md5, - &size, &descr, &shortDescr, &destDir, &destFile) == 0) - return 0; - - pkgAcquire *fetcher = GetCpp(pyfetcher); - pkgAcqFile *af = new pkgAcqFile(fetcher, // owner - uri, // uri - md5, // md5 - size, // size - descr, // descr - shortDescr, - destDir, - destFile); // short-desc - CppOwnedPyObject *AcqFileObj = CppOwnedPyObject_NEW(pyfetcher, type); - AcqFileObj->Object = af; - - // Register the file so we can remove it later. - ((PyAcquireObject *)pyfetcher)->item_map[af].file = AcqFileObj; - - return AcqFileObj; -} - - -static char *doc_PkgAcquireFile = - "AcquireFile(owner, uri[, md5, size, descr, short_descr, destdir," - "destfile]) -> New AcquireFile() object\n\n" - "The parameter *owner* refers to an apt_pkg.Acquire() object. You can use\n" - "*destdir* OR *destfile* to specify the destination directory/file."; - -PyTypeObject PyAcquireFile_Type = -{ - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.AcquireFile", // tp_name - sizeof(CppOwnedPyObject),// tp_basicsize - 0, // tp_itemsize - // Methods - AcquireItemDealloc, // 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 | // tp_flags - Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC), - doc_PkgAcquireFile, // tp_doc - CppOwnedTraverse, // tp_traverse - CppOwnedClear, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - 0, // tp_methods - 0, // tp_members - 0, // tp_getset - &PyAcquireItem_Type, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - PkgAcquireFileNew, // tp_new -}; - -#ifdef COMPAT_0_7 -char *doc_GetPkgAcqFile = -"GetPkgAcqFile(pkgAquire, uri[, md5, size, descr, shortDescr, destDir, destFile]) -> PkgAcqFile\n"; -PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) -{ - PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgAcqFile() is " - "deprecated. Please see apt_pkg.AcquireFile() for the " - "replacement", 1); - PyObject *pyfetcher; - char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; - int size = 0; - uri = md5 = descr = shortDescr = destDir = destFile = ""; - - char * kwlist[] = {"owner","uri", "md5", "size", "descr", "shortDescr", - "destDir", "destFile", NULL}; - - if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, - &PyAcquire_Type, &pyfetcher, &uri, &md5, - &size, &descr, &shortDescr, &destDir, &destFile) == 0) - return 0; - - pkgAcquire *fetcher = GetCpp(pyfetcher); - pkgAcqFile *af = new pkgAcqFile(fetcher, // owner - uri, // uri - md5, // md5 - size, // size - descr, // descr - shortDescr, - destDir, - destFile); // short-desc - CppPyObject *AcqFileObj = CppPyObject_NEW(&PyAcquireFile_Type); - AcqFileObj->Object = af; - AcqFileObj->NoDelete = true; - - return AcqFileObj; -} -#endif diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 5ee4015c..0a899efb 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -13,6 +13,7 @@ #include "generic.h" #include +#include #include #include #include @@ -606,6 +607,9 @@ extern "C" void initapt_pkg() PyModule_AddObject(Module,"Config",Config); #endif + + + // Add our classes. /* ============================ tag.cc ============================ */ ADDTYPE(Module,"TagSection",&PyTagSection_Type); @@ -661,6 +665,34 @@ extern "C" void initapt_pkg() PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER", CharCharToList(TFRewriteSourceOrder)); + + // AcquireItem Constants. + + + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_idle", + Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_fetching", + Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_done", + Py_BuildValue("i", pkgAcquire::Item::StatDone)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_error", + Py_BuildValue("i", pkgAcquire::Item::StatError)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_auth_error", + Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); + +#ifdef COMPAT_0_7 + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatIdle", + Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatFetching", + Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatDone", + Py_BuildValue("i", pkgAcquire::Item::StatDone)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatError", + Py_BuildValue("i", pkgAcquire::Item::StatError)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatAuthError", + Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); +#endif + #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 PyObject *PyCapsule = PyCapsule_New(&API, "apt_pkg._C_API", NULL); #else diff --git a/python/progress.cc b/python/progress.cc index 305246b7..1b135a75 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -35,7 +35,12 @@ inline bool setattr(PyObject *object, const char *attr, const char *fmt, T arg) return result != -1; } -#define TUPLEIZE(op) Py_BuildValue("(O)", op) +inline PyObject *TUPLEIZE(PyObject *op) { + PyObject *ret = Py_BuildValue("(O)", op); + Py_DECREF(op); + return ret; +} + // generic bool PyCallbackObj::RunSimpleCallback(const char* method_name, PyObject *arglist, @@ -300,7 +305,10 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) if (PyObject_TypeCheck(callbackInst, &PyAcquireProgress_Type)) { PyObject *result1; bool res1 = true; - if (RunSimpleCallback("pulse", TUPLEIZE(PyAcquire_FromCpp(Owner)), &result1)) { + + Py_INCREF(pyAcquire); + + if (RunSimpleCallback("pulse", TUPLEIZE(pyAcquire) , &result1)) { if (result1 != NULL && PyArg_Parse(result1, "b", &res1) && res1 == false) { // the user returned a explicit false here, stop PyCbObj_BEGIN_ALLOW_THREADS diff --git a/python/progress.h b/python/progress.h index e92933a7..bc1bd640 100644 --- a/python/progress.h +++ b/python/progress.h @@ -94,6 +94,9 @@ struct PyOpProgress : public OpProgress, public PyCallbackObj struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj { + protected: + PyObject *pyAcquire; + public: enum { DLDone, DLQueued, DLFailed, DLHit, DLIgnored }; @@ -102,6 +105,10 @@ struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj virtual bool MediaChange(string Media, string Drive); + void setPyAcquire(PyObject *o) { + pyAcquire = o; + } + /* apt stuff */ virtual void IMSHit(pkgAcquire::ItemDesc &Itm); virtual void Fetch(pkgAcquire::ItemDesc &Itm); diff --git a/setup.py b/setup.py index e07bd83b..93fcb436 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,8 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc', 'lock.cc'] + 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc', 'lock.cc', + 'acquire-item.cc'] files = sorted(['python/' + fname for fname in files]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) -- cgit v1.2.3 From fb8e639a7199a5707ae24c8424e5dc748fe0be37 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 31 Jul 2009 15:24:09 +0200 Subject: python: Remove the progress classes in apt_pkg. They have been replaced with apt.progress.base, so stuff like GTK+ or Qt progress classes can be written using subclassing. --- apt/cache.py | 6 +- apt/cdrom.py | 3 +- apt/progress/old.py | 28 +++---- apt/progress/text.py | 36 ++++---- python/acquireprogress.cc | 208 ---------------------------------------------- python/apt_pkgmodule.cc | 3 - python/apt_pkgmodule.h | 3 - python/cache.cc | 6 -- python/cdrom.cc | 3 +- python/cdromprogress.cc | 106 ----------------------- python/opprogress.cc | 175 -------------------------------------- python/progress.h | 32 ------- setup.py | 5 +- 13 files changed, 36 insertions(+), 578 deletions(-) delete mode 100644 python/acquireprogress.cc delete mode 100644 python/cdromprogress.cc delete mode 100644 python/opprogress.cc (limited to 'setup.py') diff --git a/apt/cache.py b/apt/cache.py index f507863c..ae4254e0 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -122,11 +122,7 @@ class Cache(object): size=len(self._cache.packages) for pkg in self._cache.packages: if progress is not None and last+100 < i: - if isinstance(progress, apt_pkg.OpProgress): - progress.percent = i/float(size)*100 - progress.update() - else: - progress.update(i/float(size)*100) + progress.update(i/float(size)*100) last=i # drop stuff with no versions (cruft) if len(pkg.version_list) > 0: diff --git a/apt/cdrom.py b/apt/cdrom.py index 126c54dd..01caa12f 100644 --- a/apt/cdrom.py +++ b/apt/cdrom.py @@ -24,6 +24,7 @@ import glob import apt_pkg from apt.deprecation import AttributeDeprecatedBy +from apt.progress.base import CdromProgress class Cdrom(apt_pkg.Cdrom): @@ -46,7 +47,7 @@ class Cdrom(apt_pkg.Cdrom): def __init__(self, progress=None, mountpoint=None, nomount=True): apt_pkg.Cdrom.__init__(self) if progress is None: - self._progress = apt_pkg.CdromProgress() + self._progress = CdromProgress() else: self._progress = progress # see if we have a alternative mountpoint diff --git a/apt/progress/old.py b/apt/progress/old.py index 88957272..adaf94b2 100644 --- a/apt/progress/old.py +++ b/apt/progress/old.py @@ -34,29 +34,21 @@ import sys import apt_pkg from apt.deprecation import AttributeDeprecatedBy, function_deprecated_by +from apt.progress import base __all__ = [] -class OpProgress(object): +class OpProgress(base.OpProgress): """Abstract class to implement reporting on cache opening. Subclass this class to implement simple Operation progress reporting. """ - def __init__(self): - self.op = None - self.subop = None - - def update(self, percent): - """Called periodically to update the user interface.""" - - def done(self): - """Called once an operation has been completed.""" - if apt_pkg._COMPAT_0_7: subOp = AttributeDeprecatedBy('subop') + Op = AttributeDeprecatedBy('op') class OpTextProgress(OpProgress): @@ -65,13 +57,15 @@ class OpTextProgress(OpProgress): def __init__(self): OpProgress.__init__(self) - def update(self, percent): + def update(self, percent=None): """Called periodically to update the user interface.""" - sys.stdout.write("\r%s: %.2i " % (self.subop, percent)) + OpProgress.update(self, percent) + sys.stdout.write("\r%s: %.2i " % (self.subop, self.percent)) sys.stdout.flush() def done(self): """Called once an operation has been completed.""" + OpProgress.done(self) sys.stdout.write("\r%s: Done\n" % self.op) @@ -349,13 +343,15 @@ class InstallProgress(DumbInstallProgress): updateInterface = function_deprecated_by(update_interface) -class CdromProgress(apt_pkg.CdromProgress): +class CdromProgress(base.CdromProgress): """Report the cdrom add progress. This class has been replaced by apt_pkg.CdromProgress. """ - askCdromName = function_deprecated_by(apt_pkg.CdromProgress.ask_cdrom_name) - changeCdrom = function_deprecated_by(apt_pkg.CdromProgress.change_cdrom) + _basetype = base.CdromProgress + askCdromName = function_deprecated_by(_basetype.ask_cdrom_name) + changeCdrom = function_deprecated_by(_basetype.change_cdrom) + del _basetype class DpkgInstallProgress(InstallProgress): diff --git a/apt/progress/text.py b/apt/progress/text.py index 54a35704..eb474d6d 100644 --- a/apt/progress/text.py +++ b/apt/progress/text.py @@ -18,7 +18,7 @@ import sys import apt_pkg -import apt.progress.base +from apt.progress import base __all__ = ['AcquireProgress', 'CdromProgress', 'OpProgress'] @@ -55,7 +55,7 @@ class TextProgress(object): self._file.flush() -class OpProgress(apt.progress.base.OpProgress, TextProgress): +class OpProgress(base.OpProgress, TextProgress): """Operation progress reporting. This closely resembles OpTextProgress in libapt-pkg. @@ -63,12 +63,12 @@ class OpProgress(apt.progress.base.OpProgress, TextProgress): def __init__(self, outfile=None): TextProgress.__init__(self, outfile) - apt.progress.base.OpProgress.__init__(self) + base.OpProgress.__init__(self) self.old_op = "" def update(self, percent=None): """Called periodically to update the user interface.""" - apt.progress.base.OpProgress.update(self, percent) + base.OpProgress.update(self, percent) if self.major_change and self.old_op: self._write(self.old_op) self._write("%s... %i%%\r" % (self.op, self.percent), False, True) @@ -76,18 +76,18 @@ class OpProgress(apt.progress.base.OpProgress, TextProgress): def done(self): """Called once an operation has been completed.""" - apt.progress.base.OpProgress.done(self) + base.OpProgress.done(self) if self.old_op: self._write(_("%c%s... Done") % ('\r', self.old_op), True, True) self.old_op = "" -class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): +class AcquireProgress(base.AcquireProgress, TextProgress): """AcquireProgress for the text interface.""" def __init__(self, outfile=None): TextProgress.__init__(self, outfile) - apt.progress.base.AcquireProgress.__init__(self) + base.AcquireProgress.__init__(self) self._signal = None self._width = 80 self._id = 1 @@ -98,7 +98,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): In this case, the function sets up a signal handler for SIGWINCH, i.e. window resize signals. And it also sets id to 1. """ - apt.progress.base.AcquireProgress.start(self) + base.AcquireProgress.start(self) import signal self._signal = signal.signal(signal.SIGWINCH, self._winch) # Get the window size. @@ -116,7 +116,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): def ims_hit(self, item): """Called when an item is update (e.g. not modified on the server).""" - apt.progress.base.AcquireProgress.ims_hit(self, item) + base.AcquireProgress.ims_hit(self, item) line = _('Hit ') + item.description if item.owner.filesize: line += ' [%sB]' % apt_pkg.size_to_str(item.owner.filesize) @@ -124,7 +124,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): def fail(self, item): """Called when an item is failed.""" - apt.progress.base.AcquireProgress.fail(self, item) + base.AcquireProgress.fail(self, item) if item.owner.status == item.owner.stat_done: self._write(_("Ign ") + item.description) else: @@ -133,7 +133,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): def fetch(self, item): """Called when some of the item's data is fetched.""" - apt.progress.base.AcquireProgress.fetch(self, item) + base.AcquireProgress.fetch(self, item) # It's complete already (e.g. Hit) if item.owner.complete: return @@ -149,7 +149,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): """Periodically invoked while the Acquire process is underway. Return False if the user asked to cancel the whole Acquire process.""" - apt.progress.base.AcquireProgress.pulse(self, owner) + base.AcquireProgress.pulse(self, owner) percent = (((self.current_bytes + self.current_items) * 100.0) / float(self.total_bytes + self.total_items)) @@ -209,7 +209,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): def media_change(self, medium, drive): """Prompt the user to change the inserted removable media.""" - apt.progress.base.AcquireProgress.media_change(self, medium, drive) + base.AcquireProgress.media_change(self, medium, drive) self._write(_("Media change: please insert the disc labeled\n" " '%s'\n" "in the drive '%s' and press enter\n") % (medium, drive)) @@ -217,7 +217,7 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): def stop(self): """Invoked when the Acquire process stops running.""" - apt.progress.base.AcquireProgress.stop(self) + base.AcquireProgress.stop(self) # Trick for getting a translation from apt self._write((_("Fetched %sB in %s (%sB/s)\n") % ( apt_pkg.size_to_str(self.fetched_bytes), @@ -229,12 +229,12 @@ class AcquireProgress(apt.progress.base.AcquireProgress, TextProgress): signal.signal(signal.SIGWINCH, self._signal) -class CdromProgress(apt.progress.base.CdromProgress, TextProgress): +class CdromProgress(base.CdromProgress, TextProgress): """Text CD-ROM progress.""" def ask_cdrom_name(self): """Ask the user to provide a name for the disc.""" - apt.progress.base.CdromProgress.ask_cdrom_name(self) + base.CdromProgress.ask_cdrom_name(self) self._write(_("Please provide a name for this Disc, such as " "'Debian 2.1r1 Disk 1'"), False) try: @@ -244,13 +244,13 @@ class CdromProgress(apt.progress.base.CdromProgress, TextProgress): def update(self, text, current): """Set the current progress.""" - apt.progress.base.CdromProgress.update(self, text, current) + base.CdromProgress.update(self, text, current) if text: self._write(text, False) def change_cdrom(self): """Ask the user to change the CD-ROM.""" - apt.progress.base.CdromProgress.change_cdrom(self) + base.CdromProgress.change_cdrom(self) self._write(_("Please insert a Disc in the drive and press enter"), False) try: diff --git a/python/acquireprogress.cc b/python/acquireprogress.cc deleted file mode 100644 index c7db8921..00000000 --- a/python/acquireprogress.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* acquireprogress.cc - Base class for FetchProgress classes. - * - * Copyright 2009 Julian Andres Klode - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include "apt_pkgmodule.h" -#include "progress.h" -#include -#include - - - -// DUMMY IMPLEMENTATIONS. -static char *acquireprogress_media_change_doc = - "media_change(media: str, drive: str) -> bool\n\n" - "Invoked when the user should be prompted to change the inserted\n" - "removable media.\n\n" - "This method should not return until the user has confirmed to the user\n" - "interface that the media change is complete.\n\n" - ":param:media The name of the media type that should be changed.\n" - ":param:drive The identifying name of the drive whose media should be\n" - " changed.\n\n" - "Return True if the user confirms the media change, False if it is\n" - "cancelled."; -static PyObject *acquireprogress_media_change(PyObject *self, PyObject *args) -{ - Py_RETURN_FALSE; -} - -static char *acquireprogress_ims_hit_doc = "ims_hit(item: AcquireItemDesc)\n\n" - "Invoked when an item is confirmed to be up-to-date. For instance,\n" - "when an HTTP download is informed that the file on the server was\n" - "not modified."; -static PyObject *acquireprogress_ims_hit(PyObject *self, PyObject *arg) -{ - if (!PyAcquireItemDesc_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "ims_hit() argument must be " - "apt_pkg.AcquireItemDesc"); - return 0; - } - Py_RETURN_NONE; -} - -static char *acquireprogress_fetch_doc = "fetch(item: AcquireItemDesc)\n\n" - "Invoked when some of an item's data is fetched."; -static PyObject *acquireprogress_fetch(PyObject *self, PyObject *arg) -{ - if (!PyAcquireItemDesc_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "fetch() argument must be " - "apt_pkg.AcquireItemDesc"); - return 0; - } - Py_RETURN_NONE; -} - -static char *acquireprogress_done_doc = "done(item: AcquireItemDesc)\n\n" - "Invoked when an item is successfully and completely fetched."; -static PyObject *acquireprogress_done(PyObject *self, PyObject *arg) -{ - if (!PyAcquireItemDesc_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "done() argument must be " - "apt_pkg.AcquireItemDesc"); - return 0; - } - Py_RETURN_NONE; -} - -static char *acquireprogress_fail_doc = "fail(item: AcquireItemDesc)\n\n" - "Invoked when the process of fetching an item encounters a fatal error."; -static PyObject *acquireprogress_fail(PyObject *self, PyObject *arg) -{ - if (!PyAcquireItemDesc_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "fail() argument must be " - "apt_pkg.AcquireItemDesc"); - return 0; - } - Py_RETURN_NONE; -} - -static char *acquireprogress_pulse_doc = "pulse(owner: Acquire) -> bool\n\n" - "Periodically invoked while the Acquire process is underway.\n\n" - "Return False if the user asked to cancel the whole Acquire process."; -static PyObject *acquireprogress_pulse(PyObject *self, PyObject *arg) -{ - if (!PyAcquire_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "pulse() argument must be " - "apt_pkg.Acquire"); - return 0; - } - Py_RETURN_TRUE; -} - -static char *acquireprogress_start_doc = "start()\n\n" - "Invoked when the Acquire process starts running."; -static PyObject *acquireprogress_start(PyObject *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static char *acquireprogress_stop_doc = "stop()\n\n" - "Invoked when the Acquire process stops running."; -static PyObject *acquireprogress_stop(PyObject *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyMethodDef acquireprogress_methods[] = { - {"media_change", acquireprogress_media_change, METH_VARARGS, - acquireprogress_media_change_doc}, - {"ims_hit",acquireprogress_ims_hit,METH_O, - acquireprogress_ims_hit_doc}, - {"fetch",acquireprogress_fetch,METH_O,acquireprogress_fetch_doc}, - {"done",acquireprogress_done,METH_O,acquireprogress_done_doc}, - {"fail",acquireprogress_fail,METH_O,acquireprogress_fail_doc}, - {"pulse",acquireprogress_pulse,METH_O,acquireprogress_pulse_doc}, - {"start",acquireprogress_start,METH_NOARGS,acquireprogress_start_doc}, - {"stop",acquireprogress_stop,METH_NOARGS,acquireprogress_stop_doc}, - {NULL} -}; - -static PyMemberDef acquireprogress_members[] = { - {"last_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, last_bytes), 0, - "The number of bytes fetched as of the previous call to pulse(),\n" - "including local items."}, - {"current_cps", T_DOUBLE, offsetof(PyAcquireProgressObject, current_cps), 0, - "The current rate of download, in bytes per second."}, - {"current_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, current_bytes), - 0, "The number of bytes fetched."}, - {"total_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, total_bytes), 0, - "The total number of bytes that need to be fetched. This member is\n" - "inaccurate, as new items might be enqueued while the download is\n" - "in progress!"}, - {"fetched_bytes", T_DOUBLE,offsetof(PyAcquireProgressObject, fetched_bytes), - 0, "The total number of bytes accounted for by items that were\n" - "successfully fetched."}, - {"elapsed_time", T_ULONG, offsetof(PyAcquireProgressObject, elapsed_time),0, - "The amount of time that has elapsed since the download started."}, - {"total_items", T_ULONG, offsetof(PyAcquireProgressObject, total_items),0, - "The total number of items that need to be fetched. This member is\n" - "inaccurate, as new items might be enqueued while the download is\n" - "in progress!"}, - {"current_items", T_ULONG, offsetof(PyAcquireProgressObject, current_items), - 0, "The number of items that have been successfully downloaded."}, - {NULL} -}; - -static char *acquireprogress_doc = "AcquireProgress()\n\n" - "A monitor object for downloads controlled by the Acquire class. This is\n" - "an mostly abstract class. You should subclass it and implement the\n" - "methods to get something useful."; - -PyTypeObject PyAcquireProgress_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.AcquireProgress", // tp_name - sizeof(PyAcquireProgressObject), // tp_basicsize - 0, // tp_itemsize - // Methods - 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 - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE, - acquireprogress_doc, // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - acquireprogress_methods, // tp_methods - acquireprogress_members, // 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 - PyType_GenericNew, // tp_new -}; diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index d53f64a6..faea423f 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -653,10 +653,7 @@ extern "C" void initapt_pkg() ADDTYPE(Module,"HashString",&PyHashString_Type); ADDTYPE(Module,"Policy",&PyPolicy_Type); ADDTYPE(Module,"Hashes",&PyHashes_Type); - ADDTYPE(Module,"OpProgress",&PyOpProgress_Type); - ADDTYPE(Module,"AcquireProgress",&PyAcquireProgress_Type); ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type); - ADDTYPE(Module,"CdromProgress",&PyCdromProgress_Type); ADDTYPE(Module,"SystemLock",&PySystemLock_Type); ADDTYPE(Module,"FileLock",&PyFileLock_Type); // Tag file constants diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 3edba5d2..97ba05a7 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -117,9 +117,6 @@ extern PyTypeObject PyIndexRecords_Type; // Policy extern PyTypeObject PyPolicy_Type; extern PyTypeObject PyHashes_Type; -extern PyTypeObject PyOpProgress_Type; -extern PyTypeObject PyAcquireProgress_Type; -extern PyTypeObject PyCdromProgress_Type; extern PyTypeObject PyAcquireItemDesc_Type; extern PyTypeObject PyAcquireWorker_Type; extern PyTypeObject PySystemLock_Type; diff --git a/python/cache.cc b/python/cache.cc index 68ee7b9e..593bc1c2 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -246,15 +246,9 @@ static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) PyObject *pyCallbackInst = 0; char *kwlist[] = {"progress", 0}; - #ifdef COMPAT_0_7 if (PyArg_ParseTupleAndKeywords(Args, kwds, "|O", kwlist, &pyCallbackInst) == 0) return 0; - #else - if (PyArg_ParseTupleAndKeywords(Args, kwds, "|O!", kwlist, - &PyOpProgress_Type, &pyCallbackInst) == 0) - return 0; - #endif if (_system == 0) { PyErr_SetString(PyExc_ValueError,"_system not initialized"); diff --git a/python/cdrom.cc b/python/cdrom.cc index 2270b01c..4195c9cb 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -57,8 +57,7 @@ static PyObject *cdrom_ident(PyObject *Self,PyObject *Args) { pkgCdrom &Cdrom = GetCpp(Self); PyObject *pyCdromProgressInst = 0; - if (PyArg_ParseTuple(Args, "O!", &PyCdromProgress_Type, - &pyCdromProgressInst) == 0) { + if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) { return 0; } diff --git a/python/cdromprogress.cc b/python/cdromprogress.cc deleted file mode 100644 index 440b5ce6..00000000 --- a/python/cdromprogress.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* cdromprogress.cc - Base class for CdromProgress classes. - * - * Copyright 2009 Julian Andres Klode - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#include "apt_pkgmodule.h" -#include "progress.h" -#include -#include - -// Takes two arguments (string, int) -static PyObject *cdromprogress_update(PyObject *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -// Takes no arguments -static PyObject *cdromprogress_change_cdrom(PyObject *self, PyObject *args) -{ - Py_RETURN_FALSE; -} - -// Takes a single PyObject argument as *arg -static PyObject *cdromprogress_ask_cdrom_name(PyObject *self, PyObject *arg) -{ - Py_RETURN_NONE; -} - -static PyMethodDef cdromprogress_methods[] = { - {"update",cdromprogress_update,METH_VARARGS, - "update(text: str, current: int)\n\nCalled regularly."}, - {"change_cdrom",cdromprogress_change_cdrom,METH_NOARGS, - "change_cdrom() -> bool\n\nAsk for the CD-ROM to be changed.\n" - "Return False if the user requested to cancel the action (default)."}, - {"ask_cdrom_name",cdromprogress_ask_cdrom_name,METH_O, - "ask_cdrom_name() -> str\n\nAsk for the name of the CD-ROM.\n" - "Return None if the user requested to cancel the action (default)."}, - {NULL} -}; - -static PyMemberDef cdromprogress_members[] = { - {"total_steps", T_INT, offsetof(PyCdromProgressObject,total_steps), 0, - "The number of total steps to be taken."}, - {NULL} -}; - -static char *cdromprogress_doc = "CdromProgress()\n\n" - "Base class for reporting the progress of adding a cdrom. Can be used\n" - "with apt_pkg.Cdrom to produce an utility like apt-cdrom."; - -PyTypeObject PyCdromProgress_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.CdromProgress", // tp_name - sizeof(PyCdromProgressObject), // tp_basicsize - 0, // tp_itemsize - // Methods - 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 - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE, - cdromprogress_doc, // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - cdromprogress_methods, // tp_methods - cdromprogress_members, // 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 - PyType_GenericNew, // tp_new -}; diff --git a/python/opprogress.cc b/python/opprogress.cc deleted file mode 100644 index 2ee6a03e..00000000 --- a/python/opprogress.cc +++ /dev/null @@ -1,175 +0,0 @@ -/* op-progress.cc - Base class for OpProgress classes. - * - * Copyright 2009 Julian Andres Klode - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include "generic.h" -#include "progress.h" -#include -#include - - - -static PyObject *opprogress_update(PyObject *Self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyObject *opprogress_done(PyObject *Self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyObject *opprogress_get_op(PyOpProgressObject *self, void *closure) -{ - Py_INCREF(self->op); - return self->op; -} - -static int opprogress_set_op(PyOpProgressObject *self, PyObject *value, - void *closure) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "Cannot delete 'op'"); - return -1; - } - if (!PyString_Check(value)) { - PyErr_SetString(PyExc_TypeError,"'op' must be a string."); - return -1; - } - Py_DECREF(self->op); - Py_INCREF(value); - - self->op = value; - return 0; -} - -static PyObject *opprogress_get_subop(PyOpProgressObject *self, void *closure) -{ - Py_INCREF(self->subop); - return self->subop; -} - -static int opprogress_set_subop(PyOpProgressObject *self, PyObject *value, - void *closure) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "Cannot delete 'subop'."); - return -1; - } - if (!PyString_Check(value)) { - PyErr_SetString(PyExc_TypeError,"'subop' must be a string."); - return -1; - } - Py_DECREF(self->subop); - Py_INCREF(value); - self->subop = value; - return 0; -} - -static PyMethodDef opprogress_methods[] = { - {"update",opprogress_update,METH_NOARGS,"update()\n\nCalled periodically."}, - {"done",opprogress_done,METH_NOARGS,"update()\n\nCalled when done."}, - {NULL}, -}; - -#ifndef T_BOOL -# define _T_BOOL T_INT -#else -# define _T_BOOL T_BOOL -#endif -static PyMemberDef opprogress_members[] = { - {"major_change", _T_BOOL, offsetof(PyOpProgressObject, major_change), 0, - "Boolean value indicating whether the change is a major change."}, - {"percent", T_FLOAT, offsetof(PyOpProgressObject, percent), 0, - "Percentage of completion (float value)."}, - {NULL} -}; - -static PyGetSetDef opprogress_getset[] = { - {"op", (getter)opprogress_get_op, (setter)opprogress_set_op, - "Description of the current operation"}, - {"subop", (getter)opprogress_get_subop, (setter)opprogress_set_subop, - "Description of the current sub-operation"}, - {NULL}, -}; - -static void opprogress_dealloc(PyObject *self) -{ - Py_XDECREF(((PyOpProgressObject *)self)->op); - Py_XDECREF(((PyOpProgressObject *)self)->subop); - self->ob_type->tp_free(self); -} - -static PyObject *opprogress_new(PyTypeObject *type, PyObject *args, - PyObject *kwds) -{ - PyOpProgressObject *res = (PyOpProgressObject *)type->tp_alloc(type, 0); - res->op = PyString_FromString(""); - res->subop = PyString_FromString(""); - return (PyObject *)res; -} - -static char *opprogress_doc = "OpProgress()\n\n" - "A base class for writing custom operation progress classes. Subclasses\n" - "should override all the methods (and call the parent ones) but shall\n" - "not override any of the inherited descriptors because they may be\n" - "ignored."; - -PyTypeObject PyOpProgress_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.OpProgress", // tp_name - sizeof(PyOpProgressObject), // tp_basicsize - 0, // tp_itemsize - // Methods - opprogress_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 | // tp_flags - Py_TPFLAGS_BASETYPE, - opprogress_doc, // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - opprogress_methods, // tp_methods - opprogress_members, // tp_members - opprogress_getset, // 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 - opprogress_new, // tp_new -}; diff --git a/python/progress.h b/python/progress.h index bc1bd640..80cb2785 100644 --- a/python/progress.h +++ b/python/progress.h @@ -32,38 +32,6 @@ #define PyCbObj_BLOCK_THREADS Py_BLOCK_THREADS #define PyCbObj_UNBLOCK_THREADS Py_UNBLOCK_THREADS -typedef struct { - PyObject_HEAD - PyObject *op; - PyObject *subop; -#ifdef T_BOOL - char major_change; -#else - int major_change; -#endif - float percent; -} PyOpProgressObject; - - -typedef struct { - PyObject_HEAD - int total_steps; -} PyCdromProgressObject; - -typedef struct { - PyObject_HEAD - double last_bytes; - double current_cps; - double current_bytes; - double total_bytes; - double fetched_bytes; - unsigned long elapsed_time; - unsigned long total_items; - unsigned long current_items; -} PyAcquireProgressObject; - - - class PyCallbackObj { protected: PyObject *callbackInst; diff --git a/setup.py b/setup.py index 93fcb436..9b33ed5d 100644 --- a/setup.py +++ b/setup.py @@ -35,9 +35,8 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'opprogress.cc', 'acquireprogress.cc', 'cdromprogress.cc', 'lock.cc', - 'acquire-item.cc'] -files = sorted(['python/' + fname for fname in files]) + 'lock.cc', 'acquire-item.cc'] +files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -- cgit v1.2.3 From e526904d0440e720cbeebf895faf884717f3fbb3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 7 Aug 2009 17:47:25 +0200 Subject: python/arfile.cc: Introduce apt_inst.ArArchive and apt_inst.ArMember. This is part one of wishlist Bug#536096, introducing classes in apt_inst. --- python/apt_instmodule.cc | 31 ++++- python/apt_instmodule.h | 4 + python/arfile.cc | 323 +++++++++++++++++++++++++++++++++++++++++++++++ python/generic.h | 1 + setup.py | 3 +- 5 files changed, 354 insertions(+), 8 deletions(-) create mode 100644 python/arfile.cc (limited to 'setup.py') diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index 5aca4e00..aedccb47 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -169,11 +169,22 @@ static PyMethodDef methods[] = {} }; + +static const char *apt_inst_doc = + "Functions for working with AR,tar archives and .deb packages.\n\n" + "This module provides useful classes and functions to work with\n" + "archives, modelled after the 'TarFile' class in the 'tarfile' module."; +#define ADDTYPE(mod,name,type) { \ + if (PyType_Ready(type) == -1) RETURN(0); \ + Py_INCREF(type); \ + PyModule_AddObject(mod,name,(PyObject *)type); } + + #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "apt_inst", - "Functions for working with packages and ar,tar archives (apt-inst)", + apt_inst_doc, -1, methods, 0, @@ -181,14 +192,20 @@ static struct PyModuleDef moduledef = { 0, 0 }; - +#define RETURN(x) return x extern "C" PyObject * PyInit_apt_inst() -{ - return PyModule_Create(&moduledef); -} #else extern "C" void initapt_inst() +#define RETURN(x) +#endif { - Py_InitModule("apt_inst",methods); +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); +#else + PyObject *module = Py_InitModule3("apt_inst",methods, apt_inst_doc); +#endif + + ADDTYPE(module,"ArMember",&PyArMember_Type); + ADDTYPE(module,"ArArchive",&PyArArchive_Type); + RETURN(module); } -#endif /*}}}*/ diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index 45ba5f85..e06e344d 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -17,4 +17,8 @@ extern char *doc_debExtract; PyObject *tarExtract(PyObject *Self,PyObject *Args); extern char *doc_tarExtract; + +extern PyTypeObject PyArMember_Type; +extern PyTypeObject PyArArchive_Type; + #endif diff --git a/python/arfile.cc b/python/arfile.cc new file mode 100644 index 00000000..368fb17c --- /dev/null +++ b/python/arfile.cc @@ -0,0 +1,323 @@ +/* + * arfile.cc - Wrapper around ARArchive and ARArchive::Member. + * + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include "generic.h" +#include +#include + +PyObject *armember_get_name(PyObject *self, void *closure) +{ + return CppPyString(GetCpp(self)->Name); +} + +PyObject *armember_get_mtime(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->MTime); +} + +PyObject *armember_get_uid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->UID); +} + +PyObject *armember_get_gid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->GID); +} + +PyObject *armember_get_mode(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Mode); +} + +PyObject *armember_get_size(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Size); +} + +PyObject *armember_get_start(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Start); +} + +PyGetSetDef armember_getset[] = { + {"gid",armember_get_gid,0,"The group id of the owner."}, + {"mode",armember_get_mode,0,"The mode of the file."}, + {"mtime",armember_get_mtime,0,"Last time of modification."}, + {"name",armember_get_name,0,"The name of the file."}, + {"size",armember_get_size,0,"The size of the files."}, + {"start",armember_get_start,0, + "The offset in the archive where the file starts."}, + {"uid",armember_get_uid,0,"The user id of the owner."}, + {NULL} +}; + +static const char *armember_doc = + "An ArMember object represents a single file within an AR archive. For\n" + "Debian packages this can be e.g. control.tar.gz. This class provides\n" + "information about this file, such as the mode and size."; +PyTypeObject PyArMember_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.ArMember", // tp_name + sizeof(CppOwnedPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDeallocPtr, // 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 | // tp_flags + Py_TPFLAGS_HAVE_GC, + armember_doc, // tp_doc + CppOwnedTraverse,// tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + armember_getset, // tp_getset +}; + +struct PyArArchiveObject : public CppOwnedPyObject { + FileFd Fd; +}; + +static const char *ararchive_getmember_doc = + "getmember(name: str) -> ArMember\n\n" + "Return a ArMember object for the member given by name. Raise\n" + "LookupError if there is no ArMember with the given name."; +PyObject *ararchive_getmember(PyArArchiveObject *self, PyObject *arg) +{ + const char *name; + CppOwnedPyObject *ret; + if (! (name = PyObject_AsString(arg))) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + // Create our object. + ret = CppOwnedPyObject_NEW(self,&PyArMember_Type); + ret->Object = const_cast(member); + ret->NoDelete = true; + return ret; +} + +static const char *ararchive_getdata_doc = + "getdata(name: str) -> bytes\n\n" + "Return the contents of the member, as a bytes object. Raise\n" + "LookupError if there is no ArMember with the given name."; +PyObject *ararchive_getdata(PyArArchiveObject *self, PyObject *args) +{ + char *name = 0; + if (PyArg_ParseTuple(args, "s:getdata", &name) == 0) + return 0; + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + char* value = new char[member->Size]; + self->Fd.Read(value, member->Size, true); + PyObject *result = PyBytes_FromStringAndSize(value, member->Size); + delete[] value; + return result; +} + +static const char *ararchive_extract_doc = + "extract(name: str[, target: str]) -> bool\n\n" + "Extract the member given by name into the directory given by target.\n" + "If the extraction failed, an error is raised. Otherwise, the method\n" + "returns True if the owner could be set or False if the owner could not\n" + "be changed. It may also raise LookupError if there is member with\n" + "the given name."; +PyObject *ararchive_extract(PyArArchiveObject *self, PyObject *args) +{ + char *name = 0; + char *target = ""; + if (PyArg_ParseTuple(args, "s|s:extract", &name, &target) == 0) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + // Open the target file + FileFd outfd(flCombine(target,name), FileFd::WriteAny, member->Mode); + if (_error->PendingError() == true) + return HandleErrors(); + + // Temporary buffer. We should probably split this into smaller parts. + char* value = new char[member->Size]; + + // Read into the buffer + if (!self->Fd.Read(value, member->Size, true)) { + delete[] value; + return HandleErrors(); + } + if (!outfd.Write(value, member->Size)) { + delete[] value; + return HandleErrors(); + } + if (fchown(outfd.Fd(), member->UID, member->GID) == -1) { + delete[] value; + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; +} + +PyMethodDef ararchive_methods[] = { + {"getmember",(PyCFunction)ararchive_getmember,METH_O, + ararchive_getmember_doc}, + {"getdata",(PyCFunction)ararchive_getdata,METH_VARARGS, + ararchive_getdata_doc}, + {"extract",(PyCFunction)ararchive_extract,METH_VARARGS, + ararchive_extract_doc}, + {NULL} +}; + +PyObject *ararchive_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *file; + PyArArchiveObject *self; + char *filename = 0; + int fileno; + if (PyArg_ParseTuple(args,"O:__new__",&file) == 0) + return 0; + + // We receive a filename. + if ((filename = (char*)PyObject_AsString(file))) { + self = (PyArArchiveObject *)CppOwnedPyObject_NEW(0,type); + new (&self->Fd) FileFd(filename,FileFd::ReadOnly); + } + // We receive a file object. + else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) { + // Clear the error set by PyObject_AsString(). + PyErr_Clear(); + self = (PyArArchiveObject *)CppOwnedPyObject_NEW(file,type); + new (&self->Fd) FileFd(fileno,false); + } + else { + return 0; + } + self->Object = new ARArchive(self->Fd); + if (_error->PendingError() == true) + return HandleErrors(); + return self; +} + +static void ararchive_dealloc(PyObject *self) { + ((PyArArchiveObject *)(self))->Fd.~FileFd(); + CppOwnedDeallocPtr(self); +} + +// Return bool or -1 (exception). +static int ararchive_contains(PyObject *self, PyObject *arg) +{ + const char *name = PyObject_AsString(arg); + if (!name) + return -1; + return (GetCpp(self)->FindMember(name) != 0); +} + +static PySequenceMethods ararchive_as_sequence = + {0,0,0,0,0,0,0,ararchive_contains,0,0}; + +static PyMappingMethods ararchive_as_mapping = + {0,(PyCFunction)ararchive_getmember,0}; + +static const char *ararchive_doc = + "ArArchive(file: str/int/file)\n\n" + "An ArArchive object represents an archive in the 4.4 BSD AR format, \n" + "which is used for e.g. deb packages.\n\n" + "The parameter 'file' may be a string specifying the path of a file, or\n" + "a file-like object providing the fileno() method. It may also be an int\n" + "specifying a file descriptor (returned by e.g. os.open()).\n" + "The recommended way is to pass in the path to the file."; + +PyTypeObject PyArArchive_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.ArArchive", // tp_name + sizeof(PyArArchiveObject), // tp_basicsize + 0, // tp_itemsize + // Methods + ararchive_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &ararchive_as_sequence, // tp_as_sequence + &ararchive_as_mapping, // 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 | // tp_flags + Py_TPFLAGS_HAVE_GC, + ararchive_doc, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + ararchive_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 + ararchive_new // tp_new +}; diff --git a/python/generic.h b/python/generic.h index 75520914..d5d6e9fb 100644 --- a/python/generic.h +++ b/python/generic.h @@ -66,6 +66,7 @@ typedef int Py_ssize_t; #define PyBytes_AS_STRING PyString_AS_STRING #define PyBytes_AsString PyString_AsString #define PyBytes_AsStringAndSize PyString_AsStringAndSize +#define PyBytes_FromStringAndSize PyString_FromStringAndSize #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, #endif #endif diff --git a/setup.py b/setup.py index 9b33ed5d..4eb6987e 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,8 @@ files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module -files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc"] +files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc", + "python/arfile.cc"] apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -- cgit v1.2.3 From 31d95030344c77d97d3245515a861a73732d0c5c Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sat, 8 Aug 2009 18:57:34 +0200 Subject: python/tarfile.cc: Introduce wrapper around ExtractTar. --- python/apt_instmodule.cc | 2 + python/apt_instmodule.h | 9 ++ python/tarfile.cc | 412 +++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 python/tarfile.cc (limited to 'setup.py') diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index aedccb47..3baaf985 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -207,5 +207,7 @@ extern "C" void initapt_inst() ADDTYPE(module,"ArMember",&PyArMember_Type); ADDTYPE(module,"ArArchive",&PyArArchive_Type); + ADDTYPE(module,"TarFile",&PyTarFile_Type); + ADDTYPE(module,"TarMember",&PyTarMember_Type); RETURN(module); } diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index e06e344d..94ada0f8 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -11,6 +11,8 @@ #define APT_INSTMODULE_H #include +#include "generic.h" +#include PyObject *debExtract(PyObject *Self,PyObject *Args); extern char *doc_debExtract; @@ -20,5 +22,12 @@ extern char *doc_tarExtract; extern PyTypeObject PyArMember_Type; extern PyTypeObject PyArArchive_Type; +extern PyTypeObject PyTarFile_Type; +extern PyTypeObject PyTarMember_Type; + +struct PyTarFileObject : public CppOwnedPyObject { + int min; + FileFd Fd; +}; #endif diff --git a/python/tarfile.cc b/python/tarfile.cc new file mode 100644 index 00000000..f3e11d2b --- /dev/null +++ b/python/tarfile.cc @@ -0,0 +1,412 @@ +/* + * arfile.cc - Wrapper around ExtractTar which behaves like Python's tarfile. + * + * Copyright 2009 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "generic.h" +#include "apt_instmodule.h" +#include +#include +#include + +/** + * A subclass of pkgDirStream which calls a Python callback. + * + * This calls a Python callback in FinishedFile() with the Item as the first + * argument and the data as the second argument. + */ +class PyDirStream : public pkgDirStream +{ + +public: + PyObject *callback; + // Set to true if an error occured in the Python callback. + bool error; + // Place where the copy of the data is stored. + char *copy; + + virtual bool DoItem(Item &Itm,int &Fd); + virtual bool FinishedFile(Item &Itm,int Fd); + virtual bool Process(Item &Itm,const unsigned char *Data, + unsigned long Size,unsigned long Pos); + + PyDirStream(PyObject *callback) : callback(callback), error(false), copy(0) { + Py_INCREF(callback); + } + + virtual ~PyDirStream() { + Py_DECREF(callback); + delete[] copy; + } +}; + +bool PyDirStream::DoItem(Item &Itm, int &Fd) +{ + delete[] copy; + copy = new char[Itm.Size]; + Fd = -2; + return true; +} + +bool PyDirStream::Process(Item &Itm,const unsigned char *Data, + unsigned long Size,unsigned long Pos) +{ + memcpy(copy + Pos, Data,Size); + return true; +} + +bool PyDirStream::FinishedFile(Item &Itm,int Fd) +{ + PyObject *py_member = CppOwnedPyObject_NEW(0,&PyTarMember_Type,&Itm); + + ((CppOwnedPyObject*)py_member)->NoDelete = true; + PyObject *py_data = PyBytes_FromStringAndSize(copy, Itm.Size); + PyObject *result = PyObject_CallFunctionObjArgs(callback, py_member, + py_data, 0); + if (result == 0) + error = true; + return (result != 0); +} + +// The tarfile.TarInfo interface for our TarMember class. +static PyObject *tarmember_isblk(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::BlockDevice); +} +static PyObject *tarmember_ischr(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::CharDevice); +} +static PyObject *tarmember_isdev(PyObject *self, PyObject *args) +{ + pkgDirStream::Item::Type_t type = GetCpp(self)->Type; + return PyBool_FromLong(type == pkgDirStream::Item::CharDevice || + type == pkgDirStream::Item::BlockDevice || + type == pkgDirStream::Item::FIFO); +} + +static PyObject *tarmember_isdir(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::Directory); +} + +static PyObject *tarmember_isfifo(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::FIFO); +} + +static PyObject *tarmember_isfile(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::File); +} +static PyObject *tarmember_islnk(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::HardLink); +} +static PyObject *tarmember_isreg(PyObject *self, PyObject *args) +{ + return tarmember_isfile(self, NULL); +} +static PyObject *tarmember_issym(PyObject *self, PyObject *args) +{ + return PyBool_FromLong(GetCpp(self)->Type == + pkgDirStream::Item::SymbolicLink); +} + +static PyObject *tarmember_get_name(PyObject *self, void *closure) +{ + return PyString_FromString(GetCpp(self)->Name); +} + +static PyObject *tarmember_get_linkname(PyObject *self, void *closure) +{ + return Safe_FromString(GetCpp(self)->LinkTarget); +} + +static PyObject *tarmember_get_mode(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Mode); +} + +static PyObject *tarmember_get_uid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->UID); +} +static PyObject *tarmember_get_gid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->GID); +} +static PyObject *tarmember_get_size(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Size); +} + +static PyObject *tarmember_get_mtime(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->MTime); +} + +static PyObject *tarmember_get_major(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Major); +} + +static PyObject *tarmember_get_minor(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp(self)->Minor); +} + +static PyObject *tarmember_repr(PyObject *self) +{ + return PyString_FromFormat("<%s object: name:'%s'>", + self->ob_type->tp_name, + GetCpp(self)->Name); + +} + + +static PyMethodDef tarmember_methods[] = { + {"isblk",tarmember_isblk,METH_NOARGS, + "Determine whether the member is a block device."}, + {"ischr",tarmember_ischr,METH_NOARGS, + "Determine whether the member is a character device."}, + {"isdev",tarmember_isdev,METH_NOARGS, + "Determine whether the member is a device (block,character or FIFO)."}, + {"isdir",tarmember_isdir,METH_NOARGS, + "Determine whether the member is a directory."}, + {"isfifo",tarmember_isfifo,METH_NOARGS, + "Determine whether the member is a FIFO."}, + {"isfile",tarmember_isfile,METH_NOARGS, + "Determine whether the member is a regular file."}, + {"islnk",tarmember_islnk,METH_NOARGS, + "Determine whether the member is a hardlink."}, + {"isreg",tarmember_isreg,METH_NOARGS, + "Determine whether the member is a regular file, same as isfile()."}, + {"issym",tarmember_issym,METH_NOARGS, + "Determine whether the member is a symbolic link."}, + {NULL} +}; + +static PyGetSetDef tarmember_getset[] = { + {"gid",tarmember_get_gid,0,"The owner's group id"}, + {"linkname",tarmember_get_linkname,0,"The target of the link."}, + {"major",tarmember_get_major,0,"The major ID of the device."}, + {"minor",tarmember_get_minor,0,"The minor ID of the device."}, + {"mode",tarmember_get_mode,0,"The mode (permissions)."}, + {"mtime",tarmember_get_mtime,0,"Last time of modification."}, + {"name",tarmember_get_name,0,"The name of the file."}, + {"size",tarmember_get_size,0,"The size of the file."}, + {"uid",tarmember_get_uid,0,"The owner's user id."}, + {NULL} +}; + +static const char *tarmember_doc = + "Represent a single member of a 'tar' archive.\n\n" + "This class, which has been modelled after 'tarfile.TarInfo', represents\n" + "information about a given member in an archive."; +PyTypeObject PyTarMember_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.TarMember", // tp_name + sizeof(CppOwnedPyObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + tarmember_repr, // 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 | // tp_flags + Py_TPFLAGS_HAVE_GC, + tarmember_doc, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + tarmember_methods, // tp_methods + 0, // tp_members + tarmember_getset // tp_getset +}; + + + +static PyObject *tarfile_new(PyTypeObject *type,PyObject *args,PyObject *kwds) +{ + PyObject *file; + PyTarFileObject *self; + char *filename; + int fileno; + int min = 0; + int max = 0xFFFFFFFF; + char *comp = "gzip"; + + static char *kwlist[] = {"file","min","max","comp",NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "O|iis", kwlist, &file, &min, + &max,&comp) == 0) + return 0; + + self = (PyTarFileObject*)CppOwnedPyObject_NEW(file,type); + + // We receive a filename. + if ((filename = (char*)PyObject_AsString(file))) + new (&self->Fd) FileFd(filename,FileFd::ReadOnly); + else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) { + // clear the error set by PyObject_AsString(). + PyErr_Clear(); + new (&self->Fd) FileFd(fileno,false); + } + else { + Py_DECREF(self); + return 0; + } + + self->min = min; + self->Object = new ExtractTar(self->Fd,max,comp); + if (_error->PendingError() == true) + return HandleErrors(self); + return self; +} + +static const char *tarfile_extractall_doc = + "extractall([rootdir: str]) -> True\n\n" + "Extract the archive in the current directory. The argument 'rootdir'\n" + "can be used to change the target directory."; +static PyObject *tarfile_extractall(PyObject *self, PyObject *args) +{ + string cwd = SafeGetCWD(); + char *rootdir = 0; + if (PyArg_ParseTuple(args,"|s:extractall",&rootdir) == 0) + return 0; + + if (rootdir) { + if (chdir(rootdir) == -1) + return PyErr_SetFromErrnoWithFilename(PyExc_OSError, rootdir); + } + + pkgDirStream Extract; + + ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min); + bool res = GetCpp(self)->Go(Extract); + + + + if (rootdir) { + if (chdir(cwd.c_str()) == -1) + return PyErr_SetFromErrnoWithFilename(PyExc_OSError, + (char*)cwd.c_str()); + } + return HandleErrors(PyBool_FromLong(res)); +} + +static const char *tarfile_go_doc = + "go(callback: callable) -> True\n\n" + "Go through the archive and call the callable callback for each\n" + "member with 2 arguments. The first argument is the TarMember and\n" + "the second one is the data, as bytes."; +static PyObject *tarfile_go(PyObject *self, PyObject *arg) +{ + pkgDirStream Extract; + PyDirStream stream(arg); + ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min); + bool res = GetCpp(self)->Go(stream); + if (stream.error) + return 0; + return HandleErrors(PyBool_FromLong(res)); +} + +static PyMethodDef tarfile_methods[] = { + {"extractall",tarfile_extractall,METH_VARARGS,tarfile_extractall_doc}, + {"go",tarfile_go,METH_O,tarfile_go_doc}, + {NULL} +}; + +static PyObject *tarfile_repr(PyObject *self) +{ + return PyString_FromFormat("<%s object: %s>", self->ob_type->tp_name, + PyString_AsString(PyObject_Repr(GetOwner(self)))); +} + +static const char *tarfile_doc = + "TarFile(file: str/int/file[, min: int, max: int, comp: str])\n\n" + "The parameter 'file' may be a string specifying the path of a file, or\n" + "a file-like object providing the fileno() method. It may also be an int\n" + "specifying a file descriptor (returned by e.g. os.open()).\n\n" + "The parameter 'min' describes the offset in the file where the archive\n" + "begins and the parameter 'max' is the size of the archive.\n\n" + "The compression of the archive is set by the parameter 'comp'. It can\n" + "be set to any program supporting the -d switch, the default being gzip."; +PyTypeObject PyTarFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_inst.TarFile", // tp_name + sizeof(PyTarFileObject), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + tarfile_repr, // 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 | // tp_flags + Py_TPFLAGS_HAVE_GC, + tarfile_doc, // tp_doc + CppOwnedTraverse, // tp_traverse + CppOwnedClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + tarfile_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 + tarfile_new // tp_new +}; diff --git a/setup.py b/setup.py index 4eb6987e..635fee9b 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) # The apt_inst module files = ["python/apt_instmodule.cc", "python/generic.cc", "python/tar.cc", - "python/arfile.cc"] + "python/arfile.cc", "python/tarfile.cc"] apt_inst = Extension("apt_inst", files, libraries=["apt-pkg", "apt-inst"]) # Replace the leading _ that is used in the templates for translation -- cgit v1.2.3 From b2a1af65654e4584d6b54c5d4e12175ff0dffad9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 2 Feb 2010 17:19:25 +0100 Subject: Remove inline functions from the C++ API, export them instead (part 2). --- python/acquire.cc | 2 +- python/apt_pkgmodule.cc | 36 +++++++++++-- python/apt_pkgmodule.h | 42 ++++++++++++++- python/configuration.cc | 8 +-- python/generic.cc | 2 + python/indexrecords.cc | 2 +- python/python-apt-helpers.cc | 68 ++++++++++++++++++++++++ python/python-apt.h | 124 +++++++++++++++++++++++-------------------- setup.py | 2 +- 9 files changed, 217 insertions(+), 69 deletions(-) create mode 100644 python/python-apt-helpers.cc (limited to 'setup.py') diff --git a/python/acquire.cc b/python/acquire.cc index cd7f7709..04e00b02 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -255,7 +255,7 @@ static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure) { PyObject *List = PyList_New(0); pkgAcquire *Owner = GetCpp(self); - CppPyObject *PyWorker = NULL; + PyObject *PyWorker = NULL; for (pkgAcquire::Worker *Worker = Owner->WorkersBegin(); Worker != 0; Worker = Owner->WorkerStep(Worker)) { PyWorker = PyAcquireWorker_FromCpp(Worker, false, self); diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index d2472395..e3da1820 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -529,64 +529,94 @@ static struct _PyAptPkgAPIStruct API = { &PyAcquire_FromCpp, // acquire_fromcpp &PyAcquire_ToCpp, // acquire_tocpp &PyAcquireFile_Type, // acquirefile_type + &PyAcquireFile_FromCpp, // acquirefile_fromcpp &PyAcquireFile_ToCpp, // acquirefile_tocpp &PyAcquireItem_Type, // acquireitem_type + &PyAcquireItem_FromCpp, // acquireitem_fromcpp &PyAcquireItem_ToCpp, // acquireitem_type &PyAcquireItemDesc_Type, // acquireitemdesc_type + &PyAcquireItemDesc_FromCpp,// acquireitemdesc_fromcpp &PyAcquireItemDesc_ToCpp, // acquireitemdesc_tocpp &PyAcquireWorker_Type, // acquireworker_type + &PyAcquireWorker_FromCpp, // acquireworker_fromcpp &PyAcquireWorker_ToCpp, // acquireworker_tocpp &PyActionGroup_Type, // actiongroup_type - &PyActionGroup_ToCpp, // actiongroup_type + &PyActionGroup_FromCpp, // actiongroup_fromcpp + &PyActionGroup_ToCpp, // actiongroup_tocpp &PyCache_Type, // cache_type + &PyCache_FromCpp, // cache_fromcpp &PyCache_ToCpp, // cache_tocpp &PyCacheFile_Type, // cachefile_type + &PyCacheFile_FromCpp, // cachefile_fromcpp &PyCacheFile_ToCpp, // cachefile_tocpp &PyCdrom_Type, // cdrom_type + &PyCdrom_FromCpp, // cdrom_fromcpp &PyCdrom_ToCpp, // cdrom_tocpp &PyConfiguration_Type, // configuration_type + &PyConfiguration_FromCpp, // configuration_fromcpp &PyConfiguration_ToCpp, // configuration_tocpp &PyDepCache_Type, // depcache_type + &PyDepCache_FromCpp, // depcache_fromcpp &PyDepCache_ToCpp, // depcache_tocpp &PyDependency_Type, // dependency_type - &PyDependency_ToCpp, // dependency_type + &PyDependency_FromCpp, // dependency_fromcpp + &PyDependency_ToCpp, // dependency_tocpp &PyDependencyList_Type, // dependencylist_type + 0, // FIXME: dependencylist_fromcpp 0, // FIXME: dependencylist_tocpp &PyDescription_Type, // description_type + &PyDescription_FromCpp, // description_fromcpp &PyDescription_ToCpp, // description_tocpp &PyHashes_Type, // hashes_type + &PyHashes_FromCpp, // hashes_fromcpp &PyHashes_ToCpp, // hashes_tocpp &PyHashString_Type, // hashstring_type + &PyHashString_FromCpp, // hashstring_fromcpp &PyHashString_ToCpp, // hashstring_tocpp &PyIndexRecords_Type, // indexrecords_type + &PyIndexRecords_FromCpp, // indexrecords_tocpp &PyIndexRecords_ToCpp, // indexrecords_tocpp &PyMetaIndex_Type, // metaindex_type + &PyMetaIndex_FromCpp, // metaindex_tocpp &PyMetaIndex_ToCpp, // metaindex_tocpp &PyPackage_Type, // package_type + &PyPackage_FromCpp, // package_tocpp &PyPackage_ToCpp, // package_tocpp &PyPackageFile_Type, // packagefile_type + &PyPackageFile_FromCpp, // packagefile_tocpp &PyPackageFile_ToCpp, // packagefile_tocpp &PyIndexFile_Type, // packageindexfile_type + &PyIndexFile_FromCpp, // packageindexfile_tocpp &PyIndexFile_ToCpp, // packageindexfile_tocpp &PyPackageList_Type, // packagelist_type + 0, // FIXME: packagelist_fromcpp 0, // FIXME: packagelist_tocpp &PyPackageManager_Type, // packagemanager_type + &PyPackageManager_FromCpp, // packagemanager_type &PyPackageManager_ToCpp, // packagemanager_type &PyPackageRecords_Type, // packagerecords_type + 0, // FIXME: packagerecords_fromcpp 0, // FIXME: packagerecords_tocpp &PyPolicy_Type, // policy_type + &PyPolicy_FromCpp, // policy_tocpp &PyPolicy_ToCpp, // policy_tocpp &PyProblemResolver_Type, // problemresolver_type + &PyProblemResolver_FromCpp, // problemresolver_tocpp &PyProblemResolver_ToCpp, // problemresolver_tocpp &PySourceList_Type, // sourcelist_type + &PySourceList_FromCpp, // sourcelist_tocpp &PySourceList_ToCpp, // sourcelist_tocpp &PySourceRecords_Type, // sourcerecords_type - 0, // sourcerecords_tocpp + 0, // FIXME: sourcerecords_fromcpp + 0, // FIXME: sourcerecords_tocpp &PyTagFile_Type, // tagfile_type + &PyTagFile_FromCpp, // tagfile_tocpp &PyTagFile_ToCpp, // tagfile_tocpp &PyTagSection_Type, // tagsection_type + &PyTagSection_FromCpp, // tagsection_tocpp &PyTagSection_ToCpp, // tagsection_tocpp &PyVersion_Type, // version_type + &PyVersion_FromCpp, // version_tocpp &PyVersion_ToCpp, // version_tocpp }; diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index a22a25f0..3dcf8069 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -13,10 +13,20 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "generic.h" // Configuration Stuff -#define Configuration_Check(op) ((op)->ob_type == &PyConfiguration_Type) extern PyTypeObject PyConfiguration_Type; extern PyTypeObject PyVersion_Type; @@ -157,6 +167,36 @@ PyObject *PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete); # define PyTagSection_ToCpp GetCpp # define PyVersion_ToCpp GetCpp +PyObject* PyAcquireFile_FromCpp(pkgAcqFile* const &obj, bool Delete, PyObject *Owner); +PyObject* PyAcquireItem_FromCpp(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner); +PyObject* PyAcquireItemDesc_FromCpp(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner); +PyObject* PyAcquireWorker_FromCpp(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner); +PyObject* PyActionGroup_FromCpp(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner); +PyObject* PyCache_FromCpp(pkgCache* const &obj, bool Delete, PyObject *Owner); +PyObject* PyCacheFile_FromCpp(pkgCacheFile* const &obj, bool Delete, PyObject *Owner); +PyObject* PyCdrom_FromCpp(pkgCdrom const &obj, bool Delete, PyObject *Owner); +PyObject* PyConfiguration_FromCpp(Configuration* const &obj, bool Delete, PyObject *Owner); +PyObject* PyDepCache_FromCpp(pkgDepCache* const &obj, bool Delete, PyObject *Owner); +PyObject* PyDependency_FromCpp(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner); +//PyObject* PyDependencyList_FromCpp(RDepListStruct const &obj, bool Delete, PyObject *Owner); +PyObject* PyDescription_FromCpp(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner); +PyObject* PyHashes_FromCpp(Hashes const &obj, bool Delete, PyObject *Owner); +PyObject* PyHashString_FromCpp(HashString* const &obj, bool Delete, PyObject *Owner); +PyObject* PyIndexRecords_FromCpp(indexRecords* const &obj, bool Delete, PyObject *Owner); +PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owner); +PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner); +PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner); +PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner); +//PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner); +PyObject* PyPackageManager_FromCpp(pkgPackageManager* const &obj, bool Delete, PyObject *Owner); +//PyObject* PyPackageRecords_FromCpp(PkgRecordsStruct const &obj, bool Delete, PyObject *Owner); +PyObject* PyPolicy_FromCpp(pkgPolicy* const &obj, bool Delete, PyObject *Owner); +PyObject* PyProblemResolver_FromCpp(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner); +PyObject* PySourceList_FromCpp(pkgSourceList* const &obj, bool Delete, PyObject *Owner); +//PyObject* PySourceRecords_FromCpp(PkgSrcRecordsStruct const &obj, bool Delete, PyObject *Owner); +PyObject* PyTagFile_FromCpp(pkgTagFile const &obj, bool Delete, PyObject *Owner); +PyObject* PyTagSection_FromCpp(pkgTagSection const &obj, bool Delete, PyObject *Owner); +PyObject* PyVersion_FromCpp(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner); #include "python-apt.h" #endif diff --git a/python/configuration.cc b/python/configuration.cc index 0cad8db3..974f6f3d 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -280,7 +280,7 @@ PyObject *LoadConfig(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"Os",&Self,&Name) == 0) return 0; - if (Configuration_Check(Self)== 0) + if (PyConfiguration_Check(Self)== 0) { PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; @@ -298,7 +298,7 @@ PyObject *LoadConfigISC(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"Os",&Self,&Name) == 0) return 0; - if (Configuration_Check(Self)== 0) + if (PyConfiguration_Check(Self)== 0) { PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; @@ -316,7 +316,7 @@ PyObject *LoadConfigDir(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"Os",&Self,&Name) == 0) return 0; - if (Configuration_Check(Self)== 0) + if (PyConfiguration_Check(Self)== 0) { PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; @@ -348,7 +348,7 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) if (PyArg_ParseTuple(Args,"OO!O!",&Self, &PyList_Type,&POList,&PyList_Type,&Pargv) == 0) return 0; - if (Configuration_Check(Self)== 0) + if (PyConfiguration_Check(Self)== 0) { PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; diff --git a/python/generic.cc b/python/generic.cc index 51439a1b..640f0862 100644 --- a/python/generic.cc +++ b/python/generic.cc @@ -9,6 +9,8 @@ /*}}}*/ // Include Files /*{{{*/ #include "generic.h" +using namespace std; + #include /*}}}*/ diff --git a/python/indexrecords.cc b/python/indexrecords.cc index 5750bf6b..80960160 100644 --- a/python/indexrecords.cc +++ b/python/indexrecords.cc @@ -60,7 +60,7 @@ static PyObject *indexrecords_lookup(PyObject *self,PyObject *args) } // Copy the HashString(), to prevent crashes and to not require the // indexRecords object to exist. - PyObject *py_hash = PyHashString_FromCpp(new HashString(result->Hash)); + PyObject *py_hash = PyHashString_FromCpp(new HashString(result->Hash), true, NULL); PyObject *value = Py_BuildValue("(Oi)",py_hash,result->Size); Py_DECREF(py_hash); return value; diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc new file mode 100644 index 00000000..7a0f20c4 --- /dev/null +++ b/python/python-apt-helpers.cc @@ -0,0 +1,68 @@ +/* + * python-apt.h - Common object creation functions for the public API + * + * Copyright 2010 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "apt_pkgmodule.h" + +/** + * Short macro to be used for the generic FromCpp functions. + * + */ +#define NEW_FROM(NAME,TYPE,Cpp) \ +PyObject* NAME(Cpp const &obj, bool Delete, PyObject *Owner) \ +{ \ + CppPyObject *Obj = CppPyObject_NEW(Owner, TYPE, obj); \ + Obj->NoDelete = (!Delete); \ + return Obj; \ +} + +// Create all those functions +NEW_FROM(PyAcquireFile_FromCpp,&PyAcquireFile_Type,pkgAcqFile*) +NEW_FROM(PyAcquireItem_FromCpp,&PyAcquireItem_Type,pkgAcquire::Item*) +NEW_FROM(PyAcquireItemDesc_FromCpp,&PyAcquireItemDesc_Type,pkgAcquire::ItemDesc*) +NEW_FROM(PyAcquireWorker_FromCpp,&PyAcquireWorker_Type,pkgAcquire::Worker*) +NEW_FROM(PyActionGroup_FromCpp,&PyActionGroup_Type,pkgDepCache::ActionGroup*) +NEW_FROM(PyCache_FromCpp,&PyCache_Type,pkgCache*) +NEW_FROM(PyCacheFile_FromCpp,&PyCacheFile_Type,pkgCacheFile*) +NEW_FROM(PyCdrom_FromCpp,&PyCdrom_Type,pkgCdrom) +NEW_FROM(PyConfiguration_FromCpp,&PyConfiguration_Type,Configuration*) +NEW_FROM(PyDepCache_FromCpp,&PyDepCache_Type,pkgDepCache*) +NEW_FROM(PyDependency_FromCpp,&PyDependency_Type,pkgCache::DepIterator) +//NEW_FROM(PyDependencyList_FromCpp,&PyDependencyList_Type,RDepListStruct) +NEW_FROM(PyDescription_FromCpp,&PyDescription_Type,pkgCache::DescIterator) +NEW_FROM(PyHashes_FromCpp,&PyHashes_Type,Hashes) +NEW_FROM(PyHashString_FromCpp,&PyHashString_Type,HashString*) +NEW_FROM(PyIndexRecords_FromCpp,&PyIndexRecords_Type,indexRecords*) +NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*) +NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator) +NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*) +NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator) +//NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct) +NEW_FROM(PyPackageManager_FromCpp,&PyPackageManager_Type,pkgPackageManager*) +//NEW_FROM(PyPackageRecords_FromCpp,&PyPackageRecords_Type,PkgRecordsStruct) +NEW_FROM(PyPolicy_FromCpp,&PyPolicy_Type,pkgPolicy*) +NEW_FROM(PyProblemResolver_FromCpp,&PyProblemResolver_Type,pkgProblemResolver*) +NEW_FROM(PySourceList_FromCpp,&PySourceList_Type,pkgSourceList*) +//NEW_FROM(PySourceRecords_FromCpp,&PySourceRecords_Type,PkgSrcRecordsStruct) +NEW_FROM(PyTagFile_FromCpp,&PyTagFile_Type,pkgTagFile) +NEW_FROM(PyTagSection_FromCpp,&PyTagSection_Type,pkgTagSection) +NEW_FROM(PyVersion_FromCpp,&PyVersion_Type,pkgCache::VerIterator) + +#undef NEW_FROM diff --git a/python/python-apt.h b/python/python-apt.h index 7b34c249..0c25ff02 100644 --- a/python/python-apt.h +++ b/python/python-apt.h @@ -47,94 +47,126 @@ struct _PyAptPkgAPIStruct { pkgAcquire*& (*acquire_tocpp)(PyObject *self); // apt_pkg.AcquireFile PyTypeObject *acquirefile_type; + PyObject* (*acquirefile_fromcpp)(pkgAcqFile* const &obj, bool Delete, PyObject *Owner); pkgAcqFile*& (*acquirefile_tocpp)(PyObject *self); + // apt_pkg.AcquireItem PyTypeObject *acquireitem_type; + PyObject* (*acquireitem_fromcpp)(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner); pkgAcquire::Item*& (*acquireitem_tocpp)(PyObject *self); // apt_pkg.AcquireItemDesc PyTypeObject *acquireitemdesc_type; + PyObject* (*acquireitemdesc_fromcpp)(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner); pkgAcquire::ItemDesc*& (*acquireitemdesc_tocpp)(PyObject *self); PyTypeObject *acquireworker_type; + PyObject* (*acquireworker_fromcpp)(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner); pkgAcquire::Worker*& (*acquireworker_tocpp)(PyObject *self); PyTypeObject *actiongroup_type; + PyObject* (*actiongroup_fromcpp)(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner); pkgDepCache::ActionGroup*& (*actiongroup_tocpp)(PyObject *self); PyTypeObject *cache_type; + PyObject* (*cache_fromcpp)(pkgCache* const &obj, bool Delete, PyObject *Owner); pkgCache*& (*cache_tocpp)(PyObject *self); PyTypeObject *cachefile_type; + PyObject* (*cachefile_fromcpp)(pkgCacheFile* const &obj, bool Delete, PyObject *Owner); pkgCacheFile*& (*cachefile_tocpp)(PyObject *self); PyTypeObject *cdrom_type; + PyObject* (*cdrom_fromcpp)(pkgCdrom const &obj, bool Delete, PyObject *Owner); pkgCdrom& (*cdrom_tocpp)(PyObject *self); PyTypeObject *configuration_type; + PyObject* (*configuration_fromcpp)(Configuration* const &obj, bool Delete, PyObject *Owner); Configuration*& (*configuration_tocpp)(PyObject *self); PyTypeObject *depcache_type; + PyObject* (*depcache_fromcpp)(pkgDepCache* const &obj, bool Delete, PyObject *Owner); pkgDepCache*& (*depcache_tocpp)(PyObject *self); PyTypeObject *dependency_type; + PyObject* (*dependency_fromcpp)(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner); pkgCache::DepIterator& (*dependency_tocpp)(PyObject *self); PyTypeObject *dependencylist_type; - void *dependencylist_tocpp; // FIXME: need packagelist_tocpp + void *dependencylist_fromcpp; // FIXME: need dependencylist_fromcpp + void *dependencylist_tocpp; // FIXME: need dependencylist_tocpp PyTypeObject *description_type; + PyObject* (*description_fromcpp)(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner); pkgCache::DescIterator& (*description_tocpp)(PyObject *self); PyTypeObject *hashes_type; + PyObject* (*hashes_fromcpp)(Hashes const &obj, bool Delete, PyObject *Owner); Hashes& (*hashes_tocpp)(PyObject *self); PyTypeObject *hashstring_type; + PyObject* (*hashstring_fromcpp)(HashString* const &obj, bool Delete, PyObject *Owner); HashString*& (*hashstring_tocpp)(PyObject *self); PyTypeObject *indexrecords_type; + PyObject* (*indexrecords_fromcpp)(indexRecords* const &obj, bool Delete, PyObject *Owner); indexRecords*& (*indexrecords_tocpp)(PyObject *self); PyTypeObject *metaindex_type; + PyObject* (*metaindex_fromcpp)(metaIndex* const &obj, bool Delete, PyObject *Owner); metaIndex*& (*metaindex_tocpp)(PyObject *self); PyTypeObject *package_type; + PyObject* (*package_fromcpp)(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner); pkgCache::PkgIterator& (*package_tocpp)(PyObject *self); PyTypeObject *packagefile_type; + PyObject* (*packagefile_fromcpp)(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner); pkgCache::PkgFileIterator& (*packagefile_tocpp)(PyObject *self); PyTypeObject *packageindexfile_type; + PyObject* (*indexfile_fromcpp)(pkgIndexFile* const &obj, bool Delete, PyObject *Owner); pkgIndexFile*& (*packageindexfile_tocpp)(PyObject *self); PyTypeObject *packagelist_type; + void *packagelist_fromcpp; // FIXME: need packagelist_fromcpp void *packagelist_tocpp; // FIXME: need packagelist_tocpp PyTypeObject *packagemanager_type; + PyObject* (*packagemanager_fromcpp)(pkgPackageManager* const &obj, bool Delete, PyObject *Owner); pkgPackageManager*& (*packagemanager_tocpp)(PyObject *self); PyTypeObject *packagerecords_type; + void *packagerecords_fromcpp; // FIXME: need packagerecords_fromcpp void *packagerecords_tocpp; // FIXME: need packagerecords_tocpp PyTypeObject *policy_type; + PyObject* (*policy_fromcpp)(pkgPolicy* const &obj, bool Delete, PyObject *Owner); pkgPolicy*& (*policy_tocpp)(PyObject *self); PyTypeObject *problemresolver_type; + PyObject* (*problemresolver_fromcpp)(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner); pkgProblemResolver*& (*problemresolver_tocpp)(PyObject *self); PyTypeObject *sourcelist_type; + PyObject* (*sourcelist_fromcpp)(pkgSourceList* const &obj, bool Delete, PyObject *Owner); pkgSourceList*& (*sourcelist_tocpp)(PyObject *self); PyTypeObject *sourcerecords_type; + void *sourcerecords_fromcpp; // FIXME: need sourcerecords_fromcpp void *sourcerecords_tocpp; // FIXME: need sourcerecords_tocpp PyTypeObject *tagfile_type; + PyObject* (*tagfile_fromcpp)(pkgTagFile const &obj, bool Delete, PyObject *Owner); pkgTagFile& (*tagfile_tocpp)(PyObject *self); PyTypeObject *tagsection_type; + PyObject* (*tagsection_fromcpp)(pkgTagSection const &obj, bool Delete, PyObject *Owner); pkgTagSection& (*tagsection_tocpp)(PyObject *self); PyTypeObject *version_type; + PyObject* (*version_fromcpp)(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner); pkgCache::VerIterator& (*version_tocpp)(PyObject *self); + }; // Checking macros. @@ -208,24 +240,10 @@ static struct _PyAptPkgAPIStruct *_PyAptPkg_API; static int import_apt_pkg(void) { # if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCapsule_Import("apt_pkg._C_API", 0); - return (_PyAptPkg_API != NULL) ? 0 : -1; # else - - PyObject *module = PyImport_ImportModule("apt_pkg"); - - if (module == NULL) { - return -1; - } - if (module != NULL) { - PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API"); - if (c_api_object == NULL) - return -1; - if (PyCObject_Check(c_api_object)) - _PyAptPkg_API = (struct _PyAptPkgAPIStruct *)PyCObject_AsVoidPtr(c_api_object); - Py_DECREF(c_api_object); - } - return 0; + _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCObject_Import("apt_pkg", "_C_API"); # endif // PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 + return (_PyAptPkg_API != NULL) ? 0 : -1; } # define PyAcquire_Type *(_PyAptPkg_API->acquire_type) @@ -292,48 +310,38 @@ static int import_apt_pkg(void) { # define PyTagSection_ToCpp _PyAptPkg_API->tagsection_tocpp # define PyVersion_ToCpp _PyAptPkg_API->version_tocpp // Get the C++ object -# define PyAcquire_FromCpp _PyAptPkg_API->acquire_fromcpp +# define PyAcquire_FromCpp _PyAptPkg_API->acquire_fromcpp +# define PyAcquireFile_FromCpp _PyAptPkg_API->acquirefile_fromcpp +# define PyAcquireItem_FromCpp _PyAptPkg_API->acquireitem_fromcpp +# define PyAcquireItemDesc_FromCpp _PyAptPkg_API->acquireitemdesc_fromcpp +# define PyAcquireWorker_FromCpp _PyAptPkg_API->acquireworker_fromcpp +# define PyActionGroup_FromCpp _PyAptPkg_API->actiongroup_fromcpp +# define PyCache_FromCpp _PyAptPkg_API->cache_fromcpp +# define PyCacheFile_FromCpp _PyAptPkg_API->cachefile_fromcpp +# define PyCdrom_FromCpp _PyAptPkg_API->cdrom_fromcpp +# define PyConfiguration_FromCpp _PyAptPkg_API->configuration_fromcpp +# define PyDepCache_FromCpp _PyAptPkg_API->depcache_fromcpp +# define PyDependency_FromCpp _PyAptPkg_API->dependency_fromcpp +# define PyDependencyList_FromCpp _PyAptPkg_API->dependencylist_fromcpp // NULL +# define PyDescription_FromCpp _PyAptPkg_API->description_fromcpp +# define PyHashes_FromCpp _PyAptPkg_API->hashes_fromcpp +# define PyHashString_FromCpp _PyAptPkg_API->hashstring_fromcpp +# define PyIndexRecords_FromCpp _PyAptPkg_API->indexrecords_fromcpp +# define PyMetaIndex_FromCpp _PyAptPkg_API->metaindex_fromcpp +# define PyPackage_FromCpp _PyAptPkg_API->package_fromcpp +# define PyPackageFile_FromCpp _PyAptPkg_API->packagefile_fromcpp +# define PyIndexFile_FromCpp _PyAptPkg_API->packageindexfile_fromcpp +# define PyPackageList_FromCpp _PyAptPkg_API->packagelist_fromcpp // NULL +# define PyPackageManager_FromCpp _PyAptPkg_API->packagemanager_fromcpp +# define PyPackageRecords_FromCpp _PyAptPkg_API->packagerecords_fromcpp +# define PyPolicy_FromCpp _PyAptPkg_API->policy_fromcpp +# define PyProblemResolver_FromCpp _PyAptPkg_API->problemresolver_fromcpp +# define PySourceList_FromCpp _PyAptPkg_API->sourcelist_fromcpp +# define PySourceRecords_FromCpp _PyAptPkg_API->sourcerecords_fromcpp // NULL +# define PyTagFile_FromCpp _PyAptPkg_API->tagfile_fromcpp +# define PyTagSection_FromCpp _PyAptPkg_API->tagsection_fromcpp +# define PyVersion_FromCpp _PyAptPkg_API->version_fromcpp # endif // APT_PKGMODULE_H -// Template using a simpler version of from cpp -template -inline CppPyObject *FromCpp(PyTypeObject *pytype, Cpp const &obj, bool Delete=false, PyObject *Owner=NULL) -{ - CppPyObject *Obj = CppPyObject_NEW(Owner, pytype, obj); - Obj->NoDelete = (!Delete); - return Obj; -} - - -# define PyAcquireFile_FromCpp(...) FromCpp(&PyAcquireFile_Type, ##__VA_ARGS__) -# define PyAcquireItem_FromCpp(...) FromCpp(&PyAcquireItem_Type,##__VA_ARGS__) -# define PyAcquireItemDesc_FromCpp(...) FromCpp(&PyAcquireItemDesc_Type,##__VA_ARGS__) -# define PyAcquireWorker_FromCpp(...) FromCpp(&PyAcquireWorker_Type,##__VA_ARGS__) -# define PyActionGroup_FromCpp(...) FromCpp(&PyActionGroup_Type,##__VA_ARGS__) -# define PyCache_FromCpp(...) FromCpp(&PyCache_Type,##__VA_ARGS__) -# define PyCacheFile_FromCpp(...) FromCpp(&PyCacheFile_Type,##__VA_ARGS__) -# define PyCdrom_FromCpp(...) FromCpp(&PyCdrom_Type,##__VA_ARGS__) -# define PyConfiguration_FromCpp(...) FromCpp(&PyConfiguration_Type, ##__VA_ARGS__) -# define PyDepCache_FromCpp(...) FromCpp(&PyDepCache_Type,##__VA_ARGS__) -# define PyDependency_FromCpp(...) FromCpp(&PyDependency_Type,##__VA_ARGS__) -//# define PyDependencyList_FromCpp(...) FromCpp(&PyDependencyList_Type,##__VA_ARGS__) -# define PyDescription_FromCpp(...) FromCpp(&PyDescription_Type,##__VA_ARGS__) -# define PyHashes_FromCpp(...) FromCpp(&PyHashes_Type,##__VA_ARGS__) -# define PyHashString_FromCpp(...) FromCpp(&PyHashString_Type,##__VA_ARGS__) -# define PyIndexRecords_FromCpp(...) FromCpp(&PyIndexRecords_Type,##__VA_ARGS__) -# define PyMetaIndex_FromCpp(...) FromCpp(&PyMetaIndex_Type,##__VA_ARGS__) -# define PyPackage_FromCpp(...) FromCpp(&PyPackage_Type,##__VA_ARGS__) -# define PyIndexFile_FromCpp(...) FromCpp(&PyIndexFile_Type,##__VA_ARGS__) -# define PyPackageFile_FromCpp(...) FromCpp(&PyPackageFile_Type,##__VA_ARGS__) -//# define PyPackageList_FromCpp(...) FromCpp(&PyPackageList_Type,##__VA_ARGS__) -# define PyPackageManager_FromCpp(...) FromCpp(&PyPackageManager_Type,##__VA_ARGS__) -//# define PyPackageRecords_FromCpp(...) FromCpp(&PyPackageRecords_Type,##__VA_ARGS__) -# define PyPolicy_FromCpp(...) FromCpp(&PyPolicy_Type,##__VA_ARGS__) -# define PyProblemResolver_FromCpp(...) FromCpp(&PyProblemResolver_Type,##__VA_ARGS__) -# define PySourceList_FromCpp(...) FromCpp(&PySourceList_Type,##__VA_ARGS__) -//# define PySourceRecords_FromCpp(...) FromCpp(&PySourceRecords_Type,##__VA_ARGS__) -# define PyTagFile_FromCpp(...) FromCpp(&PyTagFile_Type,##__VA_ARGS__) -# define PyTagSection_FromCpp(...) FromCpp(&PyTagSection_Type,##__VA_ARGS__) -# define PyVersion_FromCpp(...) FromCpp(&PyVersion_Type,##__VA_ARGS__) #endif diff --git a/setup.py b/setup.py index 635fee9b..2fa8198b 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc', 'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc', 'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc', 'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc', - 'lock.cc', 'acquire-item.cc'] + 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc'] files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3]) apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]) -- cgit v1.2.3 From 24971a75407f0b28f2cb4e890545a0f5825af87d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sat, 13 Feb 2010 17:27:59 +0100 Subject: * data/templates/*.in: Switch MirrorsFile to relative filenames. - setup.py: Copy the mirror lists to the build directory - aptsources/distinfo.py: Support relative filenames for MirrorsFile. --- aptsources/distinfo.py | 3 +++ data/templates/Debian.info.in | 16 ++++++++-------- data/templates/Ubuntu.info.in | 32 ++++++++++++++++---------------- debian/changelog | 3 +++ setup.py | 4 ++++ 5 files changed, 34 insertions(+), 24 deletions(-) (limited to 'setup.py') diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py index 0aa34f20..19308348 100644 --- a/aptsources/distinfo.py +++ b/aptsources/distinfo.py @@ -220,6 +220,9 @@ class DistInfo(object): template.match_uri = value elif (field == 'MirrorsFile' or field == 'MirrorsFile-%s' % self.arch): + # Make the path absolute. + value = os.path.isabs(value) and value or \ + os.path.abspath(os.path.join(base_dir, value)) if value not in map_mirror_sets: mirror_set = {} try: diff --git a/data/templates/Debian.info.in b/data/templates/Debian.info.in index 9ea368d6..b9f70940 100644 --- a/data/templates/Debian.info.in +++ b/data/templates/Debian.info.in @@ -4,7 +4,7 @@ Suite: squeeze RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 6.0 'Squeeze' Component: main _CompDescription: Officially supported @@ -29,7 +29,7 @@ Suite: lenny RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 5.0 'Lenny' Component: main _CompDescription: Officially supported @@ -54,7 +54,7 @@ Suite: etch RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 4.0 'Etch' Component: main _CompDescription: Officially supported @@ -79,7 +79,7 @@ Suite: sarge RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 3.1 'Sarge' Component: main _CompDescription: Officially supported @@ -104,7 +104,7 @@ Suite: stable RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian current stable release Component: main _CompDescription: Officially supported @@ -117,7 +117,7 @@ Suite: testing RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian testing Component: main _CompDescription: Officially supported @@ -130,7 +130,7 @@ Suite: sid RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 'Sid' (unstable) Component: main _CompDescription: Officially supported @@ -143,7 +143,7 @@ Suite: unstable RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.([a-z]*\.){0,1}debian\.org -MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors +MirrorsFile: Debian.mirrors _Description: Debian 'Sid' (unstable) Component: main _CompDescription: Officially supported diff --git a/data/templates/Ubuntu.info.in b/data/templates/Ubuntu.info.in index 2335454f..1ca76927 100644 --- a/data/templates/Ubuntu.info.in +++ b/data/templates/Ubuntu.info.in @@ -8,8 +8,8 @@ BaseURI-powerpc: http://ports.ubuntu.com/ MatchURI-powerpc: ports.ubuntu.com|archive.ubuntu.com BaseURI-lpia: http://ports.ubuntu.com/ MatchURI-lpia: ports.ubuntu.com|archive.ubuntu.com -MirrorsFile-amd64: /usr/share/python-apt/templates/Ubuntu.mirrors -MirrorsFile-i386: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile-amd64: Ubuntu.mirrors +MirrorsFile-i386: Ubuntu.mirrors _Description: Ubuntu 10.04 'Lucid Lynx' Component: main _CompDescription: Officially supported @@ -69,8 +69,8 @@ BaseURI-powerpc: http://ports.ubuntu.com/ MatchURI-powerpc: ports.ubuntu.com|archive.ubuntu.com BaseURI-lpia: http://ports.ubuntu.com/ MatchURI-lpia: ports.ubuntu.com|archive.ubuntu.com -MirrorsFile-amd64: /usr/share/python-apt/templates/Ubuntu.mirrors -MirrorsFile-i386: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile-amd64: Ubuntu.mirrors +MirrorsFile-i386: Ubuntu.mirrors _Description: Ubuntu 9.10 'Karmic Koala' Component: main _CompDescription: Officially supported @@ -130,8 +130,8 @@ BaseURI-powerpc: http://ports.ubuntu.com/ MatchURI-powerpc: ports.ubuntu.com|archive.ubuntu.com BaseURI-lpia: http://ports.ubuntu.com/ MatchURI-lpia: ports.ubuntu.com|archive.ubuntu.com -MirrorsFile-amd64: /usr/share/python-apt/templates/Ubuntu.mirrors -MirrorsFile-i386: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile-amd64: Ubuntu.mirrors +MirrorsFile-i386: Ubuntu.mirrors _Description: Ubuntu 9.04 'Jaunty Jackalope' Component: main _CompDescription: Officially supported @@ -191,8 +191,8 @@ BaseURI-powerpc: http://ports.ubuntu.com/ MatchURI-powerpc: ports.ubuntu.com|archive.ubuntu.com BaseURI-lpia: http://ports.ubuntu.com/ MatchURI-lpia: ports.ubuntu.com|archive.ubuntu.com -MirrorsFile-amd64: /usr/share/python-apt/templates/Ubuntu.mirrors -MirrorsFile-i386: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile-amd64: Ubuntu.mirrors +MirrorsFile-i386: Ubuntu.mirrors _Description: Ubuntu 8.10 'Intrepid Ibex' Component: main _CompDescription: Officially supported @@ -253,8 +253,8 @@ BaseURI-powerpc: http://ports.ubuntu.com/ MatchURI-powerpc: ports.ubuntu.com|archive.ubuntu.com BaseURI-lpia: http://ports.ubuntu.com/ MatchURI-lpia: ports.ubuntu.com|archive.ubuntu.com -MirrorsFile-amd64: /usr/share/python-apt/templates/Ubuntu.mirrors -MirrorsFile-i386: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile-amd64: Ubuntu.mirrors +MirrorsFile-i386: Ubuntu.mirrors _Description: Ubuntu 8.04 'Hardy Heron' Component: main _CompDescription: Officially supported @@ -309,7 +309,7 @@ Suite: gutsy RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 7.10 'Gutsy Gibbon' Component: main _CompDescription: Officially supported @@ -362,7 +362,7 @@ Suite: feisty RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 7.04 'Feisty Fawn' Component: main _CompDescription: Officially supported @@ -414,7 +414,7 @@ Suite: edgy RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 6.10 'Edgy Eft' Component: main _CompDescription: Officially supported @@ -466,7 +466,7 @@ Suite: dapper RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 6.06 LTS 'Dapper Drake' Component: main _CompDescription: Officially supported @@ -518,7 +518,7 @@ Suite: breezy RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 5.10 'Breezy Badger' Component: main _CompDescription: Officially supported @@ -561,7 +561,7 @@ Suite: hoary RepositoryType: deb BaseURI: http://archive.ubuntu.com/ubuntu/ MatchURI: archive.ubuntu.com/ubuntu -MirrorsFile: /usr/share/python-apt/templates/Ubuntu.mirrors +MirrorsFile: Ubuntu.mirrors _Description: Ubuntu 5.04 'Hoary Hedgehog' Component: main _CompDescription: Officially supported diff --git a/debian/changelog b/debian/changelog index c63d3a16..cfdc5301 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,6 +16,9 @@ python-apt (0.7.93.2) UNRELEASED; urgency=low * tests: - Fix aptsources tests to use local data files if available. - test_all.py: Use local modules instead of system ones if possible. + * data/templates/*.in: Switch MirrorsFile to relative filenames. + - setup.py: Copy the mirror lists to the build directory + - aptsources/distinfo.py: Support relative filenames for MirrorsFile. -- Julian Andres Klode Sun, 07 Feb 2010 19:58:40 +0100 diff --git a/setup.py b/setup.py index 2fa8198b..b285fcee 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,10 @@ if len(sys.argv) > 1 and sys.argv[1] == "build": build.write(line.lstrip("_")) source.close() build.close() + for template in glob.glob('data/templates/*.mirrors'): + import shutil + shutil.copy(template, os.path.join("build", template)) + setup(name="python-apt", description="Python bindings for APT", -- cgit v1.2.3