diff options
| author | Michael Vogt <michael.vogt@ubuntu.com> | 2009-01-13 17:22:27 +0100 |
|---|---|---|
| committer | Michael Vogt <michael.vogt@ubuntu.com> | 2009-01-13 17:22:27 +0100 |
| commit | 38d602dc83006c51dfe4ed594d691ea9b0679498 (patch) | |
| tree | b7aedfba82c44cad6c3012f879b5d6d7e8ad1425 | |
| parent | 12cf58d12b969010f3d98b2974d72bbb950b775f (diff) | |
| parent | 614897f798d9f16591fbd29ebe2a6c5674102d2d (diff) | |
| download | python-apt-38d602dc83006c51dfe4ed594d691ea9b0679498.tar.gz | |
* apt/*.py:
- Almost complete cleanup of the code
- Remove inconsistent use of tabs and spaces (Closes: #505443)
- Improved documentation
* apt/debfile.py:
- Drop get*() methods, as they are deprecated and were
never in a stable release
- Make DscSrcPackage working
* apt/gtk/widgets.py:
- Fix the code and document the signals
* Introduce new documentation build with Sphinx
- Contains style Guide (Closes: #481562)
- debian/rules: Build the documentation here
- setup.py: Remove pydoc building and add new docs.
- debian/examples: Include examples from documentation
- debian/python-apt.docs:
+ Change html/ to build/doc/html.
+ Add build/doc/text for the text-only documentation
* setup.py:
- Only create build/data when building, not all the time
- Remove build/mo and build/data on clean -a
* debian/control:
- Remove the Conflicts on python2.3-apt, python2.4-apt, as
they are only needed for oldstable (sarge)
- Build-Depend on python-sphinx (>= 0.5)
* aptsources/distinfo.py:
- Allow @ in mirror urls (Closes: #478171) (LP: #223097)
* Merge Ben Finney's whitespace changes (Closes: #481563)
* Merge Ben Finney's do not use has_key() (Closes: #481878)
* Do not use deprecated form of raise statement (Closes: #494259)
* Add support for PkgRecords.SHA256Hash (Closes: #456113)
115 files changed, 5934 insertions, 2849 deletions
@@ -1,9 +1,9 @@ * apt.Package: - change all candidateInstalledSize() to installSize(useCandidate=True) - same for candidateOrigin() (see downloadable for a example). + same for candidateOrigin() (see downloadable for a example). - might be better to have "Package.candidate.{downloadable,size,etc} - + * aptsources: - make the distro detection in sources.list more clever by using the origin informaton to avoid adding full uris to (unofficial/internal) - mirrors + mirrors diff --git a/apt/README.apt b/apt/README.apt index 30166a24..2a017bde 100644 --- a/apt/README.apt +++ b/apt/README.apt @@ -12,10 +12,4 @@ WARNING !!! The API is not 100% stable yet !!! Style Guides: ------------- - -Follow PEP08. - -Internal variables/methods are prefixed with a "_" (e.g. _foo). - - - +See ../doc/source/coding.rst diff --git a/apt/__init__.py b/apt/__init__.py index c6a2ff39..05407aff 100644 --- a/apt/__init__.py +++ b/apt/__init__.py @@ -6,7 +6,8 @@ import os # import some fancy classes from apt.package import Package from apt.cache import Cache -from apt.progress import OpProgress, FetchProgress, InstallProgress, CdromProgress +from apt.progress import ( + OpProgress, FetchProgress, InstallProgress, CdromProgress) from apt.cdrom import Cdrom from apt_pkg import SizeToStr, TimeToStr, VersionCompare diff --git a/apt/cache.py b/apt/cache.py index 79e58282..0065d14c 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -1,62 +1,68 @@ # cache.py - apt cache abstraction -# +# # Copyright (c) 2005 Canonical -# +# # Author: Michael Vogt <michael.vogt@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA +import os +import sys + import apt_pkg from apt import Package import apt.progress -import os -import sys + class FetchCancelledException(IOError): - " Exception that is thrown when the user cancels a fetch operation " - pass + """Exception that is thrown when the user cancels a fetch operation.""" + + class FetchFailedException(IOError): - " Exception that is thrown when fetching fails " - pass + """Exception that is thrown when fetching fails.""" + + class LockFailedException(IOError): - " Exception that is thrown when locking fails " - pass + """Exception that is thrown when locking fails.""" + class Cache(object): - """ Dictionary-like package cache - This class has all the packages that are available in it's - dictionary + """Dictionary-like package cache. + + This class has all the packages that are available in it's + dictionary """ def __init__(self, progress=None, rootdir=None, memonly=False): self._callbacks = {} if memonly: # force apt to build its caches in memory - apt_pkg.Config.Set("Dir::Cache::pkgcache","") + apt_pkg.Config.Set("Dir::Cache::pkgcache", "") if rootdir: apt_pkg.Config.Set("Dir", rootdir) - apt_pkg.Config.Set("Dir::State::status", rootdir + "/var/lib/dpkg/status") + apt_pkg.Config.Set("Dir::State::status", + rootdir + "/var/lib/dpkg/status") self.open(progress) def _runCallbacks(self, name): """ internal helper to run a callback """ - if self._callbacks.has_key(name): + if name in self._callbacks: for callback in self._callbacks[name]: callback() - + def open(self, progress): """ Open the package cache, after that it can be used like a dictionary @@ -70,12 +76,12 @@ class Cache(object): self._dict = {} # build the packages dict - if progress != None: + if progress is not None: progress.Op = "Building data structures" i=last=0 size=len(self._cache.Packages) for pkg in self._cache.Packages: - if progress != None and last+100 < i: + if progress is not None and last+100 < i: progress.update(i/float(size)*100) last=i # drop stuff with no versions (cruft) @@ -83,12 +89,12 @@ class Cache(object): self._dict[pkg.Name] = Package(self._cache, self._depcache, self._records, self._list, self, pkg) - + i += 1 - if progress != None: + if progress is not None: progress.done() self._runCallbacks("cache_post_open") - + def __getitem__(self, key): """ look like a dictionary (get key) """ return self._dict[key] @@ -99,10 +105,10 @@ class Cache(object): raise StopIteration def has_key(self, key): - return self._dict.has_key(key) + return (key in self._dict) def __contains__(self, key): - return key in self._dict + return (key in self._dict) def __len__(self): return len(self._dict) @@ -112,7 +118,7 @@ class Cache(object): def getChanges(self): """ Get the marked changes """ - changes = [] + changes = [] for name in self._dict.keys(): p = self._dict[name] if p.markedUpgrade or p.markedInstall or p.markedDelete or \ @@ -130,21 +136,23 @@ class Cache(object): @property def requiredDownload(self): - """ get the size of the packages that are required to download """ + """Get the size of the packages that are required to download.""" pm = apt_pkg.GetPackageManager(self._depcache) fetcher = apt_pkg.GetAcquire() pm.GetArchives(fetcher, self._list, self._records) return fetcher.FetchNeeded + @property def additionalRequiredSpace(self): - """ get the size of the additional required space on the fs """ + """Get the size of the additional required space on the fs.""" return self._depcache.UsrSize + @property def reqReinstallPkgs(self): - " return the packages not downloadable packages in reqreinst state " + """Return the packages not downloadable packages in reqreinst state.""" reqreinst = set() for pkg in self: - if (not pkg.candidateDownloadable and + if (not pkg.candidateDownloadable and (pkg._pkg.InstState == apt_pkg.InstStateReInstReq or pkg._pkg.InstState == apt_pkg.InstStateHoldReInstReq)): reqreinst.add(pkg.name) @@ -153,7 +161,7 @@ class Cache(object): def _runFetcher(self, fetcher): # do the actual fetching res = fetcher.Run() - + # now check the result (this is the code from apt-get.cc) failed = False transient = False @@ -164,14 +172,15 @@ class Cache(object): if item.StatIdle: transient = True continue - errMsg += "Failed to fetch %s %s\n" % (item.DescURI,item.ErrorText) + errMsg += "Failed to fetch %s %s\n" % (item.DescURI, + item.ErrorText) failed = True # we raise a exception if the download failed or it was cancelt if res == fetcher.ResultCancelled: - raise FetchCancelledException, errMsg + raise FetchCancelledException(errMsg) elif failed: - raise FetchFailedException, errMsg + raise FetchFailedException(errMsg) return res def _fetchArchives(self, fetcher, pm): @@ -181,7 +190,7 @@ class Cache(object): lockfile = apt_pkg.Config.FindDir("Dir::Cache::Archives") + "lock" lock = apt_pkg.GetLock(lockfile) if lock < 0: - raise LockFailedException, "Failed to lock %s" % lockfile + raise LockFailedException("Failed to lock %s" % lockfile) try: # this may as well throw a SystemError exception @@ -193,6 +202,11 @@ class Cache(object): finally: os.close(lock) + def isVirtualPackage(self, pkgname): + """Return whether the package is a virtual package.""" + pkg = self._cache[pkgname] + return bool(pkg.ProvidesList and not pkg.VersionList) + def getProvidingPackages(self, virtual): """ Return a list of packages which provide the virtual package of the @@ -207,7 +221,7 @@ class Cache(object): return providers for pkg in self: v = self._depcache.GetCandidateVer(pkg._pkg) - if v == None: + if v is None: continue for p in v.ProvidesList: if virtual == p[0]: @@ -220,21 +234,21 @@ class Cache(object): lockfile = apt_pkg.Config.FindDir("Dir::State::Lists") + "lock" lock = apt_pkg.GetLock(lockfile) if lock < 0: - raise LockFailedException, "Failed to lock %s" % lockfile + raise LockFailedException("Failed to lock %s" % lockfile) try: - if fetchProgress == None: + if fetchProgress is None: fetchProgress = apt.progress.FetchProgress() return self._cache.Update(fetchProgress, self._list) finally: os.close(lock) - + def installArchives(self, pm, installProgress): installProgress.startUpdate() res = installProgress.run(pm) installProgress.finishUpdate() return res - + def commit(self, fetchProgress=None, installProgress=None): """ Apply the marked changes to the cache """ # FIXME: @@ -244,9 +258,9 @@ class Cache(object): # Current a failed download will just display "error" # which is less than optimal! - if fetchProgress == None: + if fetchProgress is None: fetchProgress = apt.progress.FetchProgress() - if installProgress == None: + if installProgress is None: installProgress = apt.progress.InstallProgress() pm = apt_pkg.GetPackageManager(self._depcache) @@ -260,16 +274,17 @@ class Cache(object): if res == pm.ResultCompleted: break if res == pm.ResultFailed: - raise SystemError, "installArchives() failed" + raise SystemError("installArchives() failed") # reload the fetcher for media swaping fetcher.Shutdown() return (res == pm.ResultCompleted) def clear(self): - """ Unmark all changes """ - self._depcache.Init() + """ Unmark all changes """ + self._depcache.Init() # cache changes + def cachePostChange(self): " called internally if the cache has changed, emit a signal then " self._runCallbacks("cache_post_change") @@ -282,34 +297,42 @@ class Cache(object): def connect(self, name, callback): """ connect to a signal, currently only used for cache_{post,pre}_{changed,open} """ - if not self._callbacks.has_key(name): + if not name in self._callbacks: self._callbacks[name] = [] self._callbacks[name].append(callback) + # ----------------------------- experimental interface + + class Filter(object): """ Filter base class """ + def apply(self, pkg): """ Filter function, return True if the package matchs a filter criteria and False otherwise """ return True + class MarkedChangesFilter(Filter): """ Filter that returns all marked changes """ + def apply(self, pkg): if pkg.markedInstall or pkg.markedDelete or pkg.markedUpgrade: return True else: return False + class FilteredCache(object): """ A package cache that is filtered. Can work on a existing cache or create a new one """ + def __init__(self, cache=None, progress=None): - if cache == None: + if cache is None: self.cache = Cache(progress) else: self.cache = cache @@ -317,17 +340,25 @@ class FilteredCache(object): self.cache.connect("cache_post_open", self.filterCachePostChange) self._filtered = {} self._filters = [] + def __len__(self): return len(self._filtered) - + def __getitem__(self, key): return self.cache._dict[key] + def __iter__(self): + for pkgname in self._filtered: + yield self.cache[pkgname] + def keys(self): return self._filtered.keys() def has_key(self, key): - return self._filtered.has_key(key) + return (key in self._filtered) + + def __contains__(self, key): + return (key in self._filtered) def _reapplyFilter(self): " internal helper to refilter " @@ -337,9 +368,9 @@ class FilteredCache(object): if f.apply(self.cache._dict[pkg]): self._filtered[pkg] = 1 break - + def setFilter(self, filter): - " set the current active filter " + """Set the current active filter.""" self._filters = [] self._filters.append(filter) #self._reapplyFilter() @@ -347,7 +378,7 @@ class FilteredCache(object): self.cache.cachePostChange() def filterCachePostChange(self): - " called internally if the cache changes, emit a signal then " + """Called internally if the cache changes, emit a signal then.""" #print "filterCachePostChange()" self._reapplyFilter() @@ -355,17 +386,15 @@ class FilteredCache(object): # self.cache.connect(name, callback) def __getattr__(self, key): - " we try to look exactly like a real cache " + """we try to look exactly like a real cache.""" #print "getattr: %s " % key - if self.__dict__.has_key(key): - return self.__dict__[key] - else: - return getattr(self.cache, key) - + return getattr(self.cache, key) + def cache_pre_changed(): print "cache pre changed" + def cache_post_changed(): print "cache post changed" @@ -377,7 +406,7 @@ if __name__ == "__main__": c = Cache(apt.progress.OpTextProgress()) c.connect("cache_pre_change", cache_pre_changed) c.connect("cache_post_change", cache_post_changed) - print c.has_key("aptitude") + print ("aptitude" in c) p = c["aptitude"] print p.name print len(c) @@ -397,7 +426,7 @@ if __name__ == "__main__": for d in ["/tmp/pytest", "/tmp/pytest/partial"]: if not os.path.exists(d): os.mkdir(d) - apt_pkg.Config.Set("Dir::Cache::Archives","/tmp/pytest") + apt_pkg.Config.Set("Dir::Cache::Archives", "/tmp/pytest") pm = apt_pkg.GetPackageManager(c._depcache) fetcher = apt_pkg.GetAcquire(apt.progress.TextFetchProgress()) c._fetchArchives(fetcher, pm) @@ -413,7 +442,7 @@ if __name__ == "__main__": for pkg in f.keys(): #print c[pkg].name x = f[pkg].name - + print len(f) print "Testing filtered cache (no argument)" @@ -426,5 +455,5 @@ if __name__ == "__main__": for pkg in f.keys(): #print c[pkg].name x = f[pkg].name - + print len(f) diff --git a/apt/cdrom.py b/apt/cdrom.py index 9d4b62cb..61250fc4 100644 --- a/apt/cdrom.py +++ b/apt/cdrom.py @@ -1,14 +1,49 @@ +# cdrom.py - CDROM handling +# +# Copyright (c) 2005 Canonical +# Copyright (c) 2009 Julian Andres Klode <jak@debian.org> +# +# Author: Michael Vogt <michael.vogt@ubuntu.com> +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +"""Classes related to cdrom handling.""" +import glob + import apt_pkg -from progress import CdromProgress +from apt.progress import CdromProgress + class Cdrom(object): + """Support for apt-cdrom like features. + + This class has several optional parameters for initialisation, which may + be used to influence the behaviour of the object: + + The optional parameter `progress` is a CdromProgress() subclass, which will + ask for the correct cdrom, etc. If not specified or None, a CdromProgress() + object will be used. + + The optional parameter `mountpoint` may be used to specify an alternative + mountpoint. + + If the optional parameter `nomount` is True, the cdroms will not be + mounted. This is the default behaviour. + """ + def __init__(self, progress=None, mountpoint=None, nomount=True): - """ Support for apt-cdrom like features. - Options: - - progress: optional progress.CdromProgress() subclass - - mountpoint: optional alternative mountpoint - - nomount: do not mess with mount/umount the CD - """ self._cdrom = apt_pkg.GetCdrom() if progress is None: self._progress = CdromProgress() @@ -16,32 +51,36 @@ class Cdrom(object): self._progress = progress # see if we have a alternative mountpoint if mountpoint is not None: - apt_pkg.Config.Set("Acquire::cdrom::mount",mountpoint) + apt_pkg.Config.Set("Acquire::cdrom::mount", mountpoint) # do not mess with mount points by default - if nomount is True: + if nomount: apt_pkg.Config.Set("APT::CDROM::NoMount", "true") else: apt_pkg.Config.Set("APT::CDROM::NoMount", "false") + def add(self): - " add cdrom to the sources.list " + """Add cdrom to the sources.list.""" return self._cdrom.Add(self._progress) + def ident(self): - " identify the cdrom " + """Identify the cdrom.""" (res, ident) = self._cdrom.Ident(self._progress) if res: return ident - return None + @property def inSourcesList(self): - " check if the cdrom is already in the current sources.list " - cdid = self.ident() - if cdid is None: + """Check if the cdrom is already in the current sources.list.""" + cd_id = self.ident() + if cd_id is None: # FIXME: throw exception instead return False - # FIXME: check sources.list.d/ as well - for line in open(apt_pkg.Config.FindFile("Dir::Etc::sourcelist")): - line = line.strip() - if not line.startswith("#") and cdid in line: - return True + # Get a list of files + src = glob.glob(apt_pkg.Config.FindDir("Dir::Etc::sourceparts") + '*') + src.append(apt_pkg.Config.FindFile("Dir::Etc::sourcelist")) + # Check each file + for fname in src: + for line in open(fname): + if not line.lstrip().startswith("#") and cd_id in line: + return True return False - diff --git a/apt/debfile.py b/apt/debfile.py index b1d436cd..f24f19f4 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -19,24 +19,25 @@ # along with GDebi; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # - -import warnings -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) -import apt_inst, apt_pkg -import sys -import os +"""Classes for working with locally available Debian packages.""" from gettext import gettext as _ +import os +import sys + +import apt_inst +import apt_pkg + # Constants for comparing the local package file with the version in the cache -(VERSION_NONE, - VERSION_OUTDATED, - VERSION_SAME, - VERSION_NEWER) = range(4) - +(VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER) = range(4) + + class NoDebArchiveException(IOError): - pass + """Exception which is raised if a file is no Debian archive.""" + class DebPackage(object): + """A Debian Package (.deb file).""" _supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma") @@ -44,11 +45,10 @@ class DebPackage(object): def __init__(self, filename=None, cache=None): self._cache = cache - self.file = filename - self._needPkgs = [] + self._need_pkgs = [] self._sections = {} - self._installedConflicts = set() - self._failureString = "" + self._installed_conflicts = set() + self._failure_string = "" if filename: self.open(filename) @@ -56,35 +56,42 @@ class DebPackage(object): " open given debfile " self.filename = filename if not apt_inst.arCheckMember(open(self.filename), "debian-binary"): - raise NoDebArchiveException, _("This is not a valid DEB archive, missing '%s' member" % "debian-binary") + raise NoDebArchiveException(_("This is not a valid DEB archive, " + "missing '%s' member" % + "debian-binary")) control = apt_inst.debExtractControl(open(self.filename)) self._sections = apt_pkg.ParseSection(control) self.pkgname = self._sections["Package"] def __getitem__(self, key): return self._sections[key] - + + @property def filelist(self): - """ return the list of files in the deb """ + """return the list of files in the deb.""" files = [] - def extract_cb(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor): - #print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u"\ - # % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor) - files.append(Name) + + def extract_cb(what, name, *_): + files.append(name) + for member in self._supported_data_members: if apt_inst.arCheckMember(open(self.filename), member): try: - apt_inst.debExtract(open(self.filename), extract_cb, member) + apt_inst.debExtract(open(self.filename), extract_cb, + member) break - except SystemError, e: - return [_("List of files for '%s'could not be read" % self.filename)] + except SystemError: + return [_("List of files for '%s'could not be read" % + self.filename)] return files - filelist = property(filelist) - def _isOrGroupSatisfied(self, or_group): - """ this function gets a 'or_group' and analyzes if - at least one dependency of this group is already satisfied """ - self._dbg(2,"_checkOrGroup(): %s " % (or_group)) + def _is_or_group_satisfied(self, or_group): + """Return True if at least one dependency of the or-group is satisfied. + + This method gets an 'or_group' and analyzes if at least one dependency + of this group is already satisfied. + """ + self._dbg(2, "_checkOrGroup(): %s " % (or_group)) for dep in or_group: depname = dep[0] @@ -92,9 +99,10 @@ class DebPackage(object): oper = dep[2] # check for virtual pkgs - if not self._cache.has_key(depname): + if not depname in self._cache: if self._cache.isVirtualPackage(depname): - self._dbg(3,"_isOrGroupSatisfied(): %s is virtual dep" % depname) + self._dbg(3, "_isOrGroupSatisfied(): %s is virtual dep" % + depname) for pkg in self._cache.getProvidingPackages(depname): if pkg.isInstalled: return True @@ -102,24 +110,17 @@ class DebPackage(object): inst = self._cache[depname] instver = inst.installedVersion - if instver != None and apt_pkg.CheckDep(instver,oper,ver) == True: + if instver is not None and apt_pkg.CheckDep(instver, oper, ver): return True return False - - - def _satisfyOrGroup(self, or_group): - """ try to satisfy the or_group """ - - or_found = False - virtual_pkg = None + def _satisfy_or_group(self, or_group): + """Try to satisfy the or_group.""" for dep in or_group: - depname = dep[0] - ver = dep[1] - oper = dep[2] + depname, ver, oper = dep # if we don't have it in the cache, it may be virtual - if not self._cache.has_key(depname): + if not depname in self._cache: if not self._cache.isVirtualPackage(depname): continue providers = self._cache.getProvidingPackages(depname) @@ -128,55 +129,59 @@ class DebPackage(object): if len(providers) != 1: continue depname = providers[0].name - + # now check if we can satisfy the deps with the candidate(s) # in the cache - cand = self._cache[depname] - candver = self._cache._depcache.GetCandidateVer(cand._pkg) - if not candver: + pkg = self._cache[depname] + cand = self._cache._depcache.GetCandidateVer(pkg._pkg) + if not cand: continue - if not apt_pkg.CheckDep(candver.VerStr,oper,ver): + if not apt_pkg.CheckDep(cand.VerStr, oper, ver): continue # check if we need to install it - self._dbg(2,"Need to get: %s" % depname) - self._needPkgs.append(depname) + self._dbg(2, "Need to get: %s" % depname) + self._need_pkgs.append(depname) return True # if we reach this point, we failed or_str = "" for dep in or_group: or_str += dep[0] - if dep != or_group[len(or_group)-1]: + if dep != or_group[-1]: or_str += "|" - self._failureString += _("Dependency is not satisfiable: %s\n" % or_str) + self._failure_string += _("Dependency is not satisfiable: %s\n" % + or_str) return False - def _checkSinglePkgConflict(self, pkgname, ver, oper): - """ returns true if a pkg conflicts with a real installed/marked - pkg """ + def _check_single_pkg_conflict(self, pkgname, ver, oper): + """Return True if a pkg conflicts with a real installed/marked pkg.""" # FIXME: deal with conflicts against its own provides # (e.g. Provides: ftp-server, Conflicts: ftp-server) - self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" % (pkgname, ver, oper)) - pkgver = None - cand = self._cache[pkgname] - if cand.isInstalled: - pkgver = cand.installedVersion - elif cand.markedInstall: - pkgver = cand.candidateVersion + self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" % + (pkgname, ver, oper)) + + pkg = self._cache[pkgname] + if pkg.isInstalled: + pkgver = pkg.installedVersion + elif pkg.markedInstall: + pkgver = pkg.candidateVersion + else: + return False #print "pkg: %s" % pkgname #print "ver: %s" % ver #print "pkgver: %s " % pkgver #print "oper: %s " % oper - if (pkgver and apt_pkg.CheckDep(pkgver,oper,ver) and - not self.replacesRealPkg(pkgname, oper, ver)): - self._failureString += _("Conflicts with the installed package '%s'" % cand.name) + if (apt_pkg.CheckDep(pkgver, oper, ver) and not + self.replaces_real_pkg(pkgname, oper, ver)): + self._failure_string += _("Conflicts with the installed package " + "'%s'" % pkg.name) return True return False - def _checkConflictsOrGroup(self, or_group): - """ check the or-group for conflicts with installed pkgs """ - self._dbg(2,"_checkConflictsOrGroup(): %s " % (or_group)) + def _check_conflicts_or_group(self, or_group): + """Check the or-group for conflicts with installed pkgs.""" + self._dbg(2, "_check_conflicts_or_group(): %s " % (or_group)) or_found = False virtual_pkg = None @@ -187,152 +192,116 @@ class DebPackage(object): oper = dep[2] # check conflicts with virtual pkgs - if not self._cache.has_key(depname): - # FIXME: we have to check for virtual replaces here as + if not depname in self._cache: + # FIXME: we have to check for virtual replaces here as # well (to pass tests/gdebi-test8.deb) if self._cache.isVirtualPackage(depname): for pkg in self._cache.getProvidingPackages(depname): self._dbg(3, "conflicts virtual check: %s" % pkg.name) # P/C/R on virtal pkg, e.g. ftpd - if self.pkgName == pkg.name: + if self.pkgname == pkg.name: self._dbg(3, "conflict on self, ignoring") continue - if self._checkSinglePkgConflict(pkg.name,ver,oper): - self._installedConflicts.add(pkg.name) + if self._check_single_pkg_conflict(pkg.name, ver, oper): + self._installed_conflicts.add(pkg.name) continue - if self._checkSinglePkgConflict(depname,ver,oper): - self._installedConflicts.add(depname) - return len(self._installedConflicts) != 0 - - def getConflicts(self): - """ - Return list of package names conflicting with this package. - - WARNING: This method will is deprecated. Please use the - attribute DebPackage.depends instead. - """ - return self.conflicts + if self._check_single_pkg_conflict(depname, ver, oper): + self._installed_conflicts.add(depname) + return bool(self._installed_conflicts) + @property def conflicts(self): - """ - List of package names conflicting with this package - """ - conflicts = [] + """List of package names conflicting with this package.""" key = "Conflicts" - if self._sections.has_key(key): - conflicts = apt_pkg.ParseDepends(self._sections[key]) - return conflicts - conflicts = property(conflicts) - - def getDepends(self): - """ - Return list of package names on which this package depends on. - - WARNING: This method will is deprecated. Please use the - attribute DebPackage.depends instead. - """ - return self.depends + try: + return apt_pkg.ParseDepends(self._sections[key]) + except KeyError: + return [] + @property def depends(self): - """ - List of package names on which this package depends on - """ + """List of package names on which this package depends on.""" depends = [] # find depends - for key in ["Depends","PreDepends"]: - if self._sections.has_key(key): + for key in "Depends", "PreDepends": + try: depends.extend(apt_pkg.ParseDepends(self._sections[key])) + except KeyError: + pass return depends - depends = property(depends) - - def getProvides(self): - """ - Return list of virtual packages which are provided by this package. - - WARNING: This method will is deprecated. Please use the - attribute DebPackage.provides instead. - """ - return self.provides + @property def provides(self): - """ - List of virtual packages which are provided by this package - """ - provides = [] + """List of virtual packages which are provided by this package.""" key = "Provides" - if self._sections.has_key(key): - provides = apt_pkg.ParseDepends(self._sections[key]) - return provides - provides = property(provides) - - def getReplaces(self): - """ - Return list of packages which are replaced by this package. - - WARNING: This method will is deprecated. Please use the - attribute DebPackage.replaces instead. - """ - return self.replaces + try: + return apt_pkg.ParseDepends(self._sections[key]) + except KeyError: + return [] + @property def replaces(self): - """ - List of packages which are replaced by this package - """ - replaces = [] + """List of packages which are replaced by this package.""" key = "Replaces" - if self._sections.has_key(key): - replaces = apt_pkg.ParseDepends(self._sections[key]) - return replaces - replaces = property(replaces) - - def replacesRealPkg(self, pkgname, oper, ver): - """ - return True if the deb packages replaces a real (not virtual) - packages named pkgname, oper, ver + try: + return apt_pkg.ParseDepends(self._sections[key]) + except KeyError: + return [] + + def replaces_real_pkg(self, pkgname, oper, ver): + """Return True if a given non-virtual package is replaced. + + Return True if the deb packages replaces a real (not virtual) + packages named (pkgname, oper, ver). """ - self._dbg(3, "replacesPkg() %s %s %s" % (pkgname,oper,ver)) - pkgver = None - cand = self._cache[pkgname] - if cand.isInstalled: - pkgver = cand.installedVersion - elif cand.markedInstall: - pkgver = cand.candidateVersion - for or_group in self.getReplaces(): + self._dbg(3, "replacesPkg() %s %s %s" % (pkgname, oper, ver)) + pkg = self._cache[pkgname] + if pkg.isInstalled: + pkgver = pkg.installedVersion + elif pkg.markedInstall: + pkgver = pkg.candidateVersion + else: + pkgver = None + for or_group in self.replaces: for (name, ver, oper) in or_group: - if (name == pkgname and - apt_pkg.CheckDep(pkgver,oper,ver)): - self._dbg(3, "we have a replaces in our package for the conflict against '%s'" % (pkgname)) + if (name == pkgname and apt_pkg.CheckDep(pkgver, oper, ver)): + self._dbg(3, "we have a replaces in our package for the " + "conflict against '%s'" % (pkgname)) return True return False - def checkConflicts(self): - """ check if the pkg conflicts with a existing or to be installed - package. Return True if the pkg is ok """ + def check_conflicts(self): + """Check if there are conflicts with existing or selected packages. + + Check if the package conflicts with a existing or to be installed + package. Return True if the pkg is OK. + """ res = True - for or_group in self.getConflicts(): - if self._checkConflictsOrGroup(or_group): + for or_group in self.conflicts: + if self._check_conflicts_or_group(or_group): #print "Conflicts with a exisiting pkg!" - #self._failureString = "Conflicts with a exisiting pkg!" + #self._failure_string = "Conflicts with a exisiting pkg!" res = False return res - - def compareToVersionInCache(self, useInstalled=True): - """ checks if the pkg is already installed or availabe in the cache - and if so in what version, returns if the version of the deb - is not available,older,same,newer + def compare_to_version_in_cache(self, use_installed=True): + """Compare the package to the version available in the cache. + + Checks if the package is already installed or availabe in the cache + and if so in what version, returns one of (VERSION_NONE, + VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER). """ - self._dbg(3,"compareToVersionInCache") + self._dbg(3, "compareToVersionInCache") pkgname = self._sections["Package"] debver = self._sections["Version"] - self._dbg(1,"debver: %s" % debver) - if self._cache.has_key(pkgname): - if useInstalled: + self._dbg(1, "debver: %s" % debver) + if pkgname in self._cache: + if use_installed: cachever = self._cache[pkgname].installedVersion else: cachever = self._cache[pkgname].candidateVersion - if cachever != None: - cmp = apt_pkg.VersionCompare(cachever,debver) + if cachever is not None: + cmp = apt_pkg.VersionCompare(cachever, debver) self._dbg(1, "CompareVersion(debver,instver): %s" % cmp) if cmp == 0: return VERSION_SAME @@ -342,82 +311,88 @@ class DebPackage(object): return VERSION_OUTDATED return VERSION_NONE - def checkDeb(self): - self._dbg(3,"checkDepends") + def check(self): + """Check if the package is installable.""" + self._dbg(3, "checkDepends") # check arch arch = self._sections["Architecture"] if arch != "all" and arch != apt_pkg.Config.Find("APT::Architecture"): - self._dbg(1,"ERROR: Wrong architecture dude!") - self._failureString = _("Wrong architecture '%s'" % arch) + self._dbg(1, "ERROR: Wrong architecture dude!") + self._failure_string = _("Wrong architecture '%s'" % arch) return False # check version - res = self.compareToVersionInCache() - if res == VERSION_OUTDATED: # the deb is older than the installed - self._failureString = _("A later version is already installed") + if self.compare_to_version_in_cache() == VERSION_OUTDATED: + # the deb is older than the installed + self._failure_string = _("A later version is already installed") return False # FIXME: this sort of error handling sux - self._failureString = "" + self._failure_string = "" # check conflicts - if not self.checkConflicts(): + if not self.check_conflicts(): return False # try to satisfy the dependencies - res = self._satisfyDepends(self.getDepends()) - if not res: + if not self._satisfy_depends(self.depends): return False # check for conflicts again (this time with the packages that are # makeed for install) - if not self.checkConflicts(): + if not self.check_conflicts(): return False if self._cache._depcache.BrokenCount > 0: - self._failureString = _("Failed to satisfy all dependencies (broken cache)") + self._failure_string = _("Failed to satisfy all dependencies " + "(broken cache)") # clean the cache again self._cache.clear() return False return True - def satisfyDependsStr(self, dependsstr): - return self._satisfyDepends(apt_pkg.ParseDepends(dependsstr)) + def satisfy_depends_str(self, dependsstr): + """Satisfy the dependencies in the given string.""" + return self._satisfy_depends(apt_pkg.ParseDepends(dependsstr)) - def _satisfyDepends(self, depends): + def _satisfy_depends(self, depends): + """Satisfy the dependencies.""" # turn off MarkAndSweep via a action group (if available) try: _actiongroup = apt_pkg.GetPkgActionGroup(self._cache._depcache) - except AttributeError, e: + except AttributeError: pass # check depends for or_group in depends: #print "or_group: %s" % or_group - #print "or_group satified: %s" % self._isOrGroupSatisfied(or_group) - if not self._isOrGroupSatisfied(or_group): - if not self._satisfyOrGroup(or_group): + #print "or_group satified: %s" % self._is_or_group_satisfied(or_group) + if not self._is_or_group_satisfied(or_group): + if not self._satisfy_or_group(or_group): return False # now try it out in the cache - for pkg in self._needPkgs: - try: - self._cache[pkg].markInstall(fromUser=False) - except SystemError, e: - self._failureString = _("Cannot install '%s'" % pkg) - self._cache.clear() - return False + for pkg in self._need_pkgs: + try: + self._cache[pkg].markInstall(fromUser=False) + except SystemError, e: + self._failure_string = _("Cannot install '%s'" % pkg) + self._cache.clear() + return False return True - def missingDeps(self): - self._dbg(1, "Installing: %s" % self._needPkgs) - if self._needPkgs == None: - self.checkDeb() - return self._needPkgs - missingDeps = property(missingDeps) + @property + def missing_deps(self): + """Return missing dependencies.""" + self._dbg(1, "Installing: %s" % self._need_pkgs) + if self._need_pkgs is None: + self.check() + return self._need_pkgs - def requiredChanges(self): - """ gets the required changes to satisfy the depends. - returns a tuple with (install, remove, unauthenticated) + @property + def required_changes(self): + """Get the changes required to satisfy the dependencies. + + Returns: a tuple with (install, remove, unauthenticated) """ install = [] remove = [] @@ -434,95 +409,118 @@ class DebPackage(object): unauthenticated.append(pkg.name) if pkg.markedDelete: remove.append(pkg.name) - return (install,remove, unauthenticated) - requiredChanges = property(requiredChanges) + return (install, remove, unauthenticated) def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ + """Write debugging output to sys.stderr.""" if level <= self.debug: print >> sys.stderr, msg - def install(self, installProgress=None): - """ Install the package """ - if installProgress == None: - res = os.system("/usr/sbin/dpkg -i %s" % self.filename) + def install(self, install_progress=None): + """Install the package.""" + if install_progress is None: + return os.system("dpkg -i %s" % self.filename) else: - installProgress.startUpdate() - res = installProgress.run(self.filename) - installProgress.finishUpdate() - return res + try: + install_progress.start_update() + except AttributeError: + install_progress.startUpdate() + res = install_progress.run(self.filename) + try: + install_progress.finish_update() + except AttributeError: + install_progress.finishUpdate() + return res + class DscSrcPackage(DebPackage): + """A locally available source package.""" + def __init__(self, filename=None, cache=None): - DebPackage.__init__(self, filename, cache) - self.depends = [] - self.conflicts = [] - self.binaries = [] - if filename != None: + DebPackage.__init__(self, None, cache) + self._depends = [] + self._conflicts = [] + self._binaries = [] + if filename is not None: self.open(filename) - def getConflicts(self): - return self.conflicts - def getDepends(self): - return self.depends + + @property + def depends(self): + """Return the dependencies of the package""" + return self._depends + + @property + def conflicts(self): + """Return the dependencies of the package""" + return self._conflicts + def open(self, file): - depends_tags = ["Build-Depends:", "Build-Depends-Indep:"] - conflicts_tags = ["Build-Conflicts:", "Build-Conflicts-Indep:"] - for line in open(file): - # check b-d and b-c - for tag in depends_tags: - if line.startswith(tag): - key = line[len(tag):].strip() - self.depends.extend(apt_pkg.ParseSrcDepends(key)) - for tag in conflicts_tags: - if line.startswith(tag): - key = line[len(tag):].strip() - self.conflicts.extend(apt_pkg.ParseSrcDepends(key)) - # check binary and source and version - if line.startswith("Source:"): - self.pkgName = line[len("Source:"):].strip() - if line.startswith("Binary:"): - self.binaries = [pkg.strip() for pkg in line[len("Binary:"):].split(",")] - if line.startswith("Version:"): - self._sections["Version"] = line[len("Version:"):].strip() - # we are at the end - if line.startswith("-----BEGIN PGP SIGNATURE-"): - break + """Open the package.""" + depends_tags = ["Build-Depends", "Build-Depends-Indep"] + conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"] + + fobj = open(file) + tagfile = apt_pkg.ParseTagFile(fobj) + sec = tagfile.Section + try: + while tagfile.Step() == 1: + for tag in depends_tags: + if not sec.has_key(tag): + continue + self._depends.extend(apt_pkg.ParseSrcDepends(sec[tag])) + for tag in conflicts_tags: + if not sec.has_key(tag): + continue + self._conflicts.extend(apt_pkg.ParseSrcDepends(sec[tag])) + if sec.has_key('Source'): + self.pkgname = sec['Source'] + if sec.has_key('Binary'): + self.binaries = sec['Binary'].split(', ') + if sec.has_key('Version'): + self._sections['Version'] = sec['Version'] + finally: + del sec + del tagfile + fobj.close() + s = _("Install Build-Dependencies for " - "source package '%s' that builds %s\n" - ) % (self.pkgName, " ".join(self.binaries)) + "source package '%s' that builds %s\n") % (self.pkgname, + " ".join(self.binaries)) self._sections["Description"] = s - - def checkDeb(self): - if not self.checkConflicts(): - for pkgname in self._installedConflicts: + + def check(self): + """Check if the package is installable..""" + if not self.check_conflicts(): + for pkgname in self._installed_conflicts: if self._cache[pkgname]._pkg.Essential: - raise Exception, _("A essential package would be removed") + raise Exception(_("An essential package would be removed")) self._cache[pkgname].markDelete() # FIXME: a additional run of the checkConflicts() # after _satisfyDepends() should probably be done - return self._satisfyDepends(self.depends) + return self._satisfy_depends(self.depends) -if __name__ == "__main__": - from cache import Cache - from progress import DpkgInstallProgress + +def _test(): + """Test function""" + from apt.cache import Cache + from apt.progress import DpkgInstallProgress cache = Cache() vp = "www-browser" - print "%s virtual: %s" % (vp,cache.isVirtualPackage(vp)) + #print "%s virtual: %s" % (vp, cache.isVirtualPackage(vp)) providers = cache.getProvidingPackages(vp) print "Providers for %s :" % vp for pkg in providers: print " %s" % pkg.name - + d = DebPackage(sys.argv[1], cache) print "Deb: %s" % d.pkgname - if not d.checkDeb(): + if not d.check(): print "can't be satified" - print d._failureString - print "missing deps: %s" % d.missingDeps - print d.requiredChanges + print d._failure_string + print "missing deps: %s" % d.missing_deps + print d.required_changes print "Installing ..." ret = d.install(DpkgInstallProgress()) @@ -535,4 +533,7 @@ if __name__ == "__main__": s = DscSrcPackage(cache=cache) d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)" - print s._satisfyDepends(apt_pkg.ParseDepends(d)) + print s._satisfy_depends(apt_pkg.ParseDepends(d)) + +if __name__ == "__main__": + _test() diff --git a/apt/gtk/widgets.py b/apt/gtk/widgets.py index 3a15258f..34cc2759 100644 --- a/apt/gtk/widgets.py +++ b/apt/gtk/widgets.py @@ -1,28 +1,26 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -widgets - GTK widgets to show the progress and status of apt - -Copyright (c) 2004,2005 Canonical Ltd. - -Authors: Michael Vogt <mvo@ubuntu.com> - Sebastian Heinlein <glatzor@ubuntu.com> - -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. - -his 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -USA -""" +# +# Copyright (c) 2004-2005 Canonical +# +# Authors: Michael Vogt <michael.vogt@ubuntu.com> +# Sebastian Heinlein <glatzor@ubuntu.com> +# Julian Andres Klode <jak@debian.org> +# +# 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. +# +# his 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +"""GObject-powered progress classes and a GTK+ status widget.""" from gettext import gettext as _ import os @@ -39,15 +37,32 @@ import vte import apt import apt_pkg + +def mksig(params=(), run=gobject.SIGNAL_RUN_FIRST, rettype=gobject.TYPE_NONE): + """Simplified Create a gobject signal. + + This allows us to write signals easier, because we just need to define the + type of the parameters (in most cases). + + ``params`` is a tuple which defines the types of the arguments. + """ + return (run, rettype, params) + + class GOpProgress(gobject.GObject, apt.progress.OpProgress): + """Operation progress with GObject signals. + + Signals: - __gsignals__ = {"status-changed":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_INT)), - "status-started":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-finished":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ())} + * status-changed(str: operation, int: percent) + * status-started() - Not Implemented yet + * status-finished() + + """ + + __gsignals__ = {"status-changed": mksig((str, int)), + "status-started": mksig(), + "status-finished": mksig()} def __init__(self): apt.progress.OpProgress.__init__(self) @@ -55,31 +70,38 @@ class GOpProgress(gobject.GObject, apt.progress.OpProgress): self._context = glib.main_context_default() def update(self, percent): + """Called to update the percentage done""" self.emit("status-changed", self.op, percent) while self._context.pending(): self._context.iteration() def done(self): + """Called when all operation have finished.""" self.emit("status-finished") + class GInstallProgress(gobject.GObject, apt.progress.InstallProgress): + """Installation progress with GObject signals. + + Signals: + + * status-changed(str: status, int: percent) + * status-started() + * status-finished() + * status-timeout() + * status-error() + * status-conffile() + """ # Seconds until a maintainer script will be regarded as hanging INSTALL_TIMEOUT = 5 * 60 - __gsignals__ = {"status-changed":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_INT)), - "status-started":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-timeout":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-error":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-conffile":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-finished":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ())} + __gsignals__ = {"status-changed": mksig((str, int)), + "status-started": mksig(), + "status-timeout": mksig(), + "status-error": mksig(), + "status-conffile": mksig(), + "status-finished": mksig()} def __init__(self, term): apt.progress.InstallProgress.__init__(self) @@ -89,32 +111,57 @@ class GInstallProgress(gobject.GObject, apt.progress.InstallProgress): self.term = term reaper = vte.reaper_get() reaper.connect("child-exited", self.childExited) - self.env = ["VTE_PTY_KEEP_FD=%s"% self.writefd, + self.env = ["VTE_PTY_KEEP_FD=%s" % self.writefd, "DEBIAN_FRONTEND=gnome", "APT_LISTCHANGES_FRONTEND=gtk"] self._context = glib.main_context_default() def childExited(self, term, pid, status): + """Called when a child process exits""" self.apt_status = os.WEXITSTATUS(status) self.finished = True def error(self, pkg, errormsg): + """Called when an error happens. + + Emits: status-error() + """ self.emit("status-error") def conffile(self, current, new): + """Called during conffile. + + Emits: status-conffile() + """ self.emit("status-conffile") def startUpdate(self): + """Called when the update starts. + + Emits: status-started() + """ self.emit("status-started") def finishUpdate(self): + """Called when the update finished. + + Emits: status-finished() + """ self.emit("status-finished") def statusChange(self, pkg, percent, status): + """Called when the status changed. + + Emits: status-changed(status, percent) + """ self.time_last_update = time.time() self.emit("status-changed", status, percent) def updateInterface(self): + """Called periodically to update the interface. + + Emits: status-timeout() [When a timeout happens] + """ apt.progress.InstallProgress.updateInterface(self) while self._context.pending(): self._context.iteration() @@ -122,34 +169,55 @@ class GInstallProgress(gobject.GObject, apt.progress.InstallProgress): self.emit("status-timeout") def fork(self): + """Fork the process.""" return self.term.forkpty(envv=self.env) def waitChild(self): + """Wait for the child process to exit.""" while not self.finished: self.updateInterface() return self.apt_status -class GDpkgInstallProgress(apt.progress.DpkgInstallProgress,GInstallProgress): +class GDpkgInstallProgress(apt.progress.DpkgInstallProgress, GInstallProgress): + """An InstallProgress for local installations. + + Signals: + + * status-changed(str: status, int: percent) + * status-started() - Not Implemented yet + * status-finished() + * status-timeout() - When the maintainer script hangs + * status-error() - When an error happens + * status-conffile() - On Conffile + """ def run(self, debfile): + """Install the given package.""" apt.progress.DpkgInstallProgress.run(self, debfile) def updateInterface(self): + """Called periodically to update the interface. + + Emits: status-timeout() [When a timeout happens]""" apt.progress.DpkgInstallProgress.updateInterface(self) if self.time_last_update + self.INSTALL_TIMEOUT < time.time(): self.emit("status-timeout") class GFetchProgress(gobject.GObject, apt.progress.FetchProgress): + """A Fetch Progress with GObject signals. - __gsignals__ = {"status-changed":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_INT)), - "status-started":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ()), - "status-finished":(gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ())} + Signals: + + * status-changed(str: description, int: percent) + * status-started() + * status-finished() + """ + + __gsignals__ = {"status-changed": mksig((str, int)), + "status-started": mksig(), + "status-finished": mksig()} def __init__(self): apt.progress.FetchProgress.__init__(self) @@ -170,17 +238,17 @@ class GFetchProgress(gobject.GObject, apt.progress.FetchProgress): apt.progress.FetchProgress.pulse(self) currentItem = self.currentItems + 1 if currentItem > self.totalItems: - currentItem = self.totalItems + currentItem = self.totalItems if self.currentCPS > 0: text = (_("Downloading file %(current)li of %(total)li with " "%(speed)s/s") % \ - {"current" : currentItem, - "total" : self.totalItems, - "speed" : humanize_size(self.currentCPS)}) + {"current": currentItem, + "total": self.totalItems, + "speed": apt_pkg.SizeToStr(self.currentCPS)}) else: text = (_("Downloading file %(current)li of %(total)li") % \ - {"current" : currentItem, - "total" : self.totalItems }) + {"current": currentItem, + "total": self.totalItems}) self.emit("status-changed", text, self.percent) while self._context.pending(): self._context.iteration() @@ -188,33 +256,12 @@ class GFetchProgress(gobject.GObject, apt.progress.FetchProgress): class GtkAptProgress(gtk.VBox): - """ + """Graphical progress for installation/fetch/operations. + This widget provides a progress bar, a terminal and a status bar for showing the progress of package manipulation tasks. - - A simple example code snippet to install/remove a package: - - import pygtk - pygtk.require('2.0') - import gtk - - import apt.widgets - - win = gtk.Window() - progress = apt.widgets.GtkAptProgress() - win.set_title("GtkAptProgress Demo") - win.add(progress) - progress.show() - win.show() - - cache = apt.cache.Cache(progress.open)) - cache["xterm"].markDelete() - progress.show_terminal(expanded=True) - cache.commit(progress.fetch), - progress.install) - - gtk.main() """ + def __init__(self): gtk.VBox.__init__(self) self.set_spacing(6) @@ -226,7 +273,7 @@ class GtkAptProgress(gtk.VBox): self._progressbar = gtk.ProgressBar() # Setup the always italic status label self._label = gtk.Label() - attr_list = pango.AttrList() + attr_list = pango.AttrList() attr_list.insert(pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)) self._label.set_attributes(attr_list) self._label.set_ellipsize(pango.ELLIPSIZE_END) @@ -239,86 +286,80 @@ class GtkAptProgress(gtk.VBox): self._progress_open = GOpProgress() self._progress_open.connect("status-changed", self._on_status_changed) self._progress_open.connect("status-started", self._on_status_started) - self._progress_open.connect("status-finished", self._on_status_finished) + self._progress_open.connect("status-finished", + self._on_status_finished) self._progress_fetch = GFetchProgress() self._progress_fetch.connect("status-changed", self._on_status_changed) self._progress_fetch.connect("status-started", self._on_status_started) - self._progress_fetch.connect("status-finished", + self._progress_fetch.connect("status-finished", self._on_status_finished) self._progress_install = GInstallProgress(self._terminal) self._progress_install.connect("status-changed", self._on_status_changed) - self._progress_install.connect("status-started", + self._progress_install.connect("status-started", self._on_status_started) - self._progress_install.connect("status-finished", + self._progress_install.connect("status-finished", self._on_status_finished) - self._progress_install.connect("status-timeout", + self._progress_install.connect("status-timeout", self._on_status_timeout) - self._progress_install.connect("status-error", + self._progress_install.connect("status-error", self._on_status_timeout) - self._progress_install.connect("status-conffile", + self._progress_install.connect("status-conffile", self._on_status_timeout) self._progress_dpkg_install = GDpkgInstallProgress(self._terminal) self._progress_dpkg_install.connect("status-changed", self._on_status_changed) - self._progress_dpkg_install.connect("status-started", + self._progress_dpkg_install.connect("status-started", self._on_status_started) - self._progress_dpkg_install.connect("status-finished", + self._progress_dpkg_install.connect("status-finished", self._on_status_finished) - self._progress_dpkg_install.connect("status-timeout", + self._progress_dpkg_install.connect("status-timeout", self._on_status_timeout) - self._progress_dpkg_install.connect("status-error", + self._progress_dpkg_install.connect("status-error", self._on_status_timeout) - self._progress_dpkg_install.connect("status-conffile", + self._progress_dpkg_install.connect("status-conffile", self._on_status_timeout) def clear(self): - """ - Reset all status information - """ + """Reset all status information.""" self._label.set_label("") - self._progress.set_fraction(0) + self._progressbar.set_fraction(0) self._expander.set_expanded(False) @property def open(self): - """ - Return the cache opening progress handler. - """ + """Return the cache opening progress handler.""" return self._progress_open @property def install(self): - """ - Return the install progress handler - """ + """Return the install progress handler.""" return self._progress_install @property def dpkg_install(self): - """ - Return the install progress handler for dpkg - """ + """Return the install progress handler for dpkg.""" return self._dpkg_progress_install - + @property def fetch(self): - """ - Return the fetch progress handler - """ + """Return the fetch progress handler.""" return self._progress_fetch def _on_status_started(self, progress): + """Called when something starts.""" self._on_status_changed(progress, _("Starting..."), 0) while gtk.events_pending(): gtk.main_iteration() def _on_status_finished(self, progress): + """Called when something finished.""" self._on_status_changed(progress, _("Complete"), 100) while gtk.events_pending(): gtk.main_iteration() def _on_status_changed(self, progress, status, percent): + """Called when the status changed.""" self._label.set_text(status) if percent is None: self._progressbar.pulse() @@ -328,18 +369,18 @@ class GtkAptProgress(gtk.VBox): gtk.main_iteration() def _on_status_timeout(self, progress): - selt._expander.set_expanded(True) + """Called when timeout happens.""" + self._expander.set_expanded(True) while gtk.events_pending(): gtk.main_iteration() def cancel_download(self): - """ - Cancel a currently running download - """ + """Cancel a currently running download.""" self._progress_fetch.cancel() def show_terminal(self, expanded=False): - """ + """Show the expander for the terminal. + Show an expander with a terminal widget which provides a way to interact with dpkg """ @@ -350,31 +391,33 @@ class GtkAptProgress(gtk.VBox): gtk.main_iteration() def hide_terminal(self): - """ - Hide the expander with the terminal widget - """ + """Hide the expander with the terminal widget.""" self._expander.hide() while gtk.events_pending(): gtk.main_iteration() def show(self): + """Show the Box""" gtk.HBox.show(self) self._label.show() self._progressbar.show() while gtk.events_pending(): gtk.main_iteration() -if __name__ == "__main__": + +def _test(): + """Test function""" import sys - import debfile + + from apt.debfile import DebPackage win = gtk.Window() - apt_progress = GAptProgress() + apt_progress = GtkAptProgress() win.set_title("GtkAptProgress Demo") win.add(apt_progress) apt_progress.show() win.show() - cache = apt.cache.Cache(apt_progress.get_open_progress()) + cache = apt.cache.Cache(apt_progress.open) pkg = cache["xterm"] if pkg.isInstalled: pkg.markDelete() @@ -382,13 +425,16 @@ if __name__ == "__main__": pkg.markInstall() apt_progress.show_terminal(True) try: - cache.commit(apt_progress.get_fetch_progress(), - apt_progress.get_install_progress()) - except: - pass + cache.commit(apt_progress.fetch, apt_progress.install) + except Exception, exc: + print >> sys.stderr, "Exception happened:", exc if len(sys.argv) > 1: deb = DebPackage(sys.argv[1], cache) - deb.install(apt_progress.get_dpkg_install_progress()) + deb.install(apt_progress.dpkg_install) gtk.main() + +if __name__ == "__main__": + _test() + # vim: ts=4 et sts=4 diff --git a/apt/package.py b/apt/package.py index 70ddbb1a..7817c64c 100644 --- a/apt/package.py +++ b/apt/package.py @@ -1,73 +1,153 @@ # package.py - apt package abstraction -# +# # Copyright (c) 2005 Canonical -# +# # Author: Michael Vogt <michael.vogt@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA - +"""Functionality related to packages.""" +import gettext import httplib import sys -import random import re import socket -import string import urllib2 import apt_pkg + +__all__ = 'BaseDependency', 'Dependency', 'Origin', 'Package', 'Record' + + # Set a timeout for the changelog download socket.setdefaulttimeout(2) -#from gettext import gettext as _ -import gettext -def _(s): return gettext.dgettext("python-apt", s) + +def _(string): + """Return the translation of the string.""" + return gettext.dgettext("python-apt", string) + class BaseDependency(object): - " a single dependency " + """A single dependency. + + Attributes defined here: + name - The name of the dependency + relation - The relation (>>,>=,==,<<,<=,) + version - The version depended on + preDepend - Boolean value whether this is a pre-dependency. + """ + def __init__(self, name, rel, ver, pre): self.name = name self.relation = rel self.version = ver self.preDepend = pre + class Dependency(object): + """Represent an Or-group of dependencies. + + Attributes defined here: + or_dependencies - The possible choices + """ + def __init__(self, alternatives): self.or_dependencies = alternatives + +class Origin(object): + """The origin of a version. + + Attributes defined here: + archive - The archive (eg. unstable) + component - The component (eg. main) + label - The Label, as set in the Release file + origin - The Origin, as set in the Release file + site - The hostname of the site. + trusted - Boolean value whether this is trustworthy. + """ + + def __init__(self, pkg, VerFileIter): + self.archive = VerFileIter.Archive + self.component = VerFileIter.Component + self.label = VerFileIter.Label + self.origin = VerFileIter.Origin + self.site = VerFileIter.Site + # check the trust + indexfile = pkg._list.FindIndex(VerFileIter) + if indexfile and indexfile.IsTrusted: + self.trusted = True + else: + self.trusted = False + + def __repr__(self): + return ("<Origin component:'%s' archive:'%s' origin:'%s' label:'%s'" + "site:'%s' isTrusted:'%s'>") % (self.component, self.archive, + self.origin, self.label, + self.site, self.trusted) + + class Record(object): - """ represents a pkgRecord, can be accessed like a - dictionary and gives the original package record - if accessed as a string """ - def __init__(self, s): - self._str = s - self._rec = apt_pkg.ParseSection(s) + """Represent a pkgRecord. + + It can be accessed like a dictionary and can also give the original package + record if accessed as a string. + """ + + def __init__(self, record_str): + self._rec = apt_pkg.ParseSection(record_str) + def __str__(self): - return self._str + return str(self._rec) + def __getitem__(self, key): - k = self._rec.get(key) - if k is None: - raise KeyError - return k + return self._rec[key] + + def __contains__(self, key): + return self._rec.has_key(key) + + def __iter__(self): + return iter(self._rec.keys()) + + def iteritems(self): + """An iterator over the (key, value) items of the record.""" + for key in self._rec.keys(): + yield key, self._rec[key] + + def get(self, key, default=None): + """Return record[key] if key in record, else `default`. + + The parameter `default` must be either a string or None. + """ + return self._rec.get(key, default) + def has_key(self, key): + """deprecated form of 'key in x'.""" return self._rec.has_key(key) + class Package(object): - """ This class represents a package in the cache + """Representation of a package in a cache. + + This class provides methods and properties for working with a package. It + lets you mark the package for installation, check if it is installed, and + much more. """ + def __init__(self, cache, depcache, records, sourcelist, pcache, pkgiter): """ Init the Package object """ self._cache = cache # low level cache @@ -77,175 +157,186 @@ class Package(object): self._list = sourcelist # sourcelist self._pcache = pcache # python cache in cache.py self._changelog = "" # Cached changelog - pass - # helper def _lookupRecord(self, UseCandidate=True): - """ internal helper that moves the Records to the right - position, must be called before _records is accessed """ + """Internal helper that moves the Records to the right position. + + Must be called before _records is accessed. + """ if UseCandidate: ver = self._depcache.GetCandidateVer(self._pkg) else: ver = self._pkg.CurrentVer # check if we found a version - if ver == None: - #print "No version for: %s (Candidate: %s)" % (self._pkg.Name, UseCandidate) + if ver is None: + #print "No version for: %s (Candidate: %s)" % (self._pkg.Name, + # UseCandidate) return False - - if ver.FileList == None: + + if ver.FileList is None: print "No FileList for: %s " % self._pkg.Name() return False f, index = ver.FileList.pop(0) - self._records.Lookup((f,index)) + self._records.Lookup((f, index)) return True - - # basic information (implemented as properties) - - # FIXME once python2.3 is dropped we can use @property instead - # of name = property(name) - + @property def name(self): - """ Return the name of the package """ + """Return the name of the package.""" return self._pkg.Name - name = property(name) + @property def id(self): - """ Return a uniq ID for the pkg, can be used to store - additional information about the pkg """ + """Return a uniq ID for the package. + + This can be used eg. to store additional information about the pkg.""" + return self._pkg.ID + + def __hash__(self): + """Return the hash of the object. + + This returns the same value as ID, which is unique.""" return self._pkg.ID - id = property(id) + @property def installedVersion(self): - """ Return the installed version as string """ + """Return the installed version as string.""" ver = self._pkg.CurrentVer - if ver != None: + if ver is not None: return ver.VerStr else: return None - installedVersion = property(installedVersion) + @property def candidateVersion(self): - """ Return the candidate version as string """ + """Return the candidate version as string.""" ver = self._depcache.GetCandidateVer(self._pkg) - if ver != None: + if ver is not None: return ver.VerStr else: return None - candidateVersion = property(candidateVersion) def _getDependencies(self, ver): + """Get the dependencies for a given version of a package.""" depends_list = [] depends = ver.DependsList for t in ["PreDepends", "Depends"]: - if not depends.has_key(t): - continue - for depVerList in depends[t]: - base_deps = [] - for depOr in depVerList: - base_deps.append(BaseDependency(depOr.TargetPkg.Name, depOr.CompType, depOr.TargetVer, (t == "PreDepends"))) - depends_list.append(Dependency(base_deps)) + try: + for depVerList in depends[t]: + base_deps = [] + for depOr in depVerList: + base_deps.append(BaseDependency(depOr.TargetPkg.Name, + depOr.CompType, depOr.TargetVer, + (t == "PreDepends"))) + depends_list.append(Dependency(base_deps)) + except KeyError: + pass return depends_list - + + @property def candidateDependencies(self): - """ return a list of candidate dependencies """ + """Return a list of candidate dependencies.""" candver = self._depcache.GetCandidateVer(self._pkg) - if candver == None: + if candver is None: return [] return self._getDependencies(candver) - candidateDependencies = property(candidateDependencies) - + + @property def installedDependencies(self): - """ return a list of installed dependencies """ + """Return a list of installed dependencies.""" ver = self._pkg.CurrentVer - if ver == None: + if ver is None: return [] return self._getDependencies(ver) - installedDependencies = property(installedDependencies) + @property def architecture(self): + """Return the Architecture of the package""" if not self._lookupRecord(): return None sec = apt_pkg.ParseSection(self._records.Record) - if sec.has_key("Architecture"): + try: return sec["Architecture"] - return None - architecture = property(architecture) + except KeyError: + return None def _downloadable(self, useCandidate=True): - """ helper, return if the version is downloadable """ + """Return True if the package is downloadable.""" if useCandidate: ver = self._depcache.GetCandidateVer(self._pkg) else: ver = self._pkg.CurrentVer - if ver == None: + if ver is None: return False return ver.Downloadable + + @property def candidateDownloadable(self): - " returns if the canidate is downloadable " - return self._downloadable(useCandidate=True) - candidateDownloadable = property(candidateDownloadable) + """Return True if the candidate is downloadable.""" + return self._downloadable(True) + @property def installedDownloadable(self): - " returns if the installed version is downloadable " - return self._downloadable(useCandidate=False) - installedDownloadable = property(installedDownloadable) + """Return True if the installed version is downloadable.""" + return self._downloadable(False) + @property def sourcePackageName(self): - """ Return the source package name as string """ + """Return the source package name as string.""" if not self._lookupRecord(): - if not self._lookupRecord(UseCandidate=False): + if not self._lookupRecord(False): return self._pkg.Name src = self._records.SourcePkg if src != "": return src else: return self._pkg.Name - sourcePackageName = property(sourcePackageName) + @property def homepage(self): - """ Return the homepage field as string """ + """Return the homepage field as string.""" if not self._lookupRecord(): return None return self._records.Homepage - homepage = property(homepage) + @property def section(self): - """ Return the section of the package""" + """Return the section of the package.""" return self._pkg.Section - section = property(section) + @property def priority(self): - """ Return the priority (of the candidate version)""" + """Return the priority (of the candidate version).""" ver = self._depcache.GetCandidateVer(self._pkg) if ver: return ver.PriorityStr else: return None - priority = property(priority) + @property def installedPriority(self): - """ Return the priority (of the installed version)""" + """Return the priority (of the installed version).""" ver = self._depcache.GetCandidateVer(self._pkg) if ver: return ver.PriorityStr else: return None - installedPriority = property(installedPriority) + @property def summary(self): - """ Return the short description (one line summary) """ + """Return the short description (one line summary).""" if not self._lookupRecord(): return "" ver = self._depcache.GetCandidateVer(self._pkg) desc_iter = ver.TranslatedDescription self._records.Lookup(desc_iter.FileList.pop(0)) return self._records.ShortDesc - summary = property(summary) + @property def description(self, format=True, useDots=False): - """ + """Return the formatted long description. + Return the formated long description according to the Debian policy (Chapter 5.6.13). See http://www.debian.org/doc/debian-policy/ch-controlfields.html @@ -261,14 +352,15 @@ class Package(object): self._records.Lookup(desc_iter.FileList.pop(0)) desc = "" try: - s = unicode(self._records.LongDesc,"utf-8") - except UnicodeDecodeError,e: - s = _("Invalid unicode in description for '%s' (%s). " - "Please report.") % (self.name,e) - lines = string.split(s, "\n") + dsc = unicode(self._records.LongDesc, "utf-8") + except UnicodeDecodeError, err: + dsc = _("Invalid unicode in description for '%s' (%s). " + "Please report.") % (self.name, err) + lines = dsc.split("\n") for i in range(len(lines)): # Skip the first line, since its a duplication of the summary - if i == 0: continue + if i == 0: + continue raw_line = lines[i] if raw_line.strip() == ".": # The line is just line break @@ -296,138 +388,145 @@ class Package(object): # Add current line to the description desc += line return desc - description = property(description) + @property def rawDescription(self): - """ return the long description (raw)""" + """return the long description (raw).""" if not self._lookupRecord(): return "" return self._records.LongDesc - rawDescription = property(rawDescription) - + + @property def candidateRecord(self): - " return the full pkgrecord as string of the candidate version " + """Return the Record of the candidate version of the package.""" if not self._lookupRecord(True): return None return Record(self._records.Record) - candidateRecord = property(candidateRecord) + @property def installedRecord(self): - " return the full pkgrecord as string of the installed version " + """Return the Record of the candidate version of the package.""" if not self._lookupRecord(False): return None return Record(self._records.Record) - installedRecord = property(installedRecord) # depcache states + + @property def markedInstall(self): - """ Package is marked for install """ + """Return True if the package is marked for install.""" return self._depcache.MarkedInstall(self._pkg) - markedInstall = property(markedInstall) + @property def markedUpgrade(self): - """ Package is marked for upgrade """ + """Return True if the package is marked for upgrade.""" return self._depcache.MarkedUpgrade(self._pkg) - markedUpgrade = property(markedUpgrade) + @property def markedDelete(self): - """ Package is marked for delete """ + """Return True if the package is marked for delete.""" return self._depcache.MarkedDelete(self._pkg) - markedDelete = property(markedDelete) + @property def markedKeep(self): - """ Package is marked for keep """ + """Return True if the package is marked for keep.""" return self._depcache.MarkedKeep(self._pkg) - markedKeep = property(markedKeep) + @property def markedDowngrade(self): """ Package is marked for downgrade """ return self._depcache.MarkedDowngrade(self._pkg) - markedDowngrade = property(markedDowngrade) + @property def markedReinstall(self): - """ Package is marked for reinstall """ + """Return True if the package is marked for reinstall.""" return self._depcache.MarkedReinstall(self._pkg) - markedReinstall = property(markedReinstall) + @property def isInstalled(self): - """ Package is installed """ - return (self._pkg.CurrentVer != None) - isInstalled = property(isInstalled) + """Return True if the package is installed.""" + return (self._pkg.CurrentVer is not None) + @property def isUpgradable(self): - """ Package is upgradable """ + """Return True if the package is upgradable.""" return self.isInstalled and self._depcache.IsUpgradable(self._pkg) - isUpgradable = property(isUpgradable) + @property def isAutoRemovable(self): - """ - Package is installed as a automatic dependency and is - no longer required + """Return True if the package is no longer required. + + If the package has been installed automatically as a dependency of + another package, and if no packages depend on it anymore, the package + is no longer required. """ return self.isInstalled and self._depcache.IsGarbage(self._pkg) - isAutoRemovable = property(isAutoRemovable) - # size + # sizes + + @property def packageSize(self): - """ The size of the candidate deb package """ + """Return the size of the candidate deb package.""" ver = self._depcache.GetCandidateVer(self._pkg) return ver.Size - packageSize = property(packageSize) + @property def installedPackageSize(self): - """ The size of the installed deb package """ + """Return the size of the installed deb package.""" ver = self._pkg.CurrentVer return ver.Size - installedPackageSize = property(installedPackageSize) + @property def candidateInstalledSize(self, UseCandidate=True): - """ The size of the candidate installed package """ + """Return the size of the candidate installed package.""" ver = self._depcache.GetCandidateVer(self._pkg) - candidateInstalledSize = property(candidateInstalledSize) + @property def installedSize(self): - """ The size of the currently installed package """ + """Return the size of the currently installed package.""" ver = self._pkg.CurrentVer if ver is None: return 0 return ver.InstalledSize - installedSize = property(installedSize) + @property def installedFiles(self): - """ - Return the list of unicode names of the files which have + """Return a list of files installed by the package. + + Return a list of unicode names of the files which have been installed by this package """ path = "/var/lib/dpkg/info/%s.list" % self.name try: - list = open(path) - files = list.read().decode().split("\n") - list.close() - except: + file_list = open(path) + try: + return file_list.read().decode().split("\n") + finally: + file_list.close() + except EnvironmentError: return [] - return files - installedFiles = property(installedFiles) def getChangelog(self, uri=None, cancel_lock=None): """ - Download the changelog of the package and return it as unicode - string - - uri: Is the uri to the changelog file. The following named variables - will be substituted: src_section, prefix, src_pkg and src_ver - For example the Ubuntu changelog: - uri = "http://changelogs.ubuntu.com/changelogs/pool" \\ - "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\ - "/%(src_pkg)s_%(src_ver)s/changelog" - cancel_lock: If this threading.Lock() is set, the download will be - canceled + Download the changelog of the package and return it as unicode + string. + + The parameter `uri` refers to the uri of the changelog file. It may + contain multiple named variables which will be substitued. These + variables are (src_section, prefix, src_pkg, src_ver). An example is + the Ubuntu changelog: + "http://changelogs.ubuntu.com/changelogs/pool" \\ + "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\ + "/%(src_pkg)s_%(src_ver)s/changelog" + + The parameter `cancel_lock` refers to an instance of threading.Lock, + which if set, prevents the download. """ # Return a cached changelog if available if self._changelog != "": return self._changelog - if uri == None: + if uri is None: if self.candidateOrigin[0].origin == "Debian": uri = "http://packages.debian.org/changelogs/pool" \ "/%(src_section)s/%(prefix)s/%(src_pkg)s" \ @@ -442,7 +541,7 @@ class Package(object): # get the src package name src_pkg = self.sourcePackageName - # assume "main" section + # assume "main" section src_section = "main" # use the section of the candidate as a starting point section = self._depcache.GetCandidateVer(self._pkg).Section @@ -452,9 +551,10 @@ class Package(object): src_ver = self.candidateVersion #print "bin: %s" % binver try: + # FIXME: This try-statement is too long ... # try to get the source version of the pkg, this differs # for some (e.g. libnspr4 on ubuntu) - # this feature only works if the correct deb-src are in the + # this feature only works if the correct deb-src are in the # sources.list # otherwise we fall back to the binary version number src_records = apt_pkg.GetPkgSrcRecords() @@ -471,7 +571,7 @@ class Package(object): else: # fail into the error handler raise SystemError - except SystemError, e: + except SystemError: src_ver = bin_ver l = section.split("/") @@ -484,26 +584,27 @@ class Package(object): prefix = "lib" + src_pkg[3] # stip epoch - l = string.split(src_ver,":") + l = src_ver.split(":") if len(l) > 1: src_ver = "".join(l[1:]) - uri = uri % {"src_section" : src_section, - "prefix" : prefix, - "src_pkg" : src_pkg, - "src_ver" : src_ver} + uri = uri % {"src_section": src_section, + "prefix": prefix, + "src_pkg": src_pkg, + "src_ver": src_ver} try: # Check if the download was canceled - if cancel_lock and cancel_lock.isSet(): return "" + if cancel_lock and cancel_lock.isSet(): + return "" changelog_file = urllib2.urlopen(uri) # do only get the lines that are new changelog = "" regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg)) - i=0 while True: # Check if the download was canceled - if cancel_lock and cancel_lock.isSet(): return "" + if cancel_lock and cancel_lock.isSet(): + return "" # Read changelog line by line line_raw = changelog_file.readline() if line_raw == "": @@ -519,7 +620,7 @@ class Package(object): # and from changelog too installed = self.installedVersion if installed and ":" in installed: - installed = installed.split(":",1)[1] + installed = installed.split(":", 1)[1] changelog_ver = match.group(1) if changelog_ver and ":" in changelog_ver: changelog_ver = changelog_ver.split(":", 1)[1] @@ -533,58 +634,47 @@ class Package(object): if len(changelog) == 0: changelog = _("The list of changes is not available") self._changelog = changelog - except urllib2.HTTPError,e: + + # FIXME: Ubuntu-specific part. + except urllib2.HTTPError: return _("The list of changes is not available yet.\n\n" "Please use http://launchpad.net/ubuntu/+source/%s/%s/" "+changelog\n" "until the changes become available or try again " - "later.") % (srcpkg, srcver), - except IOError, httplib.BadStatusLine: - return _("Failed to download the list of changes. \nPlease " - "check your Internet connection.") + "later.") % (src_pkg, src_ver) + except (IOError, httplib.BadStatusLine): + return _("Failed to download the list of changes. \nPlease " + "check your Internet connection.") return self._changelog - # canidate origin - class Origin: - def __init__(self, pkg, VerFileIter): - self.component = VerFileIter.Component - self.archive = VerFileIter.Archive - self.origin = VerFileIter.Origin - self.label = VerFileIter.Label - self.site = VerFileIter.Site - # check the trust - indexfile = pkg._list.FindIndex(VerFileIter) - if indexfile and indexfile.IsTrusted: - self.trusted = True - else: - self.trusted = False - def __repr__(self): - return "component: '%s' archive: '%s' origin: '%s' label: '%s' " \ - "site '%s' isTrusted: '%s'"% (self.component, self.archive, - self.origin, self.label, - self.site, self.trusted) - + @property def candidateOrigin(self): + """Return the Origin() of the candidate version.""" ver = self._depcache.GetCandidateVer(self._pkg) if not ver: return None origins = [] - for (verFileIter,index) in ver.FileList: - origins.append(self.Origin(self, verFileIter)) + for (verFileIter, index) in ver.FileList: + origins.append(Origin(self, verFileIter)) return origins - candidateOrigin = property(candidateOrigin) # depcache actions + def markKeep(self): - """ mark a package for keep """ + """Mark a package for keep.""" self._pcache.cachePreChange() self._depcache.MarkKeep(self._pkg) self._pcache.cachePostChange() + def markDelete(self, autoFix=True, purge=False): - """ mark a package for delete. Run the resolver if autoFix is set. - Mark the package as purge (remove with configuration) if 'purge' - is set. - """ + """Mark a package for install. + + If autoFix is True, the resolver will be run, trying to fix broken + packages. This is the default. + + If purge is True, remove the configuration files of the package as + well. The default is to keep the configuration. + """ self._pcache.cachePreChange() self._depcache.MarkDelete(self._pkg, purge) # try to fix broken stuffsta @@ -596,10 +686,20 @@ class Package(object): Fix.InstallProtect() Fix.Resolve() self._pcache.cachePostChange() + def markInstall(self, autoFix=True, autoInst=True, fromUser=True): - """ mark a package for install. Run the resolver if autoFix is set, - automatically install required dependencies if autoInst is set - record it as automatically installed when fromuser is set to false + """Mark a package for install. + + If autoFix is True, the resolver will be run, trying to fix broken + packages. This is the default. + + If autoInst is True, the dependencies of the packages will be installed + automatically. This is the default. + + If fromUser is True, this package will not be marked as automatically + installed. This is the default. Set it to False if you want to be able + to remove the package at a later stage if no other package depends on + it. """ self._pcache.cachePreChange() self._depcache.MarkInstall(self._pkg, autoInst, fromUser) @@ -610,24 +710,33 @@ class Package(object): fixer.Protect(self._pkg) fixer.Resolve(True) self._pcache.cachePostChange() + def markUpgrade(self): - """ mark a package for upgrade """ + """Mark a package for upgrade.""" if self.isUpgradable: self.markInstall() else: # FIXME: we may want to throw a exception here - sys.stderr.write("MarkUpgrade() called on a non-upgrable pkg: '%s'\n" %self._pkg.Name) + sys.stderr.write(("MarkUpgrade() called on a non-upgrable pkg: " + "'%s'\n") % self._pkg.Name) def commit(self, fprogress, iprogress): - """ commit the changes, need a FetchProgress and InstallProgress - object as argument + """Commit the changes. + + The parameter `fprogress` refers to a FetchProgress() object, as + found in apt.progress. + + The parameter `iprogress` refers to an InstallProgress() object, as + found in apt.progress. """ self._depcache.Commit(fprogress, iprogress) - -# self-test -if __name__ == "__main__": + +def _test(): + """Self-test.""" print "Self-test for the Package modul" + import random + import apt apt_pkg.init() cache = apt_pkg.GetCache() depcache = apt_pkg.GetDepCache(cache) @@ -653,35 +762,38 @@ if __name__ == "__main__": print "PackageSize: %s " % pkg.packageSize print "Dependencies: %s" % pkg.installedDependencies for dep in pkg.candidateDependencies: - print ",".join(["%s (%s) (%s) (%s)" % (o.name,o.version,o.relation, o.preDepend) for o in dep.or_dependencies]) + print ",".join("%s (%s) (%s) (%s)" % (o.name, o.version, o.relation, + o.preDepend) for o in dep.or_dependencies) print "arch: %s" % pkg.architecture print "homepage: %s" % pkg.homepage - print "rec: ",pkg.candidateRecord + print "rec: ", pkg.candidateRecord # now test install/remove - import apt progress = apt.progress.OpTextProgress() cache = apt.Cache(progress) - for i in [True, False]: + for i in True, False: print "Running install on random upgradable pkgs with AutoFix: %s " % i - for name in cache.keys(): - pkg = cache[name] + for pkg in cache: if pkg.isUpgradable: - if random.randint(0,1) == 1: + if random.randint(0, 1) == 1: pkg.markInstall(i) print "Broken: %s " % cache._depcache.BrokenCount print "InstCount: %s " % cache._depcache.InstCount print # get a new cache - for i in [True, False]: + for i in True, False: print "Randomly remove some packages with AutoFix: %s" % i cache = apt.Cache(progress) for name in cache.keys(): - if random.randint(0,1) == 1: + if random.randint(0, 1) == 1: try: cache[name].markDelete(i) except SystemError: print "Error trying to remove: %s " % name print "Broken: %s " % cache._depcache.BrokenCount print "DelCount: %s " % cache._depcache.DelCount + +# self-test +if __name__ == "__main__": + _test() diff --git a/apt/progress.py b/apt/progress.py index a8ab76b6..51eb2426 100644 --- a/apt/progress.py +++ b/apt/progress.py @@ -1,61 +1,82 @@ # Progress.py - progress reporting classes -# +# # Copyright (c) 2005 Canonical -# +# # Author: Michael Vogt <michael.vogt@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA +"""progress reporting classes. -import sys +This module provides classes for progress reporting. They can be used with +e.g., for reporting progress on the cache opening process, the cache update +progress, or the package install progress. +""" + +import errno +import fcntl import os import re -import fcntl -import string -from errno import * import select +import sys + import apt_pkg -import apt + +__all__ = ('CdromProgress', 'DpkgInstallProgress', 'DumbInstallProgress', + 'FetchProgress', 'InstallProgress', 'OpProgress', 'OpTextProgress', + 'TextFetchProgress') + class OpProgress(object): - """ Abstract class to implement reporting on cache opening - Subclass this class to implement simple Operation progress reporting + """Abstract class to implement reporting on cache opening. + + Subclass this class to implement simple Operation progress reporting. """ + def __init__(self): - pass + self.op = None + self.subOp = None + def update(self, percent): - pass + """Called periodically to update the user interface.""" + def done(self): - pass + """Called once an operation has been completed.""" + class OpTextProgress(OpProgress): - """ A simple text based cache open reporting class """ + """A simple text based cache open reporting class.""" + def __init__(self): OpProgress.__init__(self) + def update(self, percent): - sys.stdout.write("\r%s: %.2i " % (self.subOp,percent)) + """Called periodically to update the user interface.""" + sys.stdout.write("\r%s: %.2i " % (self.subOp, percent)) sys.stdout.flush() + def done(self): + """Called once an operation has been completed.""" sys.stdout.write("\r%s: Done\n" % self.op) - class FetchProgress(object): - """ Report the download/fetching progress - Subclass this class to implement fetch progress reporting + """Report the download/fetching progress. + + Subclass this class to implement fetch progress reporting """ # download status constants @@ -64,46 +85,71 @@ class FetchProgress(object): dlFailed = 2 dlHit = 3 dlIgnored = 4 - dlStatusStr = {dlDone : "Done", - dlQueued : "Queued", - dlFailed : "Failed", - dlHit : "Hit", - dlIgnored : "Ignored"} - + dlStatusStr = {dlDone: "Done", + dlQueued: "Queued", + dlFailed: "Failed", + dlHit: "Hit", + dlIgnored: "Ignored"} + def __init__(self): self.eta = 0.0 self.percent = 0.0 - pass - + # Make checking easier + self.currentBytes = 0 + self.currentItems = 0 + self.totalBytes = 0 + self.totalItems = 0 + self.currentCPS = 0 + def start(self): - pass - + """Called when the fetching starts.""" + def stop(self): - pass - + """Called when all files have been fetched.""" + def updateStatus(self, uri, descr, shortDescr, status): - pass + """Called when the status of an item changes. + + This happens eg. when the downloads fails or is completed. + """ def pulse(self): - """ called periodically (to update the gui), importend to - return True to continue or False to cancel + """Called periodically to update the user interface. + + Return True to continue or False to cancel. """ - self.percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems) + self.percent = (((self.currentBytes + self.currentItems) * 100.0) / + float(self.totalBytes + self.totalItems)) if self.currentCPS > 0: - self.eta = (self.totalBytes-self.currentBytes)/float(self.currentCPS) + self.eta = ((self.totalBytes - self.currentBytes) / + float(self.currentCPS)) return True + def mediaChange(self, medium, drive): - pass + """react to media change events.""" + class TextFetchProgress(FetchProgress): """ Ready to use progress object for terminal windows """ + def __init__(self): + FetchProgress.__init__(self) self.items = {} + def updateStatus(self, uri, descr, shortDescr, status): + """Called when the status of an item changes. + + This happens eg. when the downloads fails or is completed. + """ if status != self.dlQueued: print "\r%s %s" % (self.dlStatusStr[status], descr) self.items[uri] = status + def pulse(self): + """Called periodically to update the user interface. + + Return True to continue or False to cancel. + """ FetchProgress.pulse(self) if self.currentCPS > 0: s = "[%2.f%%] %sB/s %s" % (self.percent, @@ -114,102 +160,121 @@ class TextFetchProgress(FetchProgress): print "\r%s" % (s), sys.stdout.flush() return True + def stop(self): - print "\rDone downloading " + """Called when all files have been fetched.""" + print "\rDone downloading " + def mediaChange(self, medium, drive): - """ react to media change events """ - res = True; - print "Media change: please insert the disc labeled \ - '%s' in the drive '%s' and press enter" % (medium,drive) - s = sys.stdin.readline() - if(s == 'c' or s == 'C'): - res = false; - return res + """react to media change events.""" + print ("Media change: please insert the disc labeled " + "'%s' in the drive '%s' and press enter") % (medium, drive) + + return raw_input() not in ('c', 'C') + class DumbInstallProgress(object): - """ Report the install progress - Subclass this class to implement install progress reporting + """Report the install progress. + + Subclass this class to implement install progress reporting. """ - def __init__(self): - pass + def startUpdate(self): - pass + """Start update.""" + def run(self, pm): + """Start installation.""" return pm.DoInstall() + def finishUpdate(self): - pass + """Called when update has finished.""" + def updateInterface(self): - pass + """Called periodically to update the user interface""" + class InstallProgress(DumbInstallProgress): - """ A InstallProgress that is pretty useful. - It supports the attributes 'percent' 'status' and callbacks - for the dpkg errors and conffiles and status changes - """ + """An InstallProgress that is pretty useful. + + It supports the attributes 'percent' 'status' and callbacks for the dpkg + errors and conffiles and status changes. + """ + def __init__(self): DumbInstallProgress.__init__(self) self.selectTimeout = 0.1 (read, write) = os.pipe() - self.writefd=write + self.writefd = write self.statusfd = os.fdopen(read, "r") - fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL,os.O_NONBLOCK) + fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) self.read = "" self.percent = 0.0 self.status = "" + def error(self, pkg, errormsg): - " called when a error is detected during the install " - pass - def conffile(self,current,new): - " called when a conffile question from dpkg is detected " - pass + """Called when a error is detected during the install.""" + + def conffile(self, current, new): + """Called when a conffile question from dpkg is detected.""" + def statusChange(self, pkg, percent, status): - " called when the status changed " - pass + """Called when the status changed.""" + def updateInterface(self): - if self.statusfd != None: - try: - while not self.read.endswith("\n"): - self.read += os.read(self.statusfd.fileno(),1) - except OSError, (errno,errstr): - # resource temporarly unavailable is ignored - if errno != EAGAIN and errnor != EWOULDBLOCK: - print errstr - if self.read.endswith("\n"): - s = self.read - #print s - try: - (status, pkg, percent, status_str) = string.split(s, ":",3) - except ValueError, e: - # silently ignore lines that can't be parsed - self.read = "" - return - #print "percent: %s %s" % (pkg, float(percent)/100.0) - if status == "pmerror": - self.error(pkg,status_str) - elif status == "pmconffile": - # we get a string like this: - # 'current-conffile' 'new-conffile' useredited distedited - match = re.compile("\s*\'(.*)\'\s*\'(.*)\'.*").match(status_str) - if match: - self.conffile(match.group(1), match.group(2)) - elif status == "pmstatus": - if float(percent) != self.percent or \ - status_str != self.status: - self.statusChange(pkg, float(percent), status_str.strip()) - self.percent = float(percent) - self.status = string.strip(status_str) - self.read = "" + """Called periodically to update the interface.""" + if self.statusfd is None: + return + try: + while not self.read.endswith("\n"): + self.read += os.read(self.statusfd.fileno(), 1) + except OSError, (errno_, errstr): + # resource temporarly unavailable is ignored + if errno_ != errno.EAGAIN and errno_ != errno.EWOULDBLOCK: + print errstr + if not self.read.endswith("\n"): + return + + s = self.read + #print s + try: + (status, pkg, percent, status_str) = s.split(":", 3) + except ValueError: + # silently ignore lines that can't be parsed + self.read = "" + return + #print "percent: %s %s" % (pkg, float(percent)/100.0) + if status == "pmerror": + self.error(pkg, status_str) + elif status == "pmconffile": + # we get a string like this: + # 'current-conffile' 'new-conffile' useredited distedited + match = re.match("\s*\'(.*)\'\s*\'(.*)\'.*", status_str) + if match: + self.conffile(match.group(1), match.group(2)) + elif status == "pmstatus": + if float(percent) != self.percent or status_str != self.status: + self.statusChange(pkg, float(percent), + status_str.strip()) + self.percent = float(percent) + self.status = status_str.strip() + self.read = "" + def fork(self): + """Fork.""" return os.fork() + def waitChild(self): + """Wait for child progress to exit.""" while True: - select.select([self.statusfd],[],[], self.selectTimeout) + select.select([self.statusfd], [], [], self.selectTimeout) self.updateInterface() - (pid, res) = os.waitpid(self.child_pid,os.WNOHANG) + (pid, res) = os.waitpid(self.child_pid, os.WNOHANG) if pid == self.child_pid: break return res + def run(self, pm): + """Start installing.""" pid = self.fork() if pid == 0: # child @@ -219,29 +284,31 @@ class InstallProgress(DumbInstallProgress): res = self.waitChild() return os.WEXITSTATUS(res) -class CdromProgress: - """ Report the cdrom add progress - Subclass this class to implement cdrom add progress reporting + +class CdromProgress(object): + """Report the cdrom add progress. + + Subclass this class to implement cdrom add progress reporting. """ + def __init__(self): pass + def update(self, text, step): - """ update is called regularly so that the gui can be redrawn """ - pass + """Called periodically to update the user interface.""" + def askCdromName(self): - pass + """Called to ask for the name of the cdrom.""" + def changeCdrom(self): - pass + """Called to ask for the cdrom to be changed.""" class DpkgInstallProgress(InstallProgress): - """ - Progress handler for a local Debian package installation - """ + """Progress handler for a local Debian package installation.""" + def run(self, debfile): - """ - Start installing the given Debian package - """ + """Start installing the given Debian package.""" self.debfile = debfile self.debname = os.path.basename(debfile).split("_")[0] pid = self.fork() @@ -255,46 +322,35 @@ class DpkgInstallProgress(InstallProgress): return res def updateInterface(self): - """ - Process status messages from dpkg - """ - if self.statusfd != None: - while True: - try: - self.read += os.read(self.statusfd.fileno(),1) - except OSError, (errno,errstr): - # resource temporarly unavailable is ignored - if errno != 11: - print errstr - break - if self.read.endswith("\n"): - statusl = string.split(self.read, ":") - if len(statusl) < 3: - print "got garbage from dpkg: '%s'" % read - self.read = "" - break - status = statusl[2].strip() - #print status - if status == "error": - self.error(self.debname, status) - elif status == "conffile-prompt": - # we get a string like this: - # 'current-conffile' 'new-conffile' useredited distedited - match = re.compile("\s*\'(.*)\'\s*\'(.*)\'.*").match(status_str) - if match: - self.conffile(match.group(1), match.group(2)) - else: - self.status = status - self.read = "" - -# module test code -if __name__ == "__main__": - import apt_pkg - apt_pkg.init() - progress = OpTextProgress() - cache = apt_pkg.GetCache(progress) - depcache = apt_pkg.GetDepCache(cache) - depcache.Init(progress) - - fprogress = TextFetchProgress() - cache.Update(fprogress) + """Process status messages from dpkg.""" + if self.statusfd is None: + return + while True: + try: + self.read += os.read(self.statusfd.fileno(), 1) + except OSError, (errno_, errstr): + # resource temporarly unavailable is ignored + if errno_ != 11: + print errstr + break + if not self.read.endswith("\n"): + continue + + statusl = self.read.split(":") + if len(statusl) < 3: + print "got garbage from dpkg: '%s'" % self.read + self.read = "" + break + status = statusl[2].strip() + #print status + if status == "error": + self.error(self.debname, status) + elif status == "conffile-prompt": + # we get a string like this: + # 'current-conffile' 'new-conffile' useredited distedited + match = re.match("\s*\'(.*)\'\s*\'(.*)\'.*", statusl[3]) + if match: + self.conffile(match.group(1), match.group(2)) + else: + self.status = status + self.read = "" diff --git a/aptsources/__init__.py b/aptsources/__init__.py index d6b3605c..c02341c2 100644 --- a/aptsources/__init__.py +++ b/aptsources/__init__.py @@ -1,5 +1,4 @@ - import apt_pkg - + # init the package system apt_pkg.init() diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py index a6c0faf8..59fa7e02 100644 --- a/aptsources/distinfo.py +++ b/aptsources/distinfo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# +# # distinfo.py - provide meta information for distro repositories # # Copyright (c) 2005 Gustavo Noronha Silva @@ -7,17 +7,17 @@ # # Author: Gustavo Noronha Silva <kov@debian.org> # Sebastian Heinlein <glatzor@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -27,16 +27,17 @@ import os import gettext from os import getenv import ConfigParser -import string +import re + import apt_pkg -#from gettext import gettext as _ -import gettext -def _(s): return gettext.dgettext("python-apt", s) -import re +def _(s): + return gettext.dgettext("python-apt", s) + class Template: + def __init__(self): self.name = None self.child = False @@ -55,45 +56,56 @@ class Template: def has_component(self, comp): ''' Check if the distribution provides the given component ''' return comp in map(lambda c: c.name, self.components) - + def is_mirror(self, url): ''' Check if a given url of a repository is a valid mirror ''' proto, hostname, dir = split_url(url) - if self.mirror_set.has_key(hostname): + if hostname in self.mirror_set: return self.mirror_set[hostname].has_repository(proto, dir) else: return False + class Component: + def __init__(self, name, desc=None, long_desc=None): self.name = name self.description = desc self.description_long = long_desc + def get_description(self): - if self.description_long != None: + if self.description_long is not None: return self.description_long - elif self.description != None: + elif self.description is not None: return self.description else: return None + def set_description(self, desc): self.description = desc + def set_description_long(self, desc): self.description_long = desc + def get_description_long(self): return self.description_long + class Mirror: ''' Storage for mirror related information ''' + def __init__(self, proto, hostname, dir, location=None): self.hostname = hostname self.repositories = [] self.add_repository(proto, dir) self.location = location + def add_repository(self, proto, dir): self.repositories.append(Repository(proto, dir)) + def get_repositories_for_proto(self, proto): return filter(lambda r: r.proto == proto, self.repositories) + def has_repository(self, proto, dir): if dir is None: return False @@ -101,28 +113,38 @@ class Mirror: if r.proto == proto and dir in r.dir: return True return False + def get_repo_urls(self): return map(lambda r: r.get_url(self.hostname), self.repositories) + def get_location(self): return self.location + def set_location(self, location): self.location = location + class Repository: + def __init__(self, proto, dir): self.proto = proto self.dir = dir + def get_info(self): return self.proto, self.dir + def get_url(self, hostname): return "%s://%s/%s" % (self.proto, hostname, self.dir) + def split_url(url): ''' split a given URL into the protocoll, the hostname and the dir part ''' - return map(lambda a,b: a, re.split(":*\/+", url, maxsplit=2), - [None, None, None]) + return map(lambda a, b: a, re.split(":*\/+", url, maxsplit=2), + [None, None, None]) + class DistInfo: + def __init__(self, dist = None, base_dir = "/usr/share/python-apt/templates"): @@ -132,7 +154,9 @@ class DistInfo: location = None match_loc = re.compile(r"^#LOC:(.+)$") - match_mirror_line = re.compile(r"^(#LOC:.+)|(((http)|(ftp)|(rsync)|(file)|(https))://[A-Za-z/\.:\-_]+)$") + match_mirror_line = re.compile( + r"^(#LOC:.+)|(((http)|(ftp)|(rsync)|(file)|(https))://" + r"[A-Za-z0-9/\.:\-_@]+)$") #match_mirror_line = re.compile(r".+") if not dist: @@ -143,21 +167,20 @@ class DistInfo: self.dist = dist - map_mirror_sets = {} dist_fname = "%s/%s.info" % (base_dir, dist) - dist_file = open (dist_fname) + dist_file = open(dist_fname) if not dist_file: return template = None component = None for line in dist_file: - tokens = line.split (':', 1) - if len (tokens) < 2: + tokens = line.split(':', 1) + if len(tokens) < 2: continue - field = tokens[0].strip () - value = tokens[1].strip () + field = tokens[0].strip() + value = tokens[1].strip() if field == 'ChangelogURI': self.changelogs_uri = _(value) elif field == 'MetaReleaseURI': @@ -190,14 +213,14 @@ class DistInfo: template.match_uri = value elif field == 'MatchURI-%s' % self.arch: template.match_uri = value - elif (field == 'MirrorsFile' or + elif (field == 'MirrorsFile' or field == 'MirrorsFile-%s' % self.arch): - if not map_mirror_sets.has_key(value): + if value not in map_mirror_sets: mirror_set = {} try: mirror_data = filter(match_mirror_line.match, - map(string.strip, open(value))) - except: + [x.strip() for x in open(value)]) + except Exception: print "WARNING: Failed to read mirror file" mirror_data = [] for line in mirror_data: @@ -205,10 +228,11 @@ class DistInfo: location = match_loc.sub(r"\1", line) continue (proto, hostname, dir) = split_url(line) - if mirror_set.has_key(hostname): + if hostname in mirror_set: mirror_set[hostname].add_repository(proto, dir) else: - mirror_set[hostname] = Mirror(proto, hostname, dir, location) + mirror_set[hostname] = Mirror( + proto, hostname, dir, location) map_mirror_sets[value] = mirror_set template.mirror_set = map_mirror_sets[value] elif field == 'Description': @@ -230,7 +254,7 @@ class DistInfo: if not template: return # reuse some properties of the parent template - if template.match_uri == None and template.child: + if template.match_uri is None and template.child: for t in template.parents: if t.match_uri: template.match_uri = t.match_uri @@ -243,11 +267,11 @@ class DistInfo: if component and not template.has_component(component.name): template.components.append(component) component = None - self.templates.append(template) + self.templates.append(template) if __name__ == "__main__": - d = DistInfo ("Ubuntu", "/usr/share/python-apt/templates") + d = DistInfo("Ubuntu", "/usr/share/python-apt/templates") print d.changelogs_uri for template in d.templates: print "\nSuite: %s" % template.name @@ -257,8 +281,8 @@ if __name__ == "__main__": if template.mirror_set != {}: print "Mirrors: %s" % template.mirror_set.keys() for comp in template.components: - print " %s -%s -%s" % (comp.name, - comp.description, + print " %s -%s -%s" % (comp.name, + comp.description, comp.description_long) for child in template.children: print " %s" % child.description diff --git a/aptsources/distro.py b/aptsources/distro.py index f271bbc4..d8f191d6 100644 --- a/aptsources/distro.py +++ b/aptsources/distro.py @@ -2,439 +2,454 @@ # # Copyright (c) 2004-2007 Canonical Ltd. # 2006-2007 Sebastian Heinlein -# +# # Authors: Sebastian Heinlein <glatzor@ubuntu.com> # Michael Vogt <mvo@debian.org> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA -import string import gettext import re import os import sys import gettext -def _(s): return gettext.dgettext("python-apt", s) + + +def _(s): + return gettext.dgettext("python-apt", s) class NoDistroTemplateException(Exception): - pass + pass + class Distribution: - def __init__(self, id, codename, description, release): - """ Container for distribution specific informations """ - # LSB information - self.id = id - self.codename = codename - self.description = description - self.release = release - - self.binary_type = "deb" - self.source_type = "deb-src" - - def get_sources(self, sourceslist): - """ - Find the corresponding template, main and child sources - for the distribution - """ - self.sourceslist = sourceslist - # corresponding sources - self.source_template = None - self.child_sources = [] - self.main_sources = [] - self.disabled_sources = [] - self.cdrom_sources = [] - self.download_comps = [] - self.enabled_comps = [] - self.cdrom_comps = [] - self.used_media = [] - self.get_source_code = False - self.source_code_sources = [] - - # location of the sources - self.default_server = "" - self.main_server = "" - self.nearest_server = "" - self.used_servers = [] - - # find the distro template - for template in self.sourceslist.matcher.templates: - if self.is_codename(template.name) and\ - template.distribution == self.id: - #print "yeah! found a template for %s" % self.description - #print template.description, template.base_uri, template.components - self.source_template = template - break - if self.source_template == None: - raise (NoDistroTemplateException, - "Error: could not find a distribution template") - - # find main and child sources - media = [] - comps = [] - cdrom_comps = [] - enabled_comps = [] - source_code = [] - for source in self.sourceslist.list: - if source.invalid == False and\ - self.is_codename(source.dist) and\ - source.template and\ - self.is_codename(source.template.name): - #print "yeah! found a distro repo: %s" % source.line - # cdroms need do be handled differently - if source.uri.startswith("cdrom:") and \ - source.disabled == False: - self.cdrom_sources.append(source) - cdrom_comps.extend(source.comps) - elif source.uri.startswith("cdrom:") and \ - source.disabled == True: - self.cdrom_sources.append(source) - elif source.type == self.binary_type and \ - source.disabled == False: - self.main_sources.append(source) - comps.extend(source.comps) - media.append(source.uri) - elif source.type == self.binary_type and \ - source.disabled == True: - self.disabled_sources.append(source) - elif source.type == self.source_type and source.disabled == False: - self.source_code_sources.append(source) - elif source.type == self.source_type and source.disabled == True: - self.disabled_sources.append(source) - if source.invalid == False and\ - source.template in self.source_template.children: - if source.disabled == False and source.type == self.binary_type: - self.child_sources.append(source) - elif source.disabled == False and source.type == self.source_type: - self.source_code_sources.append(source) - else: - self.disabled_sources.append(source) - self.download_comps = set(comps) - self.cdrom_comps = set(cdrom_comps) - enabled_comps.extend(comps) - enabled_comps.extend(cdrom_comps) - self.enabled_comps = set(enabled_comps) - self.used_media = set(media) - - self.get_mirrors() - - def get_mirrors(self, mirror_template=None): - """ - Provide a set of mirrors where you can get the distribution from - """ - # the main server is stored in the template - self.main_server = self.source_template.base_uri + def __init__(self, id, codename, description, release): + """ Container for distribution specific informations """ + # LSB information + self.id = id + self.codename = codename + self.description = description + self.release = release - # other used servers - for medium in self.used_media: - if not medium.startswith("cdrom:"): - # seems to be a network source - self.used_servers.append(medium) + self.binary_type = "deb" + self.source_type = "deb-src" - if len(self.main_sources) == 0: - self.default_server = self.main_server - else: - self.default_server = self.main_sources[0].uri - - # get a list of country codes and real names - self.countries = {} - try: - f = open("/usr/share/iso-codes/iso_3166.tab", "r") - lines = f.readlines() - for line in lines: - parts = line.split("\t") - self.countries[parts[0].lower()] = parts[1].strip() - except: - print "could not open file '%s'" % file - else: - f.close() - - # try to guess the nearest mirror from the locale - self.country = None - self.country_code = None - locale = os.getenv("LANG", default="en_UK") - a = locale.find("_") - z = locale.find(".") - if z == -1: - z = len(locale) - country_code = locale[a+1:z].lower() - - if mirror_template: - self.nearest_server = mirror_template % country_code - - if self.countries.has_key(country_code): - self.country = self.countries[country_code] - self.country_code = country_code - - def _get_mirror_name(self, server): - ''' Try to get a human readable name for the main mirror of a country - Customize for different distributions ''' - country = None - i = server.find("://") - l = server.find(".archive.ubuntu.com") - if i != -1 and l != -1: - country = server[i+len("://"):l] - if self.countries.has_key(country): - # TRANSLATORS: %s is a country - return _("Server for %s") % \ - gettext.dgettext("iso_3166", - self.countries[country].rstrip()).rstrip() - else: - return("%s" % server.rstrip("/ ")) - - def get_server_list(self): - ''' Return a list of used and suggested servers ''' - def compare_mirrors(mir1, mir2): - '''Helper function that handles comaprision of mirror urls - that could contain trailing slashes''' - return re.match(mir1.strip("/ "), mir2.rstrip("/ ")) - - # Store all available servers: - # Name, URI, active - mirrors = [] - if len(self.used_servers) < 1 or \ - (len(self.used_servers) == 1 and \ - compare_mirrors(self.used_servers[0], self.main_server)): - mirrors.append([_("Main server"), self.main_server, True]) - mirrors.append([self._get_mirror_name(self.nearest_server), - self.nearest_server, False]) - elif len(self.used_servers) == 1 and not \ - compare_mirrors(self.used_servers[0], self.main_server): - mirrors.append([_("Main server"), self.main_server, False]) - # Only one server is used - server = self.used_servers[0] - - # Append the nearest server if it's not already used - if not compare_mirrors(server, self.nearest_server): - mirrors.append([self._get_mirror_name(self.nearest_server), - self.nearest_server, False]) - mirrors.append([self._get_mirror_name(server), server, True]) - - elif len(self.used_servers) > 1: - # More than one server is used. Since we don't handle this case - # in the user interface we set "custom servers" to true and - # append a list of all used servers - mirrors.append([_("Main server"), self.main_server, False]) - mirrors.append([self._get_mirror_name(self.nearest_server), - self.nearest_server, False]) - mirrors.append([_("Custom servers"), None, True]) - for server in self.used_servers: - if compare_mirrors(server, self.nearest_server) or\ - compare_mirrors(server, self.main_server): - continue - elif not [self._get_mirror_name(server), server, False] in mirrors: - mirrors.append([self._get_mirror_name(server), server, False]) - - return mirrors - - def add_source(self, type=None, - uri=None, dist=None, comps=None, comment=""): - """ - Add distribution specific sources - """ - if uri == None: - # FIXME: Add support for the server selector - uri = self.default_server - if dist == None: - dist = self.codename - if comps == None: - comps = list(self.enabled_comps) - if type == None: - type = self.binary_type - new_source = self.sourceslist.add(type, uri, dist, comps, comment) - # if source code is enabled add a deb-src line after the new - # source - if self.get_source_code == True and type == self.binary_type: - self.sourceslist.add(self.source_type, uri, dist, comps, comment, - file=new_source.file, - pos=self.sourceslist.list.index(new_source)+1) - - def enable_component(self, comp): - """ - Enable a component in all main, child and source code sources - (excluding cdrom based sources) + def get_sources(self, sourceslist): + """ + Find the corresponding template, main and child sources + for the distribution + """ - comp: the component that should be enabled - """ - def add_component_only_once(source, comps_per_dist): + self.sourceslist = sourceslist + # corresponding sources + self.source_template = None + self.child_sources = [] + self.main_sources = [] + self.disabled_sources = [] + self.cdrom_sources = [] + self.download_comps = [] + self.enabled_comps = [] + self.cdrom_comps = [] + self.used_media = [] + self.get_source_code = False + self.source_code_sources = [] + + # location of the sources + self.default_server = "" + self.main_server = "" + self.nearest_server = "" + self.used_servers = [] + + # find the distro template + for template in self.sourceslist.matcher.templates: + if self.is_codename(template.name) and\ + template.distribution == self.id: + #print "yeah! found a template for %s" % self.description + #print template.description, template.base_uri, \ + # template.components + self.source_template = template + break + if self.source_template is None: + raise NoDistroTemplateException("Error: could not find a " + "distribution template") + + # find main and child sources + media = [] + comps = [] + cdrom_comps = [] + enabled_comps = [] + source_code = [] + for source in self.sourceslist.list: + if source.invalid == False and\ + self.is_codename(source.dist) and\ + source.template and\ + self.is_codename(source.template.name): + #print "yeah! found a distro repo: %s" % source.line + # cdroms need do be handled differently + if source.uri.startswith("cdrom:") and \ + source.disabled == False: + self.cdrom_sources.append(source) + cdrom_comps.extend(source.comps) + elif source.uri.startswith("cdrom:") and \ + source.disabled == True: + self.cdrom_sources.append(source) + elif source.type == self.binary_type and \ + source.disabled == False: + self.main_sources.append(source) + comps.extend(source.comps) + media.append(source.uri) + elif source.type == self.binary_type and \ + source.disabled == True: + self.disabled_sources.append(source) + elif source.type == self.source_type \ + and source.disabled == False: + self.source_code_sources.append(source) + elif source.type == self.source_type \ + and source.disabled == True: + self.disabled_sources.append(source) + if source.invalid == False and\ + source.template in self.source_template.children: + if source.disabled == False \ + and source.type == self.binary_type: + self.child_sources.append(source) + elif source.disabled == False \ + and source.type == self.source_type: + self.source_code_sources.append(source) + else: + self.disabled_sources.append(source) + self.download_comps = set(comps) + self.cdrom_comps = set(cdrom_comps) + enabled_comps.extend(comps) + enabled_comps.extend(cdrom_comps) + self.enabled_comps = set(enabled_comps) + self.used_media = set(media) + + self.get_mirrors() + + def get_mirrors(self, mirror_template=None): """ - Check if we already added the component to the repository, since - a repository could be splitted into different apt lines. If not - add the component + Provide a set of mirrors where you can get the distribution from """ - # if we don't that distro, just reutnr (can happen for e.g. - # dapper-update only in deb-src - if not comps_per_dist.has_key(source.dist): - return - # if we have seen this component already for this distro, - # return (nothing to do - if comp in comps_per_dist[source.dist]: - return - # add it - source.comps.append(comp) - comps_per_dist[source.dist].add(comp) - - sources = [] - sources.extend(self.main_sources) - sources.extend(self.child_sources) - # store what comps are enabled already per distro (where distro is - # e.g. "dapper", "dapper-updates") - comps_per_dist = {} - comps_per_sdist = {} - for s in sources: - if s.type == self.binary_type: - if not comps_per_dist.has_key(s.dist): - comps_per_dist[s.dist] = set() - map(comps_per_dist[s.dist].add, s.comps) - for s in self.source_code_sources: - if s.type == self.source_type: - if not comps_per_sdist.has_key(s.dist): - comps_per_sdist[s.dist] = set() - map(comps_per_sdist[s.dist].add, s.comps) - - # check if there is a main source at all - if len(self.main_sources) < 1: - # create a new main source - self.add_source(comps=["%s"%comp]) - else: - # add the comp to all main, child and source code sources - for source in sources: - add_component_only_once(source, comps_per_dist) + # the main server is stored in the template + self.main_server = self.source_template.base_uri - # check if there is a main source code source at all - if self.get_source_code == True: - if len(self.source_code_sources) < 1: - # create a new main source - self.add_source(type=self.source_type, comps=["%s"%comp]) + # other used servers + for medium in self.used_media: + if not medium.startswith("cdrom:"): + # seems to be a network source + self.used_servers.append(medium) + + if len(self.main_sources) == 0: + self.default_server = self.main_server + else: + self.default_server = self.main_sources[0].uri + + # get a list of country codes and real names + self.countries = {} + try: + f = open("/usr/share/iso-codes/iso_3166.tab", "r") + lines = f.readlines() + for line in lines: + parts = line.split("\t") + self.countries[parts[0].lower()] = parts[1].strip() + except: + print "could not open file '%s'" % file + else: + f.close() + + # try to guess the nearest mirror from the locale + self.country = None + self.country_code = None + locale = os.getenv("LANG", default="en_UK") + a = locale.find("_") + z = locale.find(".") + if z == -1: + z = len(locale) + country_code = locale[a+1:z].lower() + + if mirror_template: + self.nearest_server = mirror_template % country_code + + if country_code in self.countries: + self.country = self.countries[country_code] + self.country_code = country_code + + def _get_mirror_name(self, server): + ''' Try to get a human readable name for the main mirror of a country + Customize for different distributions ''' + country = None + i = server.find("://") + l = server.find(".archive.ubuntu.com") + if i != -1 and l != -1: + country = server[i+len("://"):l] + if country in self.countries: + # TRANSLATORS: %s is a country + return _("Server for %s") % \ + gettext.dgettext("iso_3166", + self.countries[country].rstrip()).rstrip() else: - # add the comp to all main, child and source code sources - for source in self.source_code_sources: - add_component_only_once(source, comps_per_sdist) + return("%s" % server.rstrip("/ ")) + + def get_server_list(self): + ''' Return a list of used and suggested servers ''' + + def compare_mirrors(mir1, mir2): + ''' Helper function that handles comaprision of mirror urls + that could contain trailing slashes''' + return re.match(mir1.strip("/ "), mir2.rstrip("/ ")) + + # Store all available servers: + # Name, URI, active + mirrors = [] + if len(self.used_servers) < 1 or \ + (len(self.used_servers) == 1 and \ + compare_mirrors(self.used_servers[0], self.main_server)): + mirrors.append([_("Main server"), self.main_server, True]) + mirrors.append([self._get_mirror_name(self.nearest_server), + self.nearest_server, False]) + elif len(self.used_servers) == 1 and not \ + compare_mirrors(self.used_servers[0], self.main_server): + mirrors.append([_("Main server"), self.main_server, False]) + # Only one server is used + server = self.used_servers[0] + + # Append the nearest server if it's not already used + if not compare_mirrors(server, self.nearest_server): + mirrors.append([self._get_mirror_name(self.nearest_server), + self.nearest_server, False]) + mirrors.append([self._get_mirror_name(server), server, True]) + + elif len(self.used_servers) > 1: + # More than one server is used. Since we don't handle this case + # in the user interface we set "custom servers" to true and + # append a list of all used servers + mirrors.append([_("Main server"), self.main_server, False]) + mirrors.append([self._get_mirror_name(self.nearest_server), + self.nearest_server, False]) + mirrors.append([_("Custom servers"), None, True]) + for server in self.used_servers: + mirror_entry = [self._get_mirror_name(server), server, False] + if compare_mirrors(server, self.nearest_server) or\ + compare_mirrors(server, self.main_server): + continue + elif not mirror_entry in mirrors: + mirrors.append(mirror_entry) + + return mirrors + + def add_source(self, type=None, + uri=None, dist=None, comps=None, comment=""): + """ + Add distribution specific sources + """ + if uri is None: + # FIXME: Add support for the server selector + uri = self.default_server + if dist is None: + dist = self.codename + if comps is None: + comps = list(self.enabled_comps) + if type is None: + type = self.binary_type + new_source = self.sourceslist.add(type, uri, dist, comps, comment) + # if source code is enabled add a deb-src line after the new + # source + if self.get_source_code == True and type == self.binary_type: + self.sourceslist.add(self.source_type, uri, dist, comps, comment, + file=new_source.file, + pos=self.sourceslist.list.index(new_source)+1) + + def enable_component(self, comp): + """ + Enable a component in all main, child and source code sources + (excluding cdrom based sources) - def disable_component(self, comp): - """ - Disable a component in all main, child and source code sources - (excluding cdrom based sources) - """ - sources = [] - sources.extend(self.main_sources) - sources.extend(self.child_sources) - sources.extend(self.source_code_sources) - if comp in self.cdrom_comps: + comp: the component that should be enabled + """ + + def add_component_only_once(source, comps_per_dist): + """ + Check if we already added the component to the repository, since + a repository could be splitted into different apt lines. If not + add the component + """ + # if we don't that distro, just reutnr (can happen for e.g. + # dapper-update only in deb-src + if source.dist not in comps_per_dist: + return + # if we have seen this component already for this distro, + # return (nothing to do + if comp in comps_per_dist[source.dist]: + return + # add it + source.comps.append(comp) + comps_per_dist[source.dist].add(comp) + + sources = [] + sources.extend(self.main_sources) + sources.extend(self.child_sources) + # store what comps are enabled already per distro (where distro is + # e.g. "dapper", "dapper-updates") + comps_per_dist = {} + comps_per_sdist = {} + for s in sources: + if s.type == self.binary_type: + if s.dist not in comps_per_dist: + comps_per_dist[s.dist] = set() + map(comps_per_dist[s.dist].add, s.comps) + for s in self.source_code_sources: + if s.type == self.source_type: + if s.dist not in comps_per_sdist: + comps_per_sdist[s.dist] = set() + map(comps_per_sdist[s.dist].add, s.comps) + + # check if there is a main source at all + if len(self.main_sources) < 1: + # create a new main source + self.add_source(comps=["%s"%comp]) + else: + # add the comp to all main, child and source code sources + for source in sources: + add_component_only_once(source, comps_per_dist) + + # check if there is a main source code source at all + if self.get_source_code == True: + if len(self.source_code_sources) < 1: + # create a new main source + self.add_source(type=self.source_type, comps=["%s"%comp]) + else: + # add the comp to all main, child and source code sources + for source in self.source_code_sources: + add_component_only_once(source, comps_per_sdist) + + def disable_component(self, comp): + """ + Disable a component in all main, child and source code sources + (excluding cdrom based sources) + """ sources = [] sources.extend(self.main_sources) - for source in sources: - if comp in source.comps: - source.comps.remove(comp) - if len(source.comps) < 1: - self.sourceslist.remove(source) - - def change_server(self, uri): - ''' Change the server of all distro specific sources to - a given host ''' - def change_server_of_source(source, uri, seen): - # Avoid creating duplicate entries - source.uri = uri - for comp in source.comps: - if [source.uri, source.dist, comp] in seen: + sources.extend(self.child_sources) + sources.extend(self.source_code_sources) + if comp in self.cdrom_comps: + sources = [] + sources.extend(self.main_sources) + for source in sources: + if comp in source.comps: source.comps.remove(comp) - else: - seen.append([source.uri, source.dist, comp]) - if len(source.comps) < 1: - self.sourceslist.remove(source) - seen_binary = [] - seen_source = [] - self.default_server = uri - for source in self.main_sources: - change_server_of_source(source, uri, seen_binary) - for source in self.child_sources: - # Do not change the forces server of a child source - if source.template.base_uri == None or \ - source.template.base_uri != source.uri: + if len(source.comps) < 1: + self.sourceslist.remove(source) + + def change_server(self, uri): + ''' Change the server of all distro specific sources to + a given host ''' + + def change_server_of_source(source, uri, seen): + # Avoid creating duplicate entries + source.uri = uri + for comp in source.comps: + if [source.uri, source.dist, comp] in seen: + source.comps.remove(comp) + else: + seen.append([source.uri, source.dist, comp]) + if len(source.comps) < 1: + self.sourceslist.remove(source) + + seen_binary = [] + seen_source = [] + self.default_server = uri + for source in self.main_sources: change_server_of_source(source, uri, seen_binary) - for source in self.source_code_sources: - change_server_of_source(source, uri, seen_source) + for source in self.child_sources: + # Do not change the forces server of a child source + if source.template.base_uri is None or \ + source.template.base_uri != source.uri: + change_server_of_source(source, uri, seen_binary) + for source in self.source_code_sources: + change_server_of_source(source, uri, seen_source) + + def is_codename(self, name): + ''' Compare a given name with the release codename. ''' + if name == self.codename: + return True + else: + return False - def is_codename(self, name): - ''' Compare a given name with the release codename. ''' - if name == self.codename: - return True - else: - return False class DebianDistribution(Distribution): - ''' Class to support specific Debian features ''' + ''' Class to support specific Debian features ''' + + def is_codename(self, name): + ''' Compare a given name with the release codename and check if + if it can be used as a synonym for a development releases ''' + if name == self.codename or self.release in ("testing", "unstable"): + return True + else: + return False + + def _get_mirror_name(self, server): + ''' Try to get a human readable name for the main mirror of a country + Debian specific ''' + country = None + i = server.find("://ftp.") + l = server.find(".debian.org") + if i != -1 and l != -1: + country = server[i+len("://ftp."):l] + if country in self.countries: + # TRANSLATORS: %s is a country + return _("Server for %s") % gettext.dgettext( + "iso_3166", self.countries[country].rstrip()).rstrip() + else: + return("%s" % server.rstrip("/ ")) + + def get_mirrors(self): + Distribution.get_mirrors( + self, mirror_template="http://ftp.%s.debian.org/debian/") - def is_codename(self, name): - ''' Compare a given name with the release codename and check if - if it can be used as a synonym for a development releases ''' - if name == self.codename or self.release in ("testing", "unstable"): - return True - else: - return False - - def _get_mirror_name(self, server): - ''' Try to get a human readable name for the main mirror of a country - Debian specific ''' - country = None - i = server.find("://ftp.") - l = server.find(".debian.org") - if i != -1 and l != -1: - country = server[i+len("://ftp."):l] - if self.countries.has_key(country): - # TRANSLATORS: %s is a country - return _("Server for %s") % \ - gettext.dgettext("iso_3166", - self.countries[country].rstrip()).rstrip() - else: - return("%s" % server.rstrip("/ ")) - - def get_mirrors(self): - Distribution.get_mirrors(self, - mirror_template="http://ftp.%s.debian.org/debian/") class UbuntuDistribution(Distribution): - ''' Class to support specific Ubuntu features ''' - def get_mirrors(self): - Distribution.get_mirrors(self, - mirror_template="http://%s.archive.ubuntu.com/ubuntu/") + ''' Class to support specific Ubuntu features ''' + + def get_mirrors(self): + Distribution.get_mirrors( + self, mirror_template="http://%s.archive.ubuntu.com/ubuntu/") + -def get_distro(id=None,codename=None,description=None,release=None): - """ +def get_distro(id=None, codename=None, description=None, release=None): + """ Check the currently used distribution and return the corresponding - distriubtion class that supports distro specific features. - + distriubtion class that supports distro specific features. + If no paramter are given the distro will be auto detected via a call to lsb-release """ # make testing easier if not (id and codename and description and release): - lsb_info = [] - for lsb_option in ["-i", "-c", "-d", "-r"]: - pipe = os.popen("lsb_release %s -s" % lsb_option) - lsb_info.append(pipe.read().strip()) - del pipe - (id, codename, description, release) = lsb_info + lsb_info = [] + for lsb_option in ["-i", "-c", "-d", "-r"]: + pipe = os.popen("lsb_release %s -s" % lsb_option) + lsb_info.append(pipe.read().strip()) + del pipe + (id, codename, description, release) = lsb_info if id == "Ubuntu": - return UbuntuDistribution(id, codename, description, - release) + return UbuntuDistribution(id, codename, description, release) elif id == "Debian": return DebianDistribution(id, codename, description, release) else: return Distribution(id, codename, description, release) - diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py index e0f32f8d..dc2a5d45 100644 --- a/aptsources/sourceslist.py +++ b/aptsources/sourceslist.py @@ -1,438 +1,449 @@ # aptsource.py - Provide an abstraction of the sources.list -# +# # Copyright (c) 2004-2007 Canonical Ltd. # 2004 Michiel Sikkes # 2006-2007 Sebastian Heinlein -# +# # Author: Michiel Sikkes <michiel@eyesopened.nl> # Michael Vogt <mvo@debian.org> # Sebastian Heinlein <glatzor@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA - -import string + import gettext -import re -import apt_pkg import glob -import shutil -import time import os.path +import re +import shutil import sys +import time + +import apt_pkg +from aptsources.distinfo import DistInfo -#from UpdateManager.Common.DistInfo import DistInfo -from distinfo import DistInfo # some global helpers + + def is_mirror(master_uri, compare_uri): - """check if the given add_url is idential or a mirror of orig_uri - e.g. master_uri = archive.ubuntu.com - compare_uri = de.archive.ubuntu.com - -> True - """ - # remove traling spaces and "/" - compare_uri = compare_uri.rstrip("/ ") - master_uri = master_uri.rstrip("/ ") - # uri is identical - if compare_uri == master_uri: - #print "Identical" - return True - # add uri is a master site and orig_uri has the from "XX.mastersite" - # (e.g. de.archive.ubuntu.com) - try: - compare_srv = compare_uri.split("//")[1] - master_srv = master_uri.split("//")[1] - #print "%s == %s " % (add_srv, orig_srv) - except IndexError: # ok, somethings wrong here - #print "IndexError" + """ check if the given add_url is idential or a mirror of orig_uri + e.g. master_uri = archive.ubuntu.com + compare_uri = de.archive.ubuntu.com + -> True + """ + # remove traling spaces and "/" + compare_uri = compare_uri.rstrip("/ ") + master_uri = master_uri.rstrip("/ ") + # uri is identical + if compare_uri == master_uri: + #print "Identical" + return True + # add uri is a master site and orig_uri has the from "XX.mastersite" + # (e.g. de.archive.ubuntu.com) + try: + compare_srv = compare_uri.split("//")[1] + master_srv = master_uri.split("//")[1] + #print "%s == %s " % (add_srv, orig_srv) + except IndexError: # ok, somethings wrong here + #print "IndexError" + return False + # remove the leading "<country>." (if any) and see if that helps + if "." in compare_srv and \ + compare_srv[compare_srv.index(".")+1:] == master_srv: + #print "Mirror" + return True return False - # remove the leading "<country>." (if any) and see if that helps - if "." in compare_srv and \ - compare_srv[compare_srv.index(".")+1:] == master_srv: - #print "Mirror" - return True - return False + def uniq(s): - """ simple and efficient way to return uniq list """ - return list(set(s)) + """ simple and efficient way to return uniq list """ + return list(set(s)) + class SourceEntry: - """ single sources.list entry """ - def __init__(self, line,file=None): - self.invalid = False # is the source entry valid - self.disabled = False # is it disabled ('#' in front) - self.type = "" # what type (deb, deb-src) - self.uri = "" # base-uri - self.dist = "" # distribution (dapper, edgy, etc) - self.comps = [] # list of available componetns (may empty) - self.comment = "" # (optional) comment - self.line = line # the original sources.list line - if file == None: - file = apt_pkg.Config.FindDir("Dir::Etc")+apt_pkg.Config.Find("Dir::Etc::sourcelist") - self.file = file # the file that the entry is located in - self.parse(line) - self.template = None # type DistInfo.Suite - self.children = [] - - def __eq__(self, other): - """ equal operator for two sources.list entries """ - return (self.disabled == other.disabled and - self.type == other.type and - self.uri == other.uri and - self.dist == other.dist and - self.comps == other.comps) - - - def mysplit(self, line): - """ a split() implementation that understands the sources.list - format better and takes [] into account (for e.g. cdroms) """ - line = string.strip(line) - pieces = [] - tmp = "" - # we are inside a [..] block - p_found = False - space_found = False - for i in range(len(line)): - if line[i] == "[": - p_found=True - tmp += line[i] - elif line[i] == "]": - p_found=False - tmp += line[i] - elif space_found and not line[i].isspace(): # we skip one or more space + """ single sources.list entry """ + + def __init__(self, line, file=None): + self.invalid = False # is the source entry valid + self.disabled = False # is it disabled ('#' in front) + self.type = "" # what type (deb, deb-src) + self.uri = "" # base-uri + self.dist = "" # distribution (dapper, edgy, etc) + self.comps = [] # list of available componetns + # (may empty) + self.comment = "" # (optional) comment + self.line = line # the original sources.list line + if file is None: + file = apt_pkg.Config.FindDir( + "Dir::Etc")+apt_pkg.Config.Find("Dir::Etc::sourcelist") + self.file = file # the file that the entry is located in + self.parse(line) + self.template = None # type DistInfo.Suite + self.children = [] + + def __eq__(self, other): + """ equal operator for two sources.list entries """ + return (self.disabled == other.disabled and + self.type == other.type and + self.uri == other.uri and + self.dist == other.dist and + self.comps == other.comps) + + def mysplit(self, line): + """ a split() implementation that understands the sources.list + format better and takes [] into account (for e.g. cdroms) """ + line = line.strip() + pieces = [] + tmp = "" + # we are inside a [..] block + p_found = False space_found = False - pieces.append(tmp) - tmp = line[i] - elif line[i].isspace() and not p_found: # found a whitespace - space_found = True - else: - tmp += line[i] - # append last piece - if len(tmp) > 0: - pieces.append(tmp) - return pieces - - def parse(self,line): - """ parse a given sources.list (textual) line and break it up - into the field we have """ - line = string.strip(self.line) - #print line - # check if the source is enabled/disabled - if line == "" or line == "#": # empty line - self.invalid = True - return - if line[0] == "#": - self.disabled = True - pieces = string.split(line[1:]) - # if it looks not like a disabled deb line return - if not pieces[0] in ("rpm", "rpm-src", "deb", "deb-src"): - self.invalid = True - return - else: - line = line[1:] - # check for another "#" in the line (this is treated as a comment) - i = line.find("#") - if i > 0: - self.comment = line[i+1:] - line = line[:i] - # source is ok, split it and see what we have - pieces = self.mysplit(line) - # Sanity check - if len(pieces) < 3: - self.invalid = True - return - # Type, deb or deb-src - self.type = string.strip(pieces[0]) - # Sanity check - if self.type not in ("deb", "deb-src", "rpm", "rpm-src"): - self.invalid = True - return - # URI - self.uri = string.strip(pieces[1]) - if len(self.uri) < 1: - self.invalid = True - # distro and components (optional) - # Directory or distro - self.dist = string.strip(pieces[2]) - if len(pieces) > 3: - # List of components - self.comps = pieces[3:] - else: - self.comps = [] - - def set_enabled(self, new_value): - """ set a line to enabled or disabled """ - self.disabled = not new_value - # enable, remove all "#" from the start of the line - if new_value == True: - i=0 - self.line = string.lstrip(self.line) - while self.line[i] == "#": - i += 1 - self.line = self.line[i:] - else: - # disabled, add a "#" - if string.strip(self.line)[0] != "#": - self.line = "#" + self.line - - def __str__(self): - """ debug helper """ - return self.str().strip() - - def str(self): - """ return the current line as string """ - if self.invalid: - return self.line - line = "" - if self.disabled: - line = "# " - line += "%s %s %s" % (self.type, self.uri, self.dist) - if len(self.comps) > 0: - line += " " + " ".join(self.comps) - if self.comment != "": - line += " #"+self.comment - line += "\n" - return line - + for i in range(len(line)): + if line[i] == "[": + p_found=True + tmp += line[i] + elif line[i] == "]": + p_found=False + tmp += line[i] + elif space_found and not line[i].isspace(): + # we skip one or more space + space_found = False + pieces.append(tmp) + tmp = line[i] + elif line[i].isspace() and not p_found: + # found a whitespace + space_found = True + else: + tmp += line[i] + # append last piece + if len(tmp) > 0: + pieces.append(tmp) + return pieces + + def parse(self, line): + """ parse a given sources.list (textual) line and break it up + into the field we have """ + line = self.line.strip() + #print line + # check if the source is enabled/disabled + if line == "" or line == "#": # empty line + self.invalid = True + return + if line[0] == "#": + self.disabled = True + pieces = line[1:].strip() + # if it looks not like a disabled deb line return + if not pieces[0] in ("rpm", "rpm-src", "deb", "deb-src"): + self.invalid = True + return + else: + line = line[1:] + # check for another "#" in the line (this is treated as a comment) + i = line.find("#") + if i > 0: + self.comment = line[i+1:] + line = line[:i] + # source is ok, split it and see what we have + pieces = self.mysplit(line) + # Sanity check + if len(pieces) < 3: + self.invalid = True + return + # Type, deb or deb-src + self.type = pieces[0].strip() + # Sanity check + if self.type not in ("deb", "deb-src", "rpm", "rpm-src"): + self.invalid = True + return + # URI + self.uri = pieces[1].strip() + if len(self.uri) < 1: + self.invalid = True + # distro and components (optional) + # Directory or distro + self.dist = pieces[2].strip() + if len(pieces) > 3: + # List of components + self.comps = pieces[3:] + else: + self.comps = [] + + def set_enabled(self, new_value): + """ set a line to enabled or disabled """ + self.disabled = not new_value + # enable, remove all "#" from the start of the line + if new_value: + self.line = self.line.lstrip().lstrip('#') + else: + # disabled, add a "#" + if self.line.strip()[0] != "#": + self.line = "#" + self.line + + def __str__(self): + """ debug helper """ + return self.str().strip() + + def str(self): + """ return the current line as string """ + if self.invalid: + return self.line + line = "" + if self.disabled: + line = "# " + line += "%s %s %s" % (self.type, self.uri, self.dist) + if len(self.comps) > 0: + line += " " + " ".join(self.comps) + if self.comment != "": + line += " #"+self.comment + line += "\n" + return line + + class NullMatcher(object): - """ a Matcher that does nothing """ - def match(self, s): - return True + """ a Matcher that does nothing """ + + def match(self, s): + return True + class SourcesList: - """ represents the full sources.list + sources.list.d file """ - def __init__(self, - withMatcher=True, - matcherPath="/usr/share/python-apt/templates/"): - self.list = [] # the actual SourceEntries Type - if withMatcher: - self.matcher = SourceEntryMatcher(matcherPath) - else: - self.matcher = NullMatcher() - self.refresh() - - def refresh(self): - """ update the list of known entries """ - self.list = [] - # read sources.list - dir = apt_pkg.Config.FindDir("Dir::Etc") - file = apt_pkg.Config.Find("Dir::Etc::sourcelist") - self.load(dir+file) - # read sources.list.d - partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") - for file in glob.glob("%s/*.list" % partsdir): - self.load(file) - # check if the source item fits a predefined template - for source in self.list: - if source.invalid == False: - self.matcher.match(source) - - def __iter__(self): - """ simple iterator to go over self.list, returns SourceEntry - types """ - for entry in self.list: - yield entry - raise StopIteration - - def add(self, type, uri, dist, orig_comps, comment="", pos=-1, file=None): - """ - Add a new source to the sources.list. - The method will search for existing matching repos and will try to - reuse them as far as possible - """ - # create a working copy of the component list so that - # we can modify it later - comps = orig_comps[:] - # check if we have this source already in the sources.list - for source in self.list: - if source.disabled == False and source.invalid == False and \ - source.type == type and uri == source.uri and \ - source.dist == dist: - for new_comp in comps: - if new_comp in source.comps: - # we have this component already, delete it from the new_comps - # list - del comps[comps.index(new_comp)] - if len(comps) == 0: - return source - for source in self.list: - # if there is a repo with the same (type, uri, dist) just add the - # components - if source.disabled == False and source.invalid == False and \ - source.type == type and uri == source.uri and \ - source.dist == dist: - comps = uniq(source.comps + comps) - source.comps = comps - return source - # if there is a corresponding repo which is disabled, enable it - elif source.disabled == True and source.invalid == False and \ - source.type == type and uri == source.uri and \ - source.dist == dist and \ - len(set(source.comps) & set(comps)) == len(comps): - source.disabled = False - return source - # there isn't any matching source, so create a new line and parse it - line = "%s %s %s" % (type,uri,dist) - for c in comps: - line = line + " " + c; - if comment != "": - line = "%s #%s\n" %(line,comment) - line = line + "\n" - new_entry = SourceEntry(line) - if file != None: - new_entry.file = file - self.matcher.match(new_entry) - self.list.insert(pos, new_entry) - return new_entry - - def remove(self, source_entry): - """ remove the specified entry from the sources.list """ - self.list.remove(source_entry) - - def restoreBackup(self, backup_ext): - " restore sources.list files based on the backup extension " - dir = apt_pkg.Config.FindDir("Dir::Etc") - file = apt_pkg.Config.Find("Dir::Etc::sourcelist") - if os.path.exists(dir+file+backup_ext) and \ - os.path.exists(dir+file): - shutil.copy(dir+file+backup_ext,dir+file) - # now sources.list.d - partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") - for file in glob.glob("%s/*.list" % partsdir): - if os.path.exists(file+backup_ext): - shutil.copy(file+backup_ext,file) - - def backup(self, backup_ext=None): - """ make a backup of the current source files, if no backup extension - is given, the current date/time is used (and returned) """ - already_backuped = set() - if backup_ext == None: - backup_ext = time.strftime("%y%m%d.%H%M") - for source in self.list: - if not source.file in already_backuped and os.path.exists(source.file): - shutil.copy(source.file,"%s%s" % (source.file,backup_ext)) - return backup_ext - - def load(self,file): - """ (re)load the current sources """ - try: - f = open(file, "r") - lines = f.readlines() - for line in lines: - source = SourceEntry(line,file) - self.list.append(source) - except: - print "could not open file '%s'" % file - else: - f.close() - - def save(self): - """ save the current sources """ - files = {} - # write an empty default config file if there aren't any sources - if len(self.list) == 0: - path = "%s%s" % (apt_pkg.Config.FindDir("Dir::Etc"), - apt_pkg.Config.Find("Dir::Etc::sourcelist")) - header = ("## See sources.list(5) for more information, especialy\n" + """ represents the full sources.list + sources.list.d file """ + + def __init__(self, + withMatcher=True, + matcherPath="/usr/share/python-apt/templates/"): + self.list = [] # the actual SourceEntries Type + if withMatcher: + self.matcher = SourceEntryMatcher(matcherPath) + else: + self.matcher = NullMatcher() + self.refresh() + + def refresh(self): + """ update the list of known entries """ + self.list = [] + # read sources.list + dir = apt_pkg.Config.FindDir("Dir::Etc") + file = apt_pkg.Config.Find("Dir::Etc::sourcelist") + self.load(dir+file) + # read sources.list.d + partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") + for file in glob.glob("%s/*.list" % partsdir): + self.load(file) + # check if the source item fits a predefined template + for source in self.list: + if not source.invalid: + self.matcher.match(source) + + def __iter__(self): + """ simple iterator to go over self.list, returns SourceEntry + types """ + for entry in self.list: + yield entry + raise StopIteration + + def add(self, type, uri, dist, orig_comps, comment="", pos=-1, file=None): + """ + Add a new source to the sources.list. + The method will search for existing matching repos and will try to + reuse them as far as possible + """ + # create a working copy of the component list so that + # we can modify it later + comps = orig_comps[:] + # check if we have this source already in the sources.list + for source in self.list: + if not source.disabled and not source.invalid and \ + source.type == type and uri == source.uri and \ + source.dist == dist: + for new_comp in comps: + if new_comp in source.comps: + # we have this component already, delete it + # from the new_comps list + del comps[comps.index(new_comp)] + if len(comps) == 0: + return source + for source in self.list: + # if there is a repo with the same (type, uri, dist) just add the + # components + if not source.disabled and not source.invalid and \ + source.type == type and uri == source.uri and \ + source.dist == dist: + comps = uniq(source.comps + comps) + source.comps = comps + return source + # if there is a corresponding repo which is disabled, enable it + elif source.disabled and not source.invalid and \ + source.type == type and uri == source.uri and \ + source.dist == dist and \ + len(set(source.comps) & set(comps)) == len(comps): + source.disabled = False + return source + # there isn't any matching source, so create a new line and parse it + line = "%s %s %s" % (type, uri, dist) + for c in comps: + line = line + " " + c + if comment != "": + line = "%s #%s\n" % (line, comment) + line = line + "\n" + new_entry = SourceEntry(line) + if file is not None: + new_entry.file = file + self.matcher.match(new_entry) + self.list.insert(pos, new_entry) + return new_entry + + def remove(self, source_entry): + """ remove the specified entry from the sources.list """ + self.list.remove(source_entry) + + def restoreBackup(self, backup_ext): + " restore sources.list files based on the backup extension " + dir = apt_pkg.Config.FindDir("Dir::Etc") + file = apt_pkg.Config.Find("Dir::Etc::sourcelist") + if os.path.exists(dir+file+backup_ext) and \ + os.path.exists(dir+file): + shutil.copy(dir+file+backup_ext, dir+file) + # now sources.list.d + partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") + for file in glob.glob("%s/*.list" % partsdir): + if os.path.exists(file+backup_ext): + shutil.copy(file+backup_ext, file) + + def backup(self, backup_ext=None): + """ make a backup of the current source files, if no backup extension + is given, the current date/time is used (and returned) """ + already_backuped = set() + if backup_ext is None: + backup_ext = time.strftime("%y%m%d.%H%M") + for source in self.list: + if not source.file in already_backuped \ + and os.path.exists(source.file): + shutil.copy(source.file, "%s%s" % (source.file, backup_ext)) + return backup_ext + + def load(self, file): + """ (re)load the current sources """ + try: + f = open(file, "r") + lines = f.readlines() + for line in lines: + source = SourceEntry(line, file) + self.list.append(source) + except: + print "could not open file '%s'" % file + else: + f.close() + + def save(self): + """ save the current sources """ + files = {} + # write an empty default config file if there aren't any sources + if len(self.list) == 0: + path = "%s%s" % (apt_pkg.Config.FindDir("Dir::Etc"), + apt_pkg.Config.Find("Dir::Etc::sourcelist")) + header = ( + "## See sources.list(5) for more information, especialy\n" "# Remember that you can only use http, ftp or file URIs\n" "# CDROMs are managed through the apt-cdrom tool.\n") - open(path,"w").write(header) - return - for source in self.list: - if not files.has_key(source.file): - files[source.file]=open(source.file,"w") - files[source.file].write(source.str()) - for f in files: - files[f].close() - - def check_for_relations(self, sources_list): - """get all parent and child channels in the sources list""" - parents = [] - used_child_templates = {} - for source in sources_list: - # try to avoid checking uninterressting sources - if source.template == None: - continue - # set up a dict with all used child templates and corresponding - # source entries - if source.template.child == True: - key = source.template - if not used_child_templates.has_key(key): - used_child_templates[key] = [] - temp = used_child_templates[key] - temp.append(source) - else: - # store each source with children aka. a parent :) - if len(source.template.children) > 0: - parents.append(source) - #print self.used_child_templates - #print self.parents - return (parents, used_child_templates) - -# matcher class to make a source entry look nice -# lots of predefined matchers to make it i18n/gettext friendly + open(path, "w").write(header) + return + for source in self.list: + if source.file not in files: + files[source.file] = open(source.file, "w") + files[source.file].write(source.str()) + for f in files: + files[f].close() + + def check_for_relations(self, sources_list): + """get all parent and child channels in the sources list""" + parents = [] + used_child_templates = {} + for source in sources_list: + # try to avoid checking uninterressting sources + if source.template is None: + continue + # set up a dict with all used child templates and corresponding + # source entries + if source.template.child: + key = source.template + if key not in used_child_templates: + used_child_templates[key] = [] + temp = used_child_templates[key] + temp.append(source) + else: + # store each source with children aka. a parent :) + if len(source.template.children) > 0: + parents.append(source) + #print self.used_child_templates + #print self.parents + return (parents, used_child_templates) + + class SourceEntryMatcher: - def __init__(self, matcherPath): - self.templates = [] - # Get the human readable channel and comp names from the channel .infos - spec_files = glob.glob("%s/*.info" % matcherPath) - for f in spec_files: - f = os.path.basename(f) - i = f.find(".info") - f = f[0:i] - dist = DistInfo(f,base_dir=matcherPath) - for template in dist.templates: - if template.match_uri != None: - self.templates.append(template) - return - - def match(self, source): - """Add a matching template to the source""" - _ = gettext.gettext - found = False - for template in self.templates: - if (re.search(template.match_uri, source.uri) and - re.match(template.match_name, source.dist)): - found = True - source.template = template - break - elif (template.is_mirror(source.uri) and - re.match(template.match_name, source.dist)): - found = True - source.template = template - break - return found + """ matcher class to make a source entry look nice + lots of predefined matchers to make it i18n/gettext friendly + """ + + def __init__(self, matcherPath): + self.templates = [] + # Get the human readable channel and comp names from the channel .infos + spec_files = glob.glob("%s/*.info" % matcherPath) + for f in spec_files: + f = os.path.basename(f) + i = f.find(".info") + f = f[0:i] + dist = DistInfo(f, base_dir=matcherPath) + for template in dist.templates: + if template.match_uri is not None: + self.templates.append(template) + return + + def match(self, source): + """Add a matching template to the source""" + _ = gettext.gettext + found = False + for template in self.templates: + if (re.search(template.match_uri, source.uri) and + re.match(template.match_name, source.dist)): + found = True + source.template = template + break + elif (template.is_mirror(source.uri) and + re.match(template.match_name, source.dist)): + found = True + source.template = template + break + return found # some simple tests if __name__ == "__main__": - apt_pkg.InitConfig() - sources = SourcesList() - - for entry in sources: - print entry.str() - #print entry.uri - - mirror = is_mirror("http://archive.ubuntu.com/ubuntu/", - "http://de.archive.ubuntu.com/ubuntu/") - print "is_mirror(): %s" % mirror - - print is_mirror("http://archive.ubuntu.com/ubuntu", - "http://de.archive.ubuntu.com/ubuntu/") - print is_mirror("http://archive.ubuntu.com/ubuntu/", - "http://de.archive.ubuntu.com/ubuntu") + apt_pkg.InitConfig() + sources = SourcesList() + + for entry in sources: + print entry.str() + #print entry.uri + + mirror = is_mirror("http://archive.ubuntu.com/ubuntu/", + "http://de.archive.ubuntu.com/ubuntu/") + print "is_mirror(): %s" % mirror + print is_mirror("http://archive.ubuntu.com/ubuntu", + "http://de.archive.ubuntu.com/ubuntu/") + print is_mirror("http://archive.ubuntu.com/ubuntu/", + "http://de.archive.ubuntu.com/ubuntu") diff --git a/configure.in b/configure.in index e62985c2..1000f38c 100644 --- a/configure.in +++ b/configure.in @@ -21,7 +21,7 @@ EOF [AC_CHECK_LIB(python$ac_cv_ver_python,PyArg_ParseTuple, [AC_DEFINE(HAVE_PYTHONLIB) PYTHONLIB="-lpython$ac_cv_ver_python $ac_cv_libs_python"],[],$ac_cv_libs_python)]) AC_SUBST(PYTHONLIB) - + PYTHONVER=$ac_cv_ver_python PYTHONPREFIX=$ac_cv_prefix_python PYTHONEXECPREFIX=$ac_cv_execprefix_python diff --git a/data/templates/Debian.info.in b/data/templates/Debian.info.in index dd040c20..5f4486d5 100644 --- a/data/templates/Debian.info.in +++ b/data/templates/Debian.info.in @@ -30,7 +30,7 @@ RepositoryType: deb BaseURI: http://http.us.debian.org/debian/ MatchURI: ftp[0-9]*\.[a-z]\.debian\.org MirrorsFile: /usr/share/python-apt/templates/Debian.mirrors -_Description: Debian 4.0 'Etch' +_Description: Debian 4.0 'Etch' Component: main _CompDescription: Officially supported Component: contrib diff --git a/data/templates/Ubuntu.info.in b/data/templates/Ubuntu.info.in index 67180bcb..0adb8e67 100644 --- a/data/templates/Ubuntu.info.in +++ b/data/templates/Ubuntu.info.in @@ -354,7 +354,7 @@ _CompDescription: Community-maintained (universe) _CompDescriptionLong: Community-maintained Open Source software Component: restricted _CompDescription: Non-free drivers -_CompDescriptionLong: Proprietary drivers for devices +_CompDescriptionLong: Proprietary drivers for devices Component: multiverse _CompDescription: Restricted software (Multiverse) _CompDescriptionLong: Software restricted by copyright or legal issues diff --git a/debian/changelog b/debian/changelog index a80a9b64..49236999 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,39 @@ +python-apt (0.7.9~exp2) experimental; urgency=low + + * apt/*.py: + - Almost complete cleanup of the code + - Remove inconsistent use of tabs and spaces (Closes: #505443) + - Improved documentation + * apt/debfile.py: + - Drop get*() methods, as they are deprecated and were + never in a stable release + - Make DscSrcPackage working + * apt/gtk/widgets.py: + - Fix the code and document the signals + * Introduce new documentation build with Sphinx + - Contains style Guide (Closes: #481562) + - debian/rules: Build the documentation here + - setup.py: Remove pydoc building and add new docs. + - debian/examples: Include examples from documentation + - debian/python-apt.docs: + + Change html/ to build/doc/html. + + Add build/doc/text for the text-only documentation + * setup.py: + - Only create build/data when building, not all the time + - Remove build/mo and build/data on clean -a + * debian/control: + - Remove the Conflicts on python2.3-apt, python2.4-apt, as + they are only needed for oldstable (sarge) + - Build-Depend on python-sphinx (>= 0.5) + * aptsources/distinfo.py: + - Allow @ in mirror urls (Closes: #478171) (LP: #223097) + * Merge Ben Finney's whitespace changes (Closes: #481563) + * Merge Ben Finney's do not use has_key() (Closes: #481878) + * Do not use deprecated form of raise statement (Closes: #494259) + * Add support for PkgRecords.SHA256Hash (Closes: #456113) + + -- Julian Andres Klode <jak@debian.org> Sun, 11 Jan 2009 20:01:59 +0100 + python-apt (0.7.9~exp1) experimental; urgency=low * Merged python-apt consolidation branch by Sebastian @@ -155,7 +191,7 @@ python-apt (0.7.4) unstable; urgency=low * apt/debfile.py: - added wrapper around apt_inst.debExtract() - - support dictionary like access + - support dictionary like access * apt/package.py: - fix apt.package.Dependency.relation initialization * python/apt_instmodule.cc: @@ -174,7 +210,7 @@ python-apt (0.7.4) unstable; urgency=low * python/depcache.cc: - be more threading friendly * python/tag.cc - - support "None" as default in + - support "None" as default in ParseSection(control).get(field, default), LP: #44470 * python/progress.cc: - fix refcount problem in OpProgress @@ -206,7 +242,7 @@ python-apt (0.7.3) unstable; urgency=low * doc/examples/records.py: - added example how to use the new Records class * apt/cache.py: - - throw FetchCancelleException, FetchFailedException, + - throw FetchCancelleException, FetchFailedException, LockFailedException exceptions when something goes wrong * aptsources/distro.py: - generalized some code, bringing it into the Distribution @@ -225,7 +261,7 @@ python-apt (0.7.2) unstable; urgency=low * build against the new apt * support for new "aptsources" pythn module - (thanks to Sebastian Heinlein) + (thanks to Sebastian Heinlein) * merged support for translated package descriptions * merged support for automatic removal of unused dependencies @@ -260,7 +296,7 @@ python-apt (0.6.21) unstable; urgency=low - better cdrom handling support * apt/package.py: - added candidateDependencies, installedDependencies - - SizeToString supports PyLong too + - SizeToString supports PyLong too - support pkg.architecture - support candidateRecord, installedRecord * apt/cache.py: @@ -290,7 +326,7 @@ python-apt (0.6.20) unstable; urgency=low - use select() when checking for statusfd (lp: #53282) * acknoledge NMU (closes: #378048, #373512) * python/apt_pkgmodule.cc: - - fix missing docstring (closes: #368907), + - fix missing docstring (closes: #368907), Thanks to Josh Triplett * make it build against python2.5 * python/progress.cc: @@ -342,40 +378,40 @@ python-apt (0.6.18) unstable; urgency=low python-apt (0.6.17) unstable; urgency=low - * apt/progress.py: + * apt/progress.py: - initialize FetchProgress.eta with the correct type - strip the staus str before passing it to InstallProgress.statusChanged() - - added InstallProgress.statusChange(pkg, percent, status) - - make DumbInstallProgress a new-style class + - added InstallProgress.statusChange(pkg, percent, status) + - make DumbInstallProgress a new-style class (thanks to kamion for the suggestions) - fix various pychecker warnings * apt/cache.py: - return useful values on Cache.update() - Release locks on failure (thanks to Colin Watson) - fix various pychecker warnings - * apt/package.py: + * apt/package.py: - fix various pychecker warnings - check if looupRecords succeeded - fix bug in the return statement of _downloadable() * python/srcrecords.cc: - add "Restart" method - - don't run auto "Restart" before performing a Lookup + - don't run auto "Restart" before performing a Lookup - fix the initalization (no need to pass a PkgCacheType to the records) - added "Index" attribute * python/indexfile.cc: - added ArchiveURI() method - + -- Michael Vogt <mvo@debian.org> Mon, 8 May 2006 22:34:58 +0200 python-apt (0.6.16.2) unstable; urgency=low - + * Non-maintainer upload. * debian/control: + Replaces: python-apt (<< 0.6.11), instead of Conflicts which is not correct here. (closes: #308586). -- Pierre Habouzit <madcoder@debian.org> Fri, 14 Apr 2006 19:30:51 +0200 - + python-apt (0.6.16.1) unstable; urgency=low * memleak fixed when pkgCache objects are deallocated @@ -388,11 +424,11 @@ python-apt (0.6.16.1) unstable; urgency=low python-apt (0.6.16) unstable; urgency=low - * added GetPkgAcqFile to queue individual file downloads with the + * added GetPkgAcqFile to queue individual file downloads with the system (dosn't make use of the improved pkgAcqFile yet) * added SourceList.GetIndexes() * rewrote apt.cache.update() to use the improved aquire interface - * apt/ API change: apt.Package.candidateOrigin returns a list of origins + * apt/ API change: apt.Package.candidateOrigin returns a list of origins now instead of a single one * apt_pkg.Cdrom.Add() returns a boolean now, CdromProgress has totalSteps * added support for pkgIndexFile and added SourcesList.FindIndex() @@ -419,8 +455,8 @@ python-apt (0.6.14) unstable; urgency=low (this is the job of the caller now) * python/srcrecords.cc: - support for "srcrecords.Files" added - - always run "Restart" before performing a Lookup - * export locking via: GetLock(),PkgSystem{Lock,UnLock} + - always run "Restart" before performing a Lookup + * export locking via: GetLock(),PkgSystem{Lock,UnLock} * apt/cache.py: - added __iter__ to make "for pkg in apt.Cache:" stuff possible @@ -438,9 +474,9 @@ python-apt (0.6.13) unstable; urgency=low * native apt/ python directory added that contains a more pythonic interface to apt_pkg * made the apt/ python code PEP08 conform - * python exceptions return the apt error message now + * python exceptions return the apt error message now (thanks to Chris Halls for the patch) - + -- Michael Vogt <mvo@debian.org> Fri, 5 Aug 2005 10:30:31 +0200 python-apt (0.6.12.2) unstable; urgency=low @@ -453,7 +489,7 @@ python-apt (0.6.12.1) unstable; urgency=low * rebuild against the latest apt - -- Michael Vogt <mvo@debian.org> Tue, 28 Jun 2005 18:29:57 +0200 + -- Michael Vogt <mvo@debian.org> Tue, 28 Jun 2005 18:29:57 +0200 python-apt (0.6.12ubuntu1) breezy; urgency=low @@ -465,17 +501,17 @@ python-apt (0.6.12ubuntu1) breezy; urgency=low -- Michael Vogt <michael.vogt@ubuntu.com> Thu, 12 May 2005 11:34:05 +0200 python-apt (0.6.12) breezy; urgency=low - + * added a tests/ directory * added tests/pkgsrcrecords.py that will check if the pkgsrcrecords interface does not segfault * new native python "apt" interface that hides the details of apt_pkg -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 6 May 2005 10:11:52 +0200 - + python-apt (0.6.11) experimental; urgency=low - * fixed some reference count problems in the depcache and + * fixed some reference count problems in the depcache and pkgsrcrecords code * DepCache.Init() is never called implicit now * merged with python-apt tree from Greek0@gmx.net--2005-main @@ -551,7 +587,7 @@ python-apt (0.5.8) unstable; urgency=low python-apt (0.5.5.2) unstable; urgency=low - * Add myself to Uploaders so that bugs don't get tagged as NMU-fixed anymore + * Add myself to Uploaders so that bugs don't get tagged as NMU-fixed anymore * Initial support for working with source packages (Closes: #199716) -- Matt Zimmerman <mdz@debian.org> Tue, 22 Jul 2003 22:20:00 -0400 @@ -561,7 +597,7 @@ python-apt (0.5.5.1) unstable; urgency=low * DepIterator::GlobOr increments the iterator; don't increment it again. This caused every other dependency to be skipped (Closes: #195805) * Avoid a null pointer dereference when calling keys() on an empty - configuration (Closes: #149380) + configuration (Closes: #149380) -- Matt Zimmerman <mdz@debian.org> Mon, 2 Jun 2003 23:18:53 -0400 @@ -591,7 +627,7 @@ python-apt (0.5.4.4) unstable; urgency=low Closes: #157773 -- Matt Zimmerman <mdz@debian.org> Tue, 27 Aug 2002 19:22:10 -0400 - + python-apt (0.5.4.3) unstable; urgency=low * #include <new> in python/generic.h so that we can build on ia64, which diff --git a/debian/control b/debian/control index b738231f..0cb6e215 100644 --- a/debian/control +++ b/debian/control @@ -5,20 +5,18 @@ Maintainer: APT Development Team <deity@lists.debian.org> Uploaders: Matt Zimmerman <mdz@debian.org>, Michael Vogt <mvo@debian.org> Standards-Version: 3.7.2.2 XS-Python-Version: all -Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.7.10), apt-utils, python-all-dev, python-distutils-extra (>= 1.9.0), cdbs, python-central (>= 0.5), python-all-dbg +Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.7.10), apt-utils, python-all-dev, python-distutils-extra (>= 1.9.0), cdbs, python-central (>= 0.5), python-all-dbg, python-sphinx (>= 0.5) Vcs-Bzr: http://bzr.debian.org/apt/python-apt/debian-sid Package: python-apt Architecture: any Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release Priority: optional -Replaces: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18) -Conflicts: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18) Provides: ${python:Provides} Suggests: python-apt-dbg, python-gtk2, python-vte XB-Python-Version: ${python:Versions} Description: Python interface to libapt-pkg - The apt_pkg Python interface will provide full access to the internal + The apt_pkg Python interface will provide full access to the internal libapt-pkg structures allowing Python programs to easily perform a variety of functions, such as: . @@ -27,7 +25,7 @@ Description: Python interface to libapt-pkg - Parsing of Debian package control files, and other files with a similar structure . - The included 'aptsources' Python interface provides an abstraction of + The included 'aptsources' Python interface provides an abstraction of the sources.list configuration on the repository and the distro level. Package: python-apt-dbg @@ -35,7 +33,7 @@ Priority: extra Architecture: any Depends: python-dbg, python-apt (= ${Source-Version}), ${shlibs:Depends} Description: Python interface to libapt-pkg (debug extension) - The apt_pkg Python interface will provide full access to the internal + The apt_pkg Python interface will provide full access to the internal libapt-pkg structures allowing Python programs to easily perform a variety of functions. . diff --git a/debian/copyright b/debian/copyright index 1e310354..f8463185 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,6 +1,6 @@ -APT is free software; you can redistribute them and/or modify them 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 +APT is free software; you can redistribute them and/or modify them 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. On Debian systems, a copy of the GNU General Public License can be diff --git a/debian/examples b/debian/examples index 80a386c8..e4a93ea1 100644 --- a/debian/examples +++ b/debian/examples @@ -1 +1,2 @@ doc/examples/*.py +doc/source/examples/*.py diff --git a/debian/python-apt.docs b/debian/python-apt.docs index f3c87fdc..6ba083f5 100644 --- a/debian/python-apt.docs +++ b/debian/python-apt.docs @@ -1,4 +1,5 @@ README apt/README.apt data/templates/README.templates -html/ +build/doc/html/ +build/doc/text/ diff --git a/debian/rules b/debian/rules index adaad2a8..90b48cda 100755 --- a/debian/rules +++ b/debian/rules @@ -13,6 +13,7 @@ include /usr/share/cdbs/1/class/python-distutils.mk PKG=python-apt DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') +DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) build/python-apt-dbg:: diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..327bba91 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,79 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html web pickle htmlhelp latex changes linkcheck + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview over all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf build/* + +text: + mkdir -p build/text build/doctrees + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) build/text + +html: + mkdir -p build/html build/doctrees + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html + @echo + @echo "Build finished. The HTML pages are in build/html." + +pickle: + mkdir -p build/pickle build/doctrees + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +web: pickle + +json: + mkdir -p build/json build/doctrees + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + mkdir -p build/htmlhelp build/doctrees + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in build/htmlhelp." + +latex: + mkdir -p build/latex build/doctrees + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex + @echo + @echo "Build finished; the LaTeX files are in build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + mkdir -p build/changes build/doctrees + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes + @echo + @echo "The overview file is in build/changes." + +linkcheck: + mkdir -p build/linkcheck build/doctrees + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in build/linkcheck/output.txt." diff --git a/doc/examples/acquire.py b/doc/examples/acquire.py index eef6c1f7..58372961 100644 --- a/doc/examples/acquire.py +++ b/doc/examples/acquire.py @@ -4,15 +4,15 @@ import os import sys import tempfile + def get_file(fetcher, uri, destFile): - # get the file - af = apt_pkg.GetPkgAcqFile(fetcher, - uri=uri, - descr="sample descr", destFile=destFile) - res = fetcher.Run() - if res != fetcher.ResultContinue: - return False - return True + # get the file + af = apt_pkg.GetPkgAcqFile(fetcher, uri=uri, descr="sample descr", + destFile=destFile) + res = fetcher.Run() + if res != fetcher.ResultContinue: + return False + return True apt_pkg.init() @@ -27,12 +27,12 @@ recs = apt_pkg.GetPkgRecords(cache) list = apt_pkg.GetPkgSourceList() list.ReadMainList() -# show the amount fetch needed for a dist-upgrade +# show the amount fetch needed for a dist-upgrade depcache.Upgrade(True) progress = apt.progress.TextFetchProgress() fetcher = apt_pkg.GetAcquire(progress) pm = apt_pkg.GetPackageManager(depcache) -pm.GetArchives(fetcher,list,recs) +pm.GetArchives(fetcher, list, recs) print "%s (%s)" % (apt_pkg.SizeToStr(fetcher.FetchNeeded), fetcher.FetchNeeded) actiongroup = apt_pkg.GetPkgActionGroup(depcache) for pkg in cache.Packages: @@ -43,7 +43,7 @@ try: os.mkdir("/tmp/pyapt-test/partial") except OSError: pass -apt_pkg.Config.Set("Dir::Cache::archives","/tmp/pyapt-test") +apt_pkg.Config.Set("Dir::Cache::archives", "/tmp/pyapt-test") pkg = cache["3ddesktop"] depcache.MarkInstall(pkg) @@ -58,7 +58,7 @@ print fetcher get_file(fetcher, "ftp://ftp.debian.org/debian/dists/README", "/tmp/lala") -pm.GetArchives(fetcher,list,recs) +pm.GetArchives(fetcher, list, recs) for item in fetcher.Items: print item @@ -67,7 +67,7 @@ for item in fetcher.Items: if item.Complete == False: print "No error, still nothing downloaded (%s)" % item.ErrorText print - + res = fetcher.Run() print "fetcher.Run() returned: %s" % res @@ -75,6 +75,3 @@ print "fetcher.Run() returned: %s" % res print "now runing pm.DoInstall()" res = pm.DoInstall(1) print "pm.DoInstall() returned: %s"% res - - - diff --git a/doc/examples/action.py b/doc/examples/action.py index adf26539..9b9d7dd3 100644 --- a/doc/examples/action.py +++ b/doc/examples/action.py @@ -21,15 +21,6 @@ cache.Update(progress) print "Exiting" sys.exit(0) - - - - - - - - - iter = cache["base-config"] print "example package iter: %s" % iter @@ -45,7 +36,6 @@ depcache.Init(progress) #sys.exit() - # get a canidate version ver= depcache.GetCandidateVer(iter) print "Candidate version: %s " % ver @@ -66,7 +56,6 @@ depcache.MarkDelete(iter) print "DelCount: %s " % depcache.DelCount print "%s.MarkedDelete(): %s" % (iter.Name, depcache.MarkedDelete(iter)) - iter = cache["3dchess"] print "\nMarking '%s' for install" % iter.Name depcache.MarkInstall(iter) @@ -97,10 +86,10 @@ print "UsrSize: %s " % apt_pkg.SizeToStr(depcache.UsrSize) print "DebSize: %s " % apt_pkg.SizeToStr(depcache.DebSize) for pkg in cache.Packages: - if pkg.CurrentVer != None and not depcache.MarkedInstall(pkg) and depcache.IsUpgradable(pkg): + if pkg.CurrentVer is not None and not depcache.MarkedInstall(pkg) \ + and depcache.IsUpgradable(pkg): print "Upgrade didn't upgrade (kept): %s" % pkg.Name - print "\nPerforming DistUpgrade" depcache.Upgrade(True) print "Keep: %s " % depcache.KeepCount @@ -112,7 +101,7 @@ print "DebSize: %s " % apt_pkg.SizeToStr(depcache.DebSize) # overview about what would happen for pkg in cache.Packages: if depcache.MarkedInstall(pkg): - if pkg.CurrentVer != None: + if pkg.CurrentVer is not None: print "Marked upgrade: %s " % pkg.Name else: print "Marked install: %s" % pkg.Name diff --git a/doc/examples/all_deps.py b/doc/examples/all_deps.py index f4f1741c..992e98d8 100644 --- a/doc/examples/all_deps.py +++ b/doc/examples/all_deps.py @@ -1,34 +1,36 @@ -#!/usr/bin/env python
-
-import sys
-import apt
-
-
-def dependencies(cache, pkg, deps, key="Depends"):
- #print "pkg: %s (%s)" % (pkg.name, deps)
- candver = cache._depcache.GetCandidateVer(pkg._pkg)
- if candver == None:
- return deps
- dependslist = candver.DependsList
- if dependslist.has_key(key):
- for depVerList in dependslist[key]:
- for dep in depVerList:
- if cache.has_key(dep.TargetPkg.Name):
- if pkg.name != dep.TargetPkg.Name and not dep.TargetPkg.Name in deps:
- deps.add(dep.TargetPkg.Name)
- dependencies(cache, cache[dep.TargetPkg.Name], deps, key)
- return deps
-
-
-pkgname = sys.argv[1]
-c = apt.Cache()
-pkg = c[pkgname]
-
-deps = set()
-
-deps = dependencies(c,pkg, deps, "Depends")
-print " ".join(deps)
-
-preDeps = set()
-preDeps = dependencies(c,pkg, preDeps, "PreDepends")
-print " ".join(preDeps)
+#!/usr/bin/env python +import sys + +import apt + + +def dependencies(cache, pkg, deps, key="Depends"): + #print "pkg: %s (%s)" % (pkg.name, deps) + candver = cache._depcache.GetCandidateVer(pkg._pkg) + if candver is None: + return deps + dependslist = candver.DependsList + if key in dependslist: + for depVerList in dependslist[key]: + for dep in depVerList: + if dep.TargetPkg.Name in cache: + if pkg.name != dep.TargetPkg.Name and \ + not dep.TargetPkg.Name in deps: + deps.add(dep.TargetPkg.Name) + dependencies( + cache, cache[dep.TargetPkg.Name], deps, key) + return deps + + +pkgname = sys.argv[1] +c = apt.Cache() +pkg = c[pkgname] + +deps = set() + +deps = dependencies(c, pkg, deps, "Depends") +print " ".join(deps) + +preDeps = set() +preDeps = dependencies(c, pkg, preDeps, "PreDepends") +print " ".join(preDeps) diff --git a/doc/examples/build-deps.py b/doc/examples/build-deps.py index 65e35f3d..aeb5667c 100755 --- a/doc/examples/build-deps.py +++ b/doc/examples/build-deps.py @@ -3,20 +3,21 @@ import apt_pkg import sys -import sets # only needed for python2.3, python2.4 supports this naively + def get_source_pkg(pkg, records, depcache): - """ get the source package name of a given package """ - version = depcache.GetCandidateVer(pkg) - if not version: - return None - file, index = version.FileList.pop(0) - records.Lookup((file, index)) - if records.SourcePkg != "": - srcpkg = records.SourcePkg - else: - srcpkg = pkg.Name - return srcpkg + """ get the source package name of a given package """ + version = depcache.GetCandidateVer(pkg) + if not version: + return None + file, index = version.FileList.pop(0) + records.Lookup((file, index)) + if records.SourcePkg != "": + srcpkg = records.SourcePkg + else: + srcpkg = pkg.Name + return srcpkg + # main apt_pkg.init() @@ -28,45 +29,45 @@ srcrecords = apt_pkg.GetPkgSrcRecords() # base package that we use for build-depends calculation if len(sys.argv) < 2: - print "need a package name as argument" - sys.exit(1) + print "need a package name as argument" + sys.exit(1) try: - base = cache[sys.argv[1]] + base = cache[sys.argv[1]] except KeyError: - print "No package %s found" % sys.argv[1] - sys.exit(1) -all_build_depends = sets.Set() + print "No package %s found" % sys.argv[1] + sys.exit(1) +all_build_depends = set() # get the build depdends for the package itself srcpkg_name = get_source_pkg(base, records, depcache) print "srcpkg_name: %s " % srcpkg_name if not srcpkg_name: - print "Can't find source package for '%s'" % pkg.Name + print "Can't find source package for '%s'" % pkg.Name srcrec = srcrecords.Lookup(srcpkg_name) if srcrec: - print "Files:" - print srcrecords.Files - bd = srcrecords.BuildDepends - print "build-depends of the package: %s " % bd - for b in bd: - all_build_depends.add(b[0]) + print "Files:" + print srcrecords.Files + bd = srcrecords.BuildDepends + print "build-depends of the package: %s " % bd + for b in bd: + all_build_depends.add(b[0]) # calculate the build depends for all dependencies depends = depcache.GetCandidateVer(base).DependsList for dep in depends["Depends"]: # FIXME: do we need to consider PreDepends? - pkg = dep[0].TargetPkg - srcpkg_name = get_source_pkg(pkg, records, depcache) - if not srcpkg_name: - print "Can't find source package for '%s'" % pkg.Name - continue - srcrec = srcrecords.Lookup(srcpkg_name) - if srcrec: - #print srcrecords.Package - #print srcrecords.Binaries - bd = srcrecords.BuildDepends - #print "%s: %s " % (srcpkg_name, bd) - for b in bd: - all_build_depends.add(b[0]) - + pkg = dep[0].TargetPkg + srcpkg_name = get_source_pkg(pkg, records, depcache) + if not srcpkg_name: + print "Can't find source package for '%s'" % pkg.Name + continue + srcrec = srcrecords.Lookup(srcpkg_name) + if srcrec: + #print srcrecords.Package + #print srcrecords.Binaries + bd = srcrecords.BuildDepends + #print "%s: %s " % (srcpkg_name, bd) + for b in bd: + all_build_depends.add(b[0]) + print "\n".join(all_build_depends) diff --git a/doc/examples/cdrom.py b/doc/examples/cdrom.py index bf044d7c..743220a6 100644 --- a/doc/examples/cdrom.py +++ b/doc/examples/cdrom.py @@ -2,7 +2,8 @@ # example how to deal with the depcache import apt_pkg -import sys, os +import sys +import os import copy from progress import CdromProgress @@ -16,17 +17,11 @@ print cdrom progress = CdromProgress() -(res,ident) = cdrom.Ident(progress) +(res, ident) = cdrom.Ident(progress) print "ident result is: %s (%s) " % (res, ident) apt_pkg.Config.Set("APT::CDROM::Rename", "True") cdrom.Add(progress) - - print "Exiting" sys.exit(0) - - - - diff --git a/doc/examples/checkstate.py b/doc/examples/checkstate.py index 2986872f..3368d500 100755 --- a/doc/examples/checkstate.py +++ b/doc/examples/checkstate.py @@ -14,23 +14,23 @@ packages = cache.Packages uninstalled, updated, upgradable = {}, {}, {} for package in packages: - versions = package.VersionList - if not versions: - continue - version = versions[0] - for other_version in versions: - if apt_pkg.VersionCompare(version.VerStr, other_version.VerStr)<0: - version = other_version - if package.CurrentVer: - current = package.CurrentVer - if apt_pkg.VersionCompare(current.VerStr, version.VerStr)<0: - upgradable[package.Name] = version - break - else: - updated[package.Name] = current - else: - uninstalled[package.Name] = version + versions = package.VersionList + if not versions: + continue + version = versions[0] + for other_version in versions: + if apt_pkg.VersionCompare(version.VerStr, other_version.VerStr)<0: + version = other_version + if package.CurrentVer: + current = package.CurrentVer + if apt_pkg.VersionCompare(current.VerStr, version.VerStr)<0: + upgradable[package.Name] = version + break + else: + updated[package.Name] = current + else: + uninstalled[package.Name] = version for l in (uninstalled, updated, upgradable): - print l.items()[0] + print l.items()[0] diff --git a/doc/examples/config.py b/doc/examples/config.py index 24d90a0d..9d4e51fc 100755 --- a/doc/examples/config.py +++ b/doc/examples/config.py @@ -6,49 +6,53 @@ # config.py -no-h --no-help --help=no ; Turn off help # config.py -qqq -q=3 ; verbosity to 3 # config.py -c /etc/apt/apt.conf ; include that config file] -# config.py -o help=true ; Turn on help by giving a config file string +# config.py -o help=true ; Turn on help by giving a +# ; config file string # config.py -no-h -- -help ; Turn off help, specify the file '-help' # -c and -o are standard APT-program options. # This shows how to use the system for configuration and option control. # The other varient is for ISC object config files. See configisc.py. -import apt_pkg,sys,posixpath; +import apt_pkg +import sys +import posixpath # Create a new empty Configuration object - there is also the system global # configuration object apt_pkg.Config which is used interally by apt-pkg # routines to control unusual situations. I recommend using the sytem global # whenever possible.. -Cnf = apt_pkg.newConfiguration(); +Cnf = apt_pkg.newConfiguration() -print "Command line is",sys.argv +print "Command line is", sys.argv # Load the default configuration file, InitConfig() does this better.. -Cnf.Set("config-file","/etc/apt/apt.conf"); # or Cnf["config-file"] = ".."; +Cnf.Set("config-file", "/etc/apt/apt.conf") # or Cnf["config-file"] = ".." if posixpath.exists(Cnf.FindFile("config-file")): - apt_pkg.ReadConfigFile(Cnf,"/etc/apt/apt.conf"); + apt_pkg.ReadConfigFile(Cnf, "/etc/apt/apt.conf") # Merge the command line arguments into the configuration space -Arguments = [('h',"help","help"), - ('v',"version","version"), - ('q',"quiet","quiet","IntLevel"), - ('c',"config-file","","ConfigFile"), - ('o',"option","","ArbItem")] -print "FileNames",apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv); +Arguments = [('h', "help", "help"), + ('v', "version", "version"), + ('q', "quiet", "quiet", "IntLevel"), + ('c', "config-file", "", "ConfigFile"), + ('o', "option", "", "ArbItem")] +print "FileNames", apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv) -print "Quiet level selected is",Cnf.FindI("quiet",0); +print "Quiet level selected is", Cnf.FindI("quiet", 0) # Do some stuff with it -if Cnf.FindB("version",0) == 1: - print "Version selected - 1.1"; +if Cnf.FindB("version", 0) == 1: + print "Version selected - 1.1" -if Cnf.FindB("help",0) == 1: - print "python-apt",apt_pkg.Version,"compiled on",apt_pkg.Date,apt_pkg.Time; - print "Hi, I am the help text for this program"; - sys.exit(0); +if Cnf.FindB("help", 0) == 1: + print "python-apt", apt_pkg.Version, \ + "compiled on", apt_pkg.Date, apt_pkg.Time + print "Hi, I am the help text for this program" + sys.exit(0) -print "No help for you, try -h"; +print "No help for you, try -h" # Print the configuration space -print "The Configuration space looks like:"; +print "The Configuration space looks like:" for I in Cnf.keys(): - print "%s \"%s\";"%(I,Cnf[I]); + print "%s \"%s\";" % (I, Cnf[I]) diff --git a/doc/examples/configisc.py b/doc/examples/configisc.py index 1773a919..de8ec6be 100755 --- a/doc/examples/configisc.py +++ b/doc/examples/configisc.py @@ -8,32 +8,37 @@ # doc/examples/ftp-archive.conf # or a bind8 config file.. -import apt_pkg,sys,posixpath; +import apt_pkg +import sys +import posixpath -ConfigFile = apt_pkg.ParseCommandLine(apt_pkg.Config,[],sys.argv); +ConfigFile = apt_pkg.ParseCommandLine(apt_pkg.Config, [], sys.argv) if len(ConfigFile) != 1: - print "Must have exactly 1 file name"; - sys.exit(0); + print "Must have exactly 1 file name" + sys.exit(0) -Cnf = apt_pkg.newConfiguration(); -apt_pkg.ReadConfigFileISC(Cnf,ConfigFile[0]); +Cnf = apt_pkg.newConfiguration() +apt_pkg.ReadConfigFileISC(Cnf, ConfigFile[0]) # Print the configuration space -#print "The Configuration space looks like:"; +#print "The Configuration space looks like:" #for I in Cnf.keys(): -# print "%s \"%s\";"%(I,Cnf[I]); +# print "%s \"%s\";" % (I, Cnf[I]) # bind8 config file.. -if Cnf.has_key("Zone"): - print "Zones: ",Cnf.SubTree("zone").List(); - for I in Cnf.List("zone"): - SubCnf = Cnf.SubTree(I); - if SubCnf.Find("type") == "slave": - print "Masters for %s: %s"%(SubCnf.MyTag(),SubCnf.ValueList("masters")); +if Cnf.Exists("Zone"): + print "Zones: ", Cnf.SubTree("zone").List() + for I in Cnf.List("zone"): + SubCnf = Cnf.SubTree(I) + if SubCnf.Find("type") == "slave": + print "Masters for %s: %s" % ( + SubCnf.MyTag(), SubCnf.ValueList("masters")) else: - print "Tree definitions:"; - for I in Cnf.List("tree"): - SubCnf = Cnf.SubTree(I); - # This could use Find which would eliminate the possibility of exceptions. - print "Subtree %s with sections '%s' and architectures '%s'"%(SubCnf.MyTag(),SubCnf["Sections"],SubCnf["Architectures"]); + print "Tree definitions:" + for I in Cnf.List("tree"): + SubCnf = Cnf.SubTree(I) + # This could use Find which would eliminate the possibility of + # exceptions. + print "Subtree %s with sections '%s' and architectures '%s'" % ( + SubCnf.MyTag(), SubCnf["Sections"], SubCnf["Architectures"]) diff --git a/doc/examples/deb_inspect.py b/doc/examples/deb_inspect.py index 0befd2bb..cc0d04be 100755 --- a/doc/examples/deb_inspect.py +++ b/doc/examples/deb_inspect.py @@ -6,11 +6,11 @@ import apt_inst import sys import os.path -def Callback(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor): + +def Callback(What, Name, Link, Mode, UID, GID, Size, MTime, Major, Minor): """ callback for debExtract """ - - print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u"\ - % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor); + print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u" \ + % (What, Name, Link, Mode, UID, GID, Size, MTime, Major, Minor) if __name__ == "__main__": @@ -39,9 +39,11 @@ if __name__ == "__main__": print "extracting archive" dir = "/tmp/deb" os.mkdir(dir) - apt_inst.debExtractArchive(open(file),dir) + apt_inst.debExtractArchive(open(file), dir) + def visit(arg, dirname, names): print "%s/" % dirname for file in names: print "\t%s" % file + os.path.walk(dir, visit, None) diff --git a/doc/examples/depcache.py b/doc/examples/depcache.py index 556c954b..790cc9d6 100644 --- a/doc/examples/depcache.py +++ b/doc/examples/depcache.py @@ -84,7 +84,8 @@ print "UsrSize: %s " % apt_pkg.SizeToStr(depcache.UsrSize) print "DebSize: %s " % apt_pkg.SizeToStr(depcache.DebSize) for pkg in cache.Packages: - if pkg.CurrentVer != None and not depcache.MarkedInstall(pkg) and depcache.IsUpgradable(pkg): + if pkg.CurrentVer is not None and not depcache.MarkedInstall(pkg) \ + and depcache.IsUpgradable(pkg): print "Upgrade didn't upgrade (kept): %s" % pkg.Name @@ -99,7 +100,7 @@ print "DebSize: %s " % apt_pkg.SizeToStr(depcache.DebSize) # overview about what would happen for pkg in cache.Packages: if depcache.MarkedInstall(pkg): - if pkg.CurrentVer != None: + if pkg.CurrentVer is not None: print "Marked upgrade: %s " % pkg.Name else: print "Marked install: %s" % pkg.Name diff --git a/doc/examples/dependant-pkgs.py b/doc/examples/dependant-pkgs.py index f36936a8..5fbbc76d 100755 --- a/doc/examples/dependant-pkgs.py +++ b/doc/examples/dependant-pkgs.py @@ -6,31 +6,31 @@ import sys pkgs = set() cache = apt.Cache() for pkg in cache: - candver = cache._depcache.GetCandidateVer(pkg._pkg) - if candver == None: - continue - dependslist = candver.DependsList - for dep in dependslist.keys(): - # get the list of each dependency object - for depVerList in dependslist[dep]: - for z in depVerList: - # get all TargetVersions of - # the dependency object - for tpkg in z.AllTargets(): - if sys.argv[1] == tpkg.ParentPkg.Name: - pkgs.add(pkg.name) + candver = cache._depcache.GetCandidateVer(pkg._pkg) + if candver is None: + continue + dependslist = candver.DependsList + for dep in dependslist.keys(): + # get the list of each dependency object + for depVerList in dependslist[dep]: + for z in depVerList: + # get all TargetVersions of + # the dependency object + for tpkg in z.AllTargets(): + if sys.argv[1] == tpkg.ParentPkg.Name: + pkgs.add(pkg.name) main = set() universe = set() for pkg in pkgs: - if "universe" in cache[pkg].section: - universe.add(cache[pkg].sourcePackageName) - else: - main.add(cache[pkg].sourcePackageName) + if "universe" in cache[pkg].section: + universe.add(cache[pkg].sourcePackageName) + else: + main.add(cache[pkg].sourcePackageName) -print "main:" +print "main:" print "\n".join(main) print -print "universe:" +print "universe:" print "\n".join(universe) diff --git a/doc/examples/desc.py b/doc/examples/desc.py index 87b9473b..f47517cf 100644 --- a/doc/examples/desc.py +++ b/doc/examples/desc.py @@ -3,7 +3,7 @@ import apt_pkg apt_pkg.init() -apt_pkg.Config.Set("APT::Acquire::Translation","de") +apt_pkg.Config.Set("APT::Acquire::Translation", "de") cache = apt_pkg.GetCache() depcache = apt_pkg.GetDepCache(cache) @@ -15,11 +15,10 @@ print cand desc = cand.TranslatedDescription print desc print desc.FileList -(f,index) = desc.FileList.pop(0) +(f, index) = desc.FileList.pop(0) records = apt_pkg.GetPkgRecords(cache) -records.Lookup((f,index)) +records.Lookup((f, index)) desc = records.LongDesc print len(desc) print desc - diff --git a/doc/examples/gui-inst.py b/doc/examples/gui-inst.py index feefd6ed..8138d922 100755 --- a/doc/examples/gui-inst.py +++ b/doc/examples/gui-inst.py @@ -1,20 +1,13 @@ #!/usr/bin/python # example how to install in a custom terminal widget # see also gnome bug: #169201 - -import apt -import apt_pkg -import sys, os, fcntl -import copy -import string -import fcntl - import pygtk pygtk.require('2.0') import gtk import apt.gtk.widgets + if __name__ == "__main__": win = gtk.Window() @@ -23,14 +16,12 @@ if __name__ == "__main__": win.add(progress) progress.show() win.show() - + cache = apt.cache.Cache(progress.open) if cache["2vcard"].isInstalled: cache["2vcard"].markDelete() else: cache["2vcard"].markInstall() progress.show_terminal(expanded=True) - cache.commit(progress.fetch, - progress.install) - + cache.commit(progress.fetch, progress.install) gtk.main() diff --git a/doc/examples/indexfile.py b/doc/examples/indexfile.py index d383fd61..22d0b635 100644 --- a/doc/examples/indexfile.py +++ b/doc/examples/indexfile.py @@ -10,7 +10,7 @@ cache = apt_pkg.GetCache() depcache = apt_pkg.GetDepCache(cache) pkg = cache["libimlib2"] cand = depcache.GetCandidateVer(pkg) -for (f,i) in cand.FileList: +for (f, i) in cand.FileList: index = sources.FindIndex(f) print index if index: diff --git a/doc/examples/inst.py b/doc/examples/inst.py index ff9d452c..a3a50356 100644 --- a/doc/examples/inst.py +++ b/doc/examples/inst.py @@ -2,27 +2,34 @@ # example how to deal with the depcache import apt -import sys, os +import sys +import os import copy import time from apt.progress import InstallProgress + class TextInstallProgress(InstallProgress): - def __init__(self): - apt.progress.InstallProgress.__init__(self) - self.last = 0.0 - def updateInterface(self): - InstallProgress.updateInterface(self) - if self.last >= self.percent: - return - sys.stdout.write("\r[%s] %s\n" %(self.percent, self.status)) - sys.stdout.flush() - self.last = self.percent - def conffile(self,current,new): - print "conffile prompt: %s %s" % (current,new) - def error(self, errorstr): - print "got dpkg error: '%s'" % errorstr + + def __init__(self): + apt.progress.InstallProgress.__init__(self) + self.last = 0.0 + + def updateInterface(self): + InstallProgress.updateInterface(self) + if self.last >= self.percent: + return + sys.stdout.write("\r[%s] %s\n" %(self.percent, self.status)) + sys.stdout.flush() + self.last = self.percent + + def conffile(self, current, new): + print "conffile prompt: %s %s" % (current, new) + + def error(self, errorstr): + print "got dpkg error: '%s'" % errorstr + cache = apt.Cache(apt.progress.OpTextProgress()) @@ -33,16 +40,12 @@ pkg = cache["3dchess"] # install or remove, the importend thing is to keep us busy :) if pkg.isInstalled: - print "Going to delete %s" % pkg.name - pkg.markDelete() + print "Going to delete %s" % pkg.name + pkg.markDelete() else: - print "Going to install %s" % pkg.name - pkg.markInstall() + print "Going to install %s" % pkg.name + pkg.markInstall() res = cache.commit(fprogress, iprogress) print res sys.exit(0) - - - - diff --git a/doc/examples/metaindex.py b/doc/examples/metaindex.py index 1bce0dba..f00a7e01 100644 --- a/doc/examples/metaindex.py +++ b/doc/examples/metaindex.py @@ -9,7 +9,7 @@ sources.ReadMainList() for metaindex in sources.List: print metaindex - print "URI: ",metaindex.URI - print "Dist: ",metaindex.Dist - print "IndexFiles: ","\n".join([str(i) for i in metaindex.IndexFiles]) + print "URI: ", metaindex.URI + print "Dist: ", metaindex.Dist + print "IndexFiles: ", "\n".join([str(i) for i in metaindex.IndexFiles]) print diff --git a/doc/examples/print_uris.py b/doc/examples/print_uris.py index c8a64223..3b678e83 100755 --- a/doc/examples/print_uris.py +++ b/doc/examples/print_uris.py @@ -12,11 +12,11 @@ upgradable = filter(lambda p: p.isUpgradable, cache) for pkg in upgradable: - pkg._lookupRecord(True) - path = apt_pkg.ParseSection(pkg._records.Record)["Filename"] - cand = pkg._depcache.GetCandidateVer(pkg._pkg) - for (packagefile,i) in cand.FileList: - indexfile = cache._list.FindIndex(packagefile) - if indexfile: - uri = indexfile.ArchiveURI(path) - print uri + pkg._lookupRecord(True) + path = apt_pkg.ParseSection(pkg._records.Record)["Filename"] + cand = pkg._depcache.GetCandidateVer(pkg._pkg) + for (packagefile, i) in cand.FileList: + indexfile = cache._list.FindIndex(packagefile) + if indexfile: + uri = indexfile.ArchiveURI(path) + print uri diff --git a/doc/examples/progress.py b/doc/examples/progress.py index 2723c382..83847598 100644 --- a/doc/examples/progress.py +++ b/doc/examples/progress.py @@ -1,10 +1,11 @@ -import apt -from apt import SizeToStr import sys import time -import string + +import apt + class TextProgress(apt.OpProgress): + def __init__(self): self.last=0.0 @@ -21,37 +22,47 @@ class TextProgress(apt.OpProgress): class TextFetchProgress(apt.FetchProgress): + def __init__(self): pass - + def start(self): pass - + def stop(self): pass - + def updateStatus(self, uri, descr, shortDescr, status): - print "UpdateStatus: '%s' '%s' '%s' '%i'" % (uri,descr,shortDescr, status) + print "UpdateStatus: '%s' '%s' '%s' '%i'" % ( + uri, descr, shortDescr, status) + def pulse(self): - print "Pulse: CPS: %s/s; Bytes: %s/%s; Item: %s/%s" % (SizeToStr(self.currentCPS), SizeToStr(self.currentBytes), SizeToStr(self.totalBytes), self.currentItems, self.totalItems) + print "Pulse: CPS: %s/s; Bytes: %s/%s; Item: %s/%s" % ( + apt.SizeToStr(self.currentCPS), SizeToStr(self.currentBytes), + apt.SizeToStr(self.totalBytes), self.currentItems, self.totalItems) return True def mediaChange(self, medium, drive): - print "Please insert medium %s in drive %s" % (medium, drive) - sys.stdin.readline() + print "Please insert medium %s in drive %s" % (medium, drive) + sys.stdin.readline() #return False class TextInstallProgress(apt.InstallProgress): + def __init__(self): apt.InstallProgress.__init__(self) pass + def startUpdate(self): print "StartUpdate" + def finishUpdate(self): print "FinishUpdate" + def statusChange(self, pkg, percent, status): print "[%s] %s: %s" % (percent, pkg, status) + def updateInterface(self): apt.InstallProgress.updateInterface(self) # usefull to e.g. redraw a GUI @@ -59,20 +70,25 @@ class TextInstallProgress(apt.InstallProgress): class TextCdromProgress(apt.CdromProgress): + def __init__(self): pass + # update is called regularly so that the gui can be redrawn + def update(self, text, step): # check if we actually have some text to display if text != "": print "Update: %s %s" % (string.strip(text), step) + def askCdromName(self): print "Please enter cd-name: ", cd_name = sys.stdin.readline() return (True, string.strip(cd_name)) + def changeCdrom(self): print "Please insert cdrom and press <ENTER>" - answer = sys.stdin.readline() + answer = sys.stdin.readline() return True diff --git a/doc/examples/recommends.py b/doc/examples/recommends.py index b1094aee..f0b3b1be 100755 --- a/doc/examples/recommends.py +++ b/doc/examples/recommends.py @@ -5,37 +5,35 @@ apt_pkg.init() cache = apt_pkg.GetCache() + class Wanted: - def __init__(self, name): - self.name = name - self.recommended = [] - self.suggested = [] + def __init__(self, name): + self.name = name + self.recommended = [] + self.suggested = [] + wanted = {} for package in cache.Packages: - current = package.CurrentVer - if not current: - continue - depends = current.DependsList - for (key, attr) in (('Suggests', 'suggested'), - ('Recommends', 'recommended')): - list = depends.get(key, []) - for dependency in list: - name = dependency[0].TargetPkg.Name - dep = cache[name] - if dep.CurrentVer: - continue - getattr(wanted.setdefault(name, Wanted(name)), - attr).append(package.Name) + current = package.CurrentVer + if not current: + continue + depends = current.DependsList + for (key, attr) in (('Suggests', 'suggested'), + ('Recommends', 'recommended')): + list = depends.get(key, []) + for dependency in list: + name = dependency[0].TargetPkg.Name + dep = cache[name] + if dep.CurrentVer: + continue + getattr(wanted.setdefault(name, Wanted(name)), + attr).append(package.Name) ks = wanted.keys() ks.sort() for want in ks: - print want, wanted[want].recommended, wanted[want].suggested - - - - + print want, wanted[want].recommended, wanted[want].suggested diff --git a/doc/examples/records.py b/doc/examples/records.py index ef04b555..a0fc8dc4 100755 --- a/doc/examples/records.py +++ b/doc/examples/records.py @@ -5,8 +5,9 @@ import apt cache = apt.Cache() for pkg in cache: - if not pkg.candidateRecord: - continue - if pkg.candidateRecord.has_key("Task"): - print "Pkg %s is part of '%s'" % (pkg.name, pkg.candidateRecord["Task"].split()) - #print pkg.candidateRecord + if not pkg.candidateRecord: + continue + if "Task" in pkg.candidateRecord: + print "Pkg %s is part of '%s'" % ( + pkg.name, pkg.candidateRecord["Task"].split()) + #print pkg.candidateRecord diff --git a/doc/examples/sources.py b/doc/examples/sources.py index b48c0ba5..49652982 100644 --- a/doc/examples/sources.py +++ b/doc/examples/sources.py @@ -10,6 +10,7 @@ apt_pkg.init() sources = apt_pkg.GetPkgSrcRecords() sources.Restart() while sources.Lookup('hello'): - print sources.Package, sources.Version, sources.Maintainer, sources.Section, `sources.Binaries` - print sources.Files - print sources.Index.ArchiveURI(sources.Files[0][2]) + print sources.Package, sources.Version, sources.Maintainer, \ + sources.Section, `sources.Binaries` + print sources.Files + print sources.Index.ArchiveURI(sources.Files[0][2]) diff --git a/doc/examples/tagfile.py b/doc/examples/tagfile.py index 653c0a71..4faf08ac 100755 --- a/doc/examples/tagfile.py +++ b/doc/examples/tagfile.py @@ -1,8 +1,8 @@ #!/usr/bin/env python import apt_pkg -Parse = apt_pkg.ParseTagFile(open("/var/lib/dpkg/status","r")); +Parse = apt_pkg.ParseTagFile(open("/var/lib/dpkg/status", "r")) while Parse.Step() == 1: - print Parse.Section.get("Package"); - print apt_pkg.ParseDepends(Parse.Section.get("Depends","")); + print Parse.Section.get("Package") + print apt_pkg.ParseDepends(Parse.Section.get("Depends", "")) diff --git a/doc/examples/update.py b/doc/examples/update.py index be7bb679..364fa1c9 100755 --- a/doc/examples/update.py +++ b/doc/examples/update.py @@ -9,5 +9,5 @@ if __name__ == "__main__": "touch /tmp/update-was-run") c = apt.Cache() res = c.update(apt.progress.TextFetchProgress()) - print "res: ",res + print "res: ", res assert(os.path.exists("/tmp/update-about-to-run")) diff --git a/doc/examples/versiontest.py b/doc/examples/versiontest.py index 95f887f2..fa13cc1c 100755 --- a/doc/examples/versiontest.py +++ b/doc/examples/versiontest.py @@ -1,36 +1,39 @@ #!/usr/bin/python # This is a simple clone of tests/versiontest.cc -import apt_pkg,sys,re,string; -apt_pkg.InitConfig(); -apt_pkg.InitSystem(); +import apt_pkg +import sys +import re -TestFile = apt_pkg.ParseCommandLine(apt_pkg.Config,[],sys.argv); +apt_pkg.InitConfig() +apt_pkg.InitSystem() + +TestFile = apt_pkg.ParseCommandLine(apt_pkg.Config, [], sys.argv) if len(TestFile) != 1: - print "Must have exactly 1 file name"; - sys.exit(0); + print "Must have exactly 1 file name" + sys.exit(0) -# Go over the file.. -List = open(TestFile[0],"r"); -CurLine = 0; +# Go over the file.. +List = open(TestFile[0], "r") +CurLine = 0 while(1): - Line = List.readline(); - CurLine = CurLine + 1; - if Line == "": - break; - Line = string.strip(Line); - if len(Line) == 0 or Line[0] == '#': - continue; - - Split = re.split("[ \n]",Line); + Line = List.readline() + CurLine = CurLine + 1 + if Line == "": + break + Line = Line.strip() + if len(Line) == 0 or Line[0] == '#': + continue + + Split = re.split("[ \n]", Line) - # Check forward - if apt_pkg.VersionCompare(Split[0],Split[1]) != int(Split[2]): - print "Comparision failed on line %u. '%s' ? '%s' %i != %i"%(CurLine, - Split[0],Split[1],apt_pkg.VersionCompare(Split[0],Split[1]), - int(Split[2])); - # Check reverse - if apt_pkg.VersionCompare(Split[1],Split[0]) != -1*int(Split[2]): - print "Comparision failed on line %u. '%s' ? '%s' %i != %i"%(CurLine, - Split[1],Split[0],apt_pkg.VersionCompare(Split[1],Split[0]), - -1*int(Split[2])); + # Check forward + if apt_pkg.VersionCompare(Split[0], Split[1]) != int(Split[2]): + print "Comparision failed on line %u. '%s' ? '%s' %i != %i" % (CurLine, + Split[0], Split[1], apt_pkg.VersionCompare(Split[0], Split[1]), + int(Split[2])) + # Check reverse + if apt_pkg.VersionCompare(Split[1], Split[0]) != -1 * int(Split[2]): + print "Comparision failed on line %u. '%s' ? '%s' %i != %i" % (CurLine, + Split[1], Split[0], apt_pkg.VersionCompare(Split[1], Split[0]), + -1 * int(Split[2])) diff --git a/doc/makefile b/doc/makefile deleted file mode 100644 index 7f9dff2b..00000000 --- a/doc/makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -*- make -*- -BASE=.. -SUBDIR=doc - -# Bring in the default rules -include ../buildlib/defaults.mak - -# Examples -SOURCE = examples/config.py examples/configisc.py examples/tagfile.py \ - examples/versiontest.py examples/checkstate.py \ - examples/recommends.py -TO = $(DOC) -include $(COPY_H) diff --git a/doc/source/apt/cache.rst b/doc/source/apt/cache.rst new file mode 100644 index 00000000..d96cba97 --- /dev/null +++ b/doc/source/apt/cache.rst @@ -0,0 +1,78 @@ +:mod:`apt.cache` --- The Cache class +===================================== +.. automodule:: apt.cache + +The Cache class +--------------- + +.. autoclass:: Cache + :members: + :undoc-members: + + .. describe:: cache[pkgname] + + Return a :class:`Package()` for the package with the name *pkgname*. + +Example +^^^^^^^ + +The following example shows how to load the cache, update it, and upgrade +all the packages on the system:: + + import apt + import apt.progress + + # First of all, open the cache + cache = apt.Cache() + # Now, lets update the package list + cache.update() + # We need to re-open the cache because it needs to read the package list + cache.open(None) + # Now we can do the same as 'apt-get upgrade' does + cache.upgrade() + # or we can play 'apt-get dist-upgrade' + cache.upgrade(True) + # Q: Why does nothing happen? + # A: You forgot to call commit()! + cache.commit(apt.progress.TextFetchProgress(), + apt.progress.InstallProgress()) + + + +Working with Filters +-------------------- +.. autoclass:: Filter + :members: + :inherited-members: + :undoc-members: + +.. autoclass:: MarkedChangesFilter + :members: + :inherited-members: + :undoc-members: + +.. autoclass:: FilteredCache + :members: + :inherited-members: + :undoc-members: + + +Example +^^^^^^^ + +This is an example for a filtered cache, which only allows access to the +packages whose state has been changed, eg. packages marked for installation:: + + >>> from apt.cache import FilteredCache, Cache, MarkedChangesFilter + >>> cache = apt.Cache() + >>> changed = apt.FilteredCache(cache) + >>> changed.setFilter(MarkedChangesFilter()) + >>> print len(changed) == len(cache.GetChanges()) # Both need to have same length + True + + +Exceptions +---------- +.. autoexception:: FetchCancelledException +.. autoexception:: FetchFailedException +.. autoexception:: LockFailedException diff --git a/doc/source/apt/cdrom.rst b/doc/source/apt/cdrom.rst new file mode 100644 index 00000000..56381f14 --- /dev/null +++ b/doc/source/apt/cdrom.rst @@ -0,0 +1,7 @@ +:mod:`apt.cdrom` - Functionality like in apt-cdrom +==================================================== +.. automodule:: apt.cdrom + :members: + + + diff --git a/doc/source/apt/debfile.rst b/doc/source/apt/debfile.rst new file mode 100644 index 00000000..7133b5a8 --- /dev/null +++ b/doc/source/apt/debfile.rst @@ -0,0 +1,39 @@ +:mod:`apt.debfile` --- Classes related to debian package files +============================================================== +The :mod:`apt.debfile` provides classes to work with locally available +debian packages, or source packages. + +.. module:: apt.debfile + +Binary packages +---------------- +.. autoclass:: DebPackage + :members: + :inherited-members: + :undoc-members: + + The :class:`DebPackage` class is a class for working with '.deb' files, + also known as Debian packages. + + It provides methods and attributes to get a list of the files in the + package, to install the package and much more. + + If you specify *cache* it has to point to an :class:`apt.cache.Cache()` + object. + + .. versionchanged:: 0.7.9 + Introduce all new methods (everything except for :meth:`open()` and + :attr:`filelist`) + + +Source packages +---------------- +.. autoclass:: DscSrcPackage + :members: + :inherited-members: + :undoc-members: + + Provide functionality to work with locally available source packages, + especially with their '.dsc' file. + + .. versionadded:: 0.7.9 diff --git a/doc/source/apt/gtk.widgets.rst b/doc/source/apt/gtk.widgets.rst new file mode 100644 index 00000000..9fa84ead --- /dev/null +++ b/doc/source/apt/gtk.widgets.rst @@ -0,0 +1,29 @@ +:mod:`apt.gtk.widgets` --- GTK widgets +====================================== +.. automodule:: apt.gtk.widgets + + +GObject progress classes +------------------------- + +.. autoclass:: GDpkgInstallProgress + :members: + +.. autoclass:: GFetchProgress + :members: + +.. autoclass:: GInstallProgress + :members: + +.. autoclass:: GOpProgress + :members: + +GTK+ Class +---------- +.. autoclass:: GtkAptProgress + :members: + + +Example +------- +.. literalinclude:: ../examples/apt-gtk.py diff --git a/doc/source/apt/index.rst b/doc/source/apt/index.rst new file mode 100644 index 00000000..5047a0fd --- /dev/null +++ b/doc/source/apt/index.rst @@ -0,0 +1,58 @@ +:mod:`apt` --- Highlevel apt package +===================================== +The highlevel apt package provides a lot of functionality, all +with an easy-to-use interface. + +.. warning:: + The API of this package is not considered stable. Evenmore, it is considered + to change the naming conventions in future to lowercase_with_underscores. + + In case this happens, the API will still be kept compatible, with the old + functions provided as deprecated ones. + +.. automodule:: apt + :members: + + + + +.. toctree:: + :maxdepth: 2 + :glob: + + * + + +Classes exported in apt +------------------------ +These classes are defined in the submodules, but are also exported directly +in the package. + +.. class:: Cache + + Please see :class:`apt.cache.Cache` for documentation. + +.. class:: Cdrom + + Please see :class:`apt.cdrom.Cdrom` for documentation. + +.. class:: CdromProgress + + Please see :class:`apt.progress.CdromProgress` for documentation. + +.. class:: FetchProgress + + Please see :class:`apt.progress.FetchProgress` for documentation. + +.. class:: InstallProgress + + Please see :class:`apt.progress.InstallProgress` for documentation. + +.. class:: OpProgress + + Please see :class:`apt.progress.OpProgress` for documentation. + +.. class:: Package + + Please see :class:`apt.package.Package` for documentation. + diff --git a/doc/source/apt/package.rst b/doc/source/apt/package.rst new file mode 100644 index 00000000..1bd032ab --- /dev/null +++ b/doc/source/apt/package.rst @@ -0,0 +1,101 @@ +:mod:`apt.package` --- Classes for package handling +==================================================== + + +.. automodule:: apt.package + + +The Package class +----------------- +.. autoclass:: Package + :members: + + +Dependency Information +---------------------- +.. class:: BaseDependency + + The :class:`BaseDependency` class defines various attributes for accessing + the parts of a dependency. The attributes are as follows: + + .. attribute:: name + + The name of the dependency + + .. attribute:: relation + + The relation (>>,>=,==,<<,<=,) + + .. attribute:: version + + The version or None. + + .. attribute:: preDepend + + Boolean value whether this is a pre-dependency. + +.. class:: Dependency + + The dependency class represents a Or-Group of dependencies. It provides + an attribute to access the :class:`BaseDependency` object for the available + choices. + + .. attribute:: or_dependencies + + A list of :class:`BaseDependency` objects which could satisfy the + requirement of the Or-Group. + + +Origin Information +------------------- +.. class:: Origin + + The :class:`Origin` class provides access to the origin of the package. + It allows you to check the component, archive, the hostname, and even if + this package can be trusted. + + .. attribute:: archive + + The archive (eg. unstable) + + .. attribute:: component + + The component (eg. main) + + .. attribute:: label + + The Label, as set in the Release file + + .. attribute:: origin + + The Origin, as set in the Release file + + .. attribute:: site + + The hostname of the site. + + .. attribute:: trusted + + Boolean value whether this is trustworthy. An origin can be trusted, if + it provides a GPG-signed Release file and the GPG-key used is in the + keyring used by apt (see apt-key). + +Examples +--------- +.. code-block:: python + + import apt + + cache = apt.Cache() + pkg = cache['python-apt'] # Access the Package object for python-apt + print 'python-apt is trusted:', pkg.candidateOrigin.trusted + + # Mark python-apt for install + pkg.markInstall() + + print 'python-apt is marked for install:', pkg.markedInstall + + print 'python-apt is', pkg.summary #Python interface to libapt-pkg + + # Now, really install it + cache.commit() diff --git a/doc/source/apt/progress.rst b/doc/source/apt/progress.rst new file mode 100644 index 00000000..8989aa27 --- /dev/null +++ b/doc/source/apt/progress.rst @@ -0,0 +1,37 @@ +:mod:`apt.progress` --- Classes for progress reporting +====================================================== +.. automodule:: apt.progress + +.. warning:: + + This class is currently under re-organisation. Therefore, the API may + change soon. The old names will still be kept until it is safe to remove + them. + + + +Classes without output +---------------------- +.. autoclass:: FetchProgress + :members: +.. autoclass:: OpProgress + :members: +.. autoclass:: CdromProgress + :members: +.. autoclass:: DumbInstallProgress + :members: + +Implementing classes for text output +------------------------------------ +.. autoclass:: TextFetchProgress + :members: +.. autoclass:: OpTextProgress + :members: +.. autoclass:: InstallProgress + :members: +.. autoclass:: DpkgInstallProgress + :members: + + + + diff --git a/doc/source/apt_inst.rst b/doc/source/apt_inst.rst new file mode 100644 index 00000000..97705f61 --- /dev/null +++ b/doc/source/apt_inst.rst @@ -0,0 +1,96 @@ +:mod:`apt_inst` - Working with local Debian packages +==================================================== +.. module:: apt_inst + +The :mod:`apt_inst` extension provides access to functions for working with +locally available Debian packages (.deb files) and tar files. + + +Checking packages +------------------ +.. function:: arCheckMember(file, membername) + + Check if the member specified by the parameter *membername* exists in + the AR file referenced by the :class:`file` object *file*. + + +Listing contents +----------------- +.. function:: debExtract(file, func, chunk) + + Call the function referenced by *func* for each member of the tar file + *chunk* which is contained in the AR file referenced by the file object + *file*. + + An example would be:: + + debExtract(open("package.deb"), my_callback, "data.tar.gz") + + See :ref:`emulating-dpkg-contents` for a more detailed example. + +.. function:: tarExtract(file,func,comp) + + Call the function *func* for each member of the tar file *file*. + + *Comp* is a string determining the compressor used. Possible options are + "lzma", "bzip2" and "gzip". + + +Callback +^^^^^^^^^ +Both of these functions expect a callback with the signature +``(what, name, link, mode, uid, gid, size, mtime, major, minor)``. + +The parameter *what* describes the type of the member. It can be 'FILE', +'DIR', or 'HARDLINK'. + +The parameter *name* refers to the name of the member. In case of links, +*link* refers to the target of the link. + + +Extracting contents +------------------- + +.. function:: debExtractArchive(file, rootdir) + + Extract the archive referenced by the :class:`file` object *file* + into the directory specified by *rootdir*. + + See :ref:`emulating-dpkg-extract` for an example. + + .. warning:: + + If the directory given by *rootdir* does not exist, the package is + extracted into the current directory. + +.. function:: debExtractControl(file[, member='control']) + + Return the indicated file from the control tar. The default is 'control'. + + If you want to print the control file of a given package, you could do + something like:: + + print debExtractControl(open("package.deb")) + + :return: The contents of the file, as :class:`str`. + + +.. _emulating-dpkg-extract: + +Example: Emulating :program:`dpkg` :option:`--extract` +------------------------------------------------------- +Here is a code snippet which emulates dpkg -x. It can be run as +:program:`tool` :option:`pkg.deb` :option:`outdir`. + +.. literalinclude:: examples/dpkg-extract.py + + +.. _emulating-dpkg-contents: + +Example: Emulating :program:`dpkg` :option:`--contents` +------------------------------------------------------- +.. literalinclude:: examples/dpkg-contents.py + +Example: Emulating :program:`dpkg` :option:`--info` +---------------------------------------------------- +.. literalinclude:: examples/dpkg-info.py diff --git a/doc/source/apt_pkg/cache.rst b/doc/source/apt_pkg/cache.rst new file mode 100644 index 00000000..af67d82f --- /dev/null +++ b/doc/source/apt_pkg/cache.rst @@ -0,0 +1,1227 @@ +Classes in apt_pkg +================== + +.. todo:: + + This should be split and cleaned up a bit. + +:class:`Acquire` +---------------- +.. class:: Acquire + + .. method:: Run() + + Fetch all the items which have been added by + :func:`apt_pkg.GetPkgAcqFile`. + + .. method:: Shutdown + + Shut the fetcher down. + +:class:`PkgAcqFile` +------------------- +.. class:: PkgAcqFile + + This class provides no methods or attributes + +:class:`AcquireItem` +--------------------- + +.. class:: AcquireItem + + .. attribute:: ID + + The ID of the item. + + .. attribute:: Complete + + Is the item completely acquired? + + .. attribute:: Local + + Is the item a local file? + + .. attribute:: IsTrusted + + Can the file be trusted? + + .. attribute:: FileSize + + The size of the file, in bytes. + + .. attribute:: ErrorText + + The error message. For example, when a file does not exist on a http + server, this will contain a 404 error message. + + .. attribute:: DestFile + + The location the file is saved as. + + .. attribute:: DescURI + + The source location. + + **Status**: + + .. attribute:: Status + + Integer, representing the status of the item. + + .. attribute:: StatIdle + + Constant for comparing :attr:`AcquireItem.Status`. + + .. attribute:: StatFetching + + Constant for comparing :attr:`AcquireItem.Status` + + .. attribute:: StatDone + + Constant for comparing :attr:`AcquireItem.Status` + + .. attribute:: StatError + + Constant for comparing :attr:`AcquireItem.Status` + + .. attribute:: StatAuthError + + Constant for comparing :attr:`AcquireItem.Status` + +:class:`ActionGroup` +-------------------- + +.. class:: ActionGroup + + Normally, apt checkes the package cache after every modification for + packages which are automatically installed but on which no package depends + anymore (it collects the package garbage). + + Using ActionGroups you can turn this off and therefore make your code + much faster. + + Initialize it using :func:`apt_pkg.GetPkgActionGroup`, eg:: + + apt_pkg.GetPkgActionGroup(depcache) + + .. method:: release + + Release the ActionGroup. This will reactive the collection of package + garbage. + + +:class:`Configuration` +---------------------- + +.. class:: Configuration + + The Configuration objects store the configuration of apt. + + .. describe:: conf[key] + + Return the value of the option given key *key*. If it does not + exist, raise :exc:`KeyError`. + + .. describe:: conf[key] = value + + Set the option at *key* to *value*. + + .. method:: Find(key[, default='']) + + Return the value for the given key *key*. This is the same as + :meth:`Configuration.get`. + + If *key* does not exist, return *default*. + + .. method:: FindFile(key[, default='']) + + Return the filename hold by the configuration at *key*. This formats the + filename correctly and supports the Dir:: stuff in the configuration. + + If *key* does not exist, return *default*. + + .. method:: FindDir(key[, default='/']) + + Return the absolute path to the directory specified in *key*. A + trailing slash is appended. + + If *key* does not exist, return *default*. + + .. method:: FindI(key[, default=0]) + + Return the integer value stored at *key*. + + If *key* does not exist, return *default*. + + .. method:: FindB(key[, default=0]) + + Return the boolean value stored at *key*. This returns an integer, but + it should be treated like True/False. + + If *key* does not exist, return *default*. + + .. method:: Set(key, value) + + Set the value of *key* to *value*. + + .. method:: Exists(key) + + Check whether the key *key* exists in the configuration. + + .. method:: SubTree(key) + + Return a sub tree starting at *key*. The resulting object can be used + like this one. + + .. method:: List([key]) + + List all items at *key*. Normally, return the keys at the top level, + eg. APT, Dir, etc. + + Use *key* to specify a key of which the childs will be returned. + + .. method:: ValueList([key]) + + Same as :meth:`Configuration.List`, but this time for the values. + + .. method:: MyTag() + + Return the tag name of the current tree. Normally this is an empty + string, but for subtrees it is the key of the subtree. + + .. method:: Clear(key) + + Clear the configuration. Remove all values and keys at *key*. + + .. method:: keys([key]) + + Return all the keys, recursive. If *key* is specified, ... (FIXME) + + .. method:: has_key(key) + + Return whether the configuration contains the key *key*. + + .. method:: get(key[, default='']) + + This behaves just like :meth:`dict.get` and :meth:`Configuration.Find`, + it returns the value of key or if it does not exist, *default*. + + +:class:`pkgCache` +----------------- +.. class:: pkgCache + + The :class:`pkgCache` class prov + + .. describe:: cache[pkgname] + + Return the :class:`Package()` object for the package name given by + *pkgname*. + + .. method:: Close() + + Close the package cache. + + .. method:: Open([progress]) + + Open the package cache again. The parameter *progress* may be set to + an :class:`apt.progress.OpProgress()` object or `None`. + + .. method:: Update(progress, list) + + Update the package cache. + + The parameter *progress* points to an :class:`apt.progress.FetchProgress()` + object. + + The parameter *list* refers to an object as returned by + :func:`apt_pkg.GetPkgSourceList`. + + .. attribute:: DependsCount + + The total number of dependencies. + + .. attribute:: PackageCount + + The total number of packages available in the cache. + + .. attribute:: ProvidesCount + + The number of provided packages. + + .. attribute:: VerFileCount + + .. todo:: Seems to be some mixture of versions and pkgFile. + + .. attribute:: VersionCount + + The total number of package versions available in the cache. + + .. attribute:: PackageFileCount + + The total number of Packages files available (the Packages files + listing the packages). This is the same as the length of the list in + the attribute :attr:`FileList`. + + .. attribute:: FileList + + A list of :class:`PackageFile` objects. + + +:class:`PackageFile` +-------------------- +.. class:: PackageFile + + A :class:`PackageFile` represents a Packages file, eg. + /var/lib/dpkg/status. + + .. attribute:: Architecture + + The architecture of the package file. + + .. attribute:: Archive + + The archive (eg. unstable) + + .. attribute:: Component + + The component (eg. main) + + .. attribute:: FileName + + The name of the file. + + .. attribute:: ID + + The ID of the package. This is an integer which can be used to store + further information about the file [eg. as dictionary key]. + + .. attribute:: IndexType + + The sort of the index file. In normal cases, this is + 'Debian Package Index'. + + .. attribute:: Label + + The Label, as set in the Release file + + .. attribute:: NotAutomatic + + Whether packages from this list will be updated automatically. The + default for eg. example is 0 (aka false). + + .. attribute:: NotSource + + Whether the file has no source from which it can be updated. In such a + case, the value is 1; else 0. /var/lib/dpkg/status is 0 for example. + + Example:: + + for pkgfile in cache.FileList: + if pkgfile.NotSource: + print 'The file %s has no source.' % pkgfile.FileName + + .. attribute:: Origin + + The Origin, as set in the Release file + + .. attribute:: Site + + The hostname of the site. + + .. attribute:: Size + + The size of the file. + + .. attribute:: Version + + The version, as set in the release file (eg. "4.0" for "Etch") + + +Example +^^^^^^^ +.. literalinclude:: ../examples/cache-pkgfile.py + + +:class:`Package` +---------------- + +.. class:: Package + + The pkgCache::Package objects are an interface to package specific + features. + + + Attributes: + + .. attribute:: CurrentVer + + The version currently installed, or None. This returns a + :class:`Version` object. + + .. attribute:: ID + + The ID of the package. This can be used to store information about + the package. The ID is an int value. + + .. attribute:: Name + + This is the name of the package. + + .. attribute:: ProvidesList + + A list of packages providing this package. More detailed, this is a + list of tuples (str:pkgname, ????, :class:`Version`). + + If you want to check for check for virtual packages, the expression + ``pkg.ProvidesList and not pkg.VersionList`` helps you. It detects if + the package is provided by something else and is not available as a + real package. + + .. attribute:: RevDependsList + + An iterator of :class:`Dependency` objects for dependencies on this + package. + + .. attribute:: Section + + The section of the package, as specified in the record. The list of + possible sections is defined in the Policy. + + .. attribute:: VersionList + + A list of :class:`Version` objects for all versions available in the + cache. + + **States**: + + .. attribute:: SelectedState + + The state we want it to be, ie. if you mark a package for installation, + this is :attr:`apt_pkg.SelStateInstall`. + + See :ref:`SelStates` for a list of available states. + + .. attribute:: InstState + + The state the currently installed version is in. This is normally + :attr:`apt_pkg.InstStateOK`, unless the installation failed. + + See :ref:`InstStates` for a list of available states. + + .. attribute:: CurState + + The current state of the package (not installed, unpacked, installed, + etc). See :ref:`CurStates` for a list of available states. + + **Flags**: + + .. attribute:: Auto + + Whether the package was installed automatically as a dependency of + another package. (or marked otherwise as automatically installed) + + .. attribute:: Essential + + Whether the package is essential. + + .. attribute:: Important + + Whether the package is important. + +Example: +^^^^^^^^^ +.. literalinclude:: ../examples/cache-packages.py + + + +:class:`Version` +---------------- +.. class:: Version + + The version object contains all information related to a specific package + version. + + .. attribute:: VerStr + + The version, as a string. + + .. attribute:: Section + + The usual sections (eg. admin, net, etc.). Prefixed with the component + name for packages not in main (eg. non-free/admin). + + .. attribute:: Arch + + The architecture of the package, eg. amd64 or all. + + .. attribute:: FileList + + A list of (:class:`PackageFile`, int: index) tuples for all Package + files containing this version of the package. + + .. attribute:: DependsListStr + + A dictionary of dependencies. The key specifies the type of the + dependency ('Depends', 'Recommends', etc.). + + + The value is a list, containing items which refer to the or-groups of + dependencies. Each of these or-groups is itself a list, containing + tuples like ('pkgname', 'version', 'relation') for each or-choice. + + An example return value for a package with a 'Depends: python (>= 2.4)' + would be:: + + {'Depends': [ + [ + ('python', '2.4', '>=') + ] + ] + } + + The same for a dependency on A (>= 1) | B (>= 2):: + + {'Depends': [ + [ + ('A', '1', '>='), + ('B', '2', '>='), + ] + ] + } + + .. attribute:: DependsList + + This is basically the same as :attr:`Version.DependsListStr`, + but instead of the ('pkgname', 'version', 'relation') tuples, + it returns :class:`Dependency` objects, which can assist you with + useful functions. + + .. attribute:: ParentPkg + + The :class:`Package` object this version belongs to. + + .. attribute:: ProvidesList + + This returns a list of all packages provided by this version. Like + :attr:`Package.ProvidesList`, it returns a list of tuples + of the form ('virtualpkgname', ???, :class:`Version`), where as the + last item is the same as the object itself. + + .. attribute:: Size + + The size of the .deb file, in bytes. + + .. attribute:: InstalledSize + + The size of the package (in kilobytes), when unpacked on the disk. + + .. attribute:: Hash + + An integer hash value. + + .. attribute:: ID + + An integer id. + + .. attribute:: Priority + + The integer representation of the priority. This can be used to speed + up comparisons a lot, compared to :attr:`Version.PriorityStr`. + + The values are defined in the :mod:`apt_pkg` extension, see + :ref:`Priorities` for more information. + + .. attribute:: PriorityStr + + Return the priority of the package version, as a string, eg. + "optional". + + .. attribute:: Downloadable + + Whether this package can be downloaded from a remote site. + + .. attribute:: TranslatedDescription + + Return a :class:`Description` object. + + +:class:`Dependency` +------------------- +.. class:: Dependency + + Represent a dependency from one package to another one. + + .. method:: AllTargets + + A list of :class:`Version` objects which satisfy the dependency, + and do not conflict with already installed ones. + + From my experience, if you use this method to select the target + version, it is the best to select the last item unless any of the + other candidates is already installed. This leads to results being + very close to the normal package installation. + + .. method:: SmartTargetPkg + + Return a :class:`Version` object of a package which satisfies the + dependency and does not conflict with installed packages + (the 'natural target'). + + .. attribute:: TargetVer + + The target version of the dependency, as string. Empty string if the + dependency is not versioned. + + .. attribute:: TargetPkg + + The :class:`Package` object of the target package. + + .. attribute:: ParentVer + + The :class:`Version` object of the parent version, ie. the package + which declares the dependency. + + .. attribute:: ParentPkg + + The :class:`Package` object of the package which declares the + dependency. This is the same as using ParentVer.ParentPkg. + + .. attribute:: CompType + + The type of comparison (>=, ==, >>, <=), as string. + + .. attribute:: DepType + + The type of the dependency, as string, eg. "Depends". + + .. attribute:: ID + + The ID of the package, as integer. + +Example: Find all missing dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With the help of Dependency.AllTargets(), you can easily find all packages with +broken dependencies: + +.. literalinclude:: ../examples/missing-deps.py + + +:class:`Description` +-------------------- +.. class:: Description + + Represent the description of the package. + + .. attribute:: LanguageCode + + The language code of the description + + .. attribute:: md5 + + The md5 hashsum of the description + + .. attribute:: FileList + + A list of tuples (:class:`PackageFile`, int: index). + + + +:class:`pkgDepCache` +-------------------- +.. class:: pkgDepCache + + The pkgDepCache object contains various methods to manipulate the cache, + to install packages, to remove them, and much more. + + .. method:: Commit(fprogress, iprogress) + + Apply all the changes made. + + The parameter *fprogress* has to be set to an instance of + apt.progress.FetchProgress or one of its subclasses. + + The parameter *iprogress* has to be set to an instance of + apt.progress.InstallProgress or one of its subclasses. + + .. method:: FixBroken() + + Try to fix all broken packages in the cache. + + .. method:: GetCandidateVer(pkg) + + Return the candidate version of the package, ie. the version that + would be installed normally. + + The parameter *pkg* refers to an :class:`Package` object, + available using the :class:`pkgCache`. + + This method returns a :class:`Version` object. + + .. method:: SetCandidateVer(pkg, version) + + The opposite of :meth:`pkgDepCache.GetCandidateVer`. Set the candidate + version of the :class:`Package` *pkg* to the :class:`Version` + *version*. + + + .. method:: Upgrade([distUpgrade=False]) + + Perform an upgrade. More detailed, this marks all the upgradable + packages for upgrade. You still need to call + :meth:`pkgDepCache.Commit` for the changes to apply. + + To perform a dist-upgrade, the optional parameter *distUpgrade* has + to be set to True. + + .. method:: FixBroken() + + Fix broken packages. + + .. method:: ReadPinFile() + + Read the policy, eg. /etc/apt/preferences. + + .. method:: MinimizeUpgrade() + + Go over the entire set of packages and try to keep each package marked + for upgrade. If a conflict is generated then the package is restored. + + .. todo:: + Explain better.. + + .. method:: MarkKeep(pkg) + + Mark the :class:`Package` *pkg* for keep. + + .. method:: MarkDelete(pkg[, purge]) + + Mark the :class:`Package` *pkg* for delete. If *purge* is True, + the configuration files will be removed as well. + + .. method:: MarkInstall(pkg[, autoInst=True[, fromUser=True]]) + + Mark the :class:`Package` *pkg* for install. + + If *autoInst* is ``True``, the dependencies of the package will be + installed as well. This is the default. + + If *fromUser* is ``True``, the package will be marked as manually + installed. This is the default. + + .. method:: SetReinstall(pkg) + + Set if the :class:`Package` *pkg* should be reinstalled. + + .. method:: IsUpgradable(pkg) + + Return ``1`` if the package is upgradable. + + The package can be upgraded by calling :meth:`pkgDepCache.MarkInstall`. + + .. method:: IsNowBroken(pkg) + + Return `1` if the package is broken now (including changes made, but + not committed). + + .. method:: IsInstBroken(pkg) + + Return ``1`` if the package is broken on the current install. This + takes changes which have not been committed not into effect. + + .. method:: IsGarbage(pkg) + + Return ``1`` if the package is garbage, ie. if it is automatically + installed and no longer referenced by other packages. + + .. method:: IsAutoInstalled(pkg) + + Return ``1`` if the package is automatically installed (eg. as the + dependency of another package). + + .. method:: MarkedInstall(pkg) + + Return ``1`` if the package is marked for install. + + .. method:: MarkedUpgrade(pkg) + + Return ``1`` if the package is marked for upgrade. + + .. method:: MarkedDelete(pkg) + + Return ``1`` if the package is marked for delete. + + .. method:: MarkedKeep(pkg) + + Return ``1`` if the package is marked for keep. + + .. method:: MarkedReinstall(pkg) + + Return ``1`` if the package should be installed. + + .. method:: MarkedDowngrade(pkg) + + Return ``1`` if the package should be downgraded. + + .. attribute:: KeepCount + + Integer, number of packages marked as keep + + .. attribute:: InstCount + + Integer, number of packages marked for installation. + + .. attribute:: DelCount + + Number of packages which should be removed. + + .. attribute:: BrokenCount + + Number of packages which are broken. + + .. attribute:: UsrSize + + The size required for the changes on the filesystem. If you install + packages, this is positive, if you remove them its negative. + + .. attribute:: DebSize + + The size of the packages which are needed for the changes to be + applied. + + +:class:`MetaIndex` +------------------ + +.. todo:: + + Complete them + +.. class:: MetaIndex + + .. attribute:: URI + .. attribute:: Dist + .. attribute:: IsTrusted + .. attribute:: IndexFiles + + +:class:`PackageIndexFile` +------------------------- + +.. class:: PackageIndexFile + + .. method:: ArchiveURI(path) + + Return the full url to path in the archive. + + .. attribute:: Label + + Return the Label. + + .. attribute:: Exists + + Return whether the file exists. + + .. attribute:: HasPackages + + Return whether the file has packages. + + .. attribute:: Size + + Size of the file + + .. attribute:: IsTrusted + + Whether we can trust the file. + + +:class:`PkgManager` +------------------- + +.. class:: PkgManager + + Class, as returned by :func:`apt_pkg.GetPackageManager`. + + .. method:: GetArchives(fetcher, list, records) + + Add all the selected packages to the :class:`Acquire()` object + *fetcher*. + + The parameter *list* refers to a :class:`PkgSourceList()` object, as + returned by :func:`apt_pkg.GetPkgSourceList`. + + The parameter *records* refers to a :class:`pkgRecords()` object, as + returned by :func:`apt_pkg.GetPkgRecords`. + + .. method:: DoInstall() + + Install the packages. + + .. method:: FixMissing + + Fix the installation if a package could not be downloaded. + + .. attribute:: ResultCompleted + + A constant for checking whether the the result is 'completed'. + + Compare it against the return value of :meth:`PkgManager.GetArchives` + or :meth:`PkgManager.DoInstall`. + + .. attribute:: ResultFailed + + A constant for checking whether the the result is 'failed'. + + Compare it against the return value of :meth:`PkgManager.GetArchives` + or :meth:`PkgManager.DoInstall`. + + .. attribute:: ResultIncomplete + + A constant for checking whether the the result is 'incomplete'. + + Compare it against the return value of :meth:`PkgManager.GetArchives` + or :meth:`PkgManager.DoInstall`. + +:class:`pkgRecords` +-------------------- + +.. class:: PkgRecords + + Provide access to the packages records. This provides very useful + attributes for fast (convient) access to some fields of the record. + + See :func:`apt_pkg.GetPkgRecords` for initialization. + + + .. method:: Lookup(verfile_iter) + + Change the actual package to the package given by the verfile_iter. + + The parameter *verfile_iter* refers to a tuple consisting + of (:class:`PackageFile()`, int: index), as returned by various + attributes, including :attr:`Version.FileList`. + + Example (shortened):: + + cand = depcache.GetCandidateVer(cache['python-apt']) + records.Lookup(cand.FileList[0]) + # Now you can access the record + print records.SourcePkg # == python-apt + + .. attribute:: FileName + + Return the field 'Filename' of the record. This is the path to the + package, relative to the base path of the archive. + + .. attribute:: MD5Hash + + Return the MD5 hashsum of the package This refers to the field + 'MD5Sum' in the raw record. + + .. attribute:: SHA1Hash + + Return the SHA1 hashsum of the package. This refers to the field 'SHA1' + in the raw record. + + .. attribute:: SHA256Hash + + Return the SHA256 hashsum of the package. This refers to the field + 'SHA256' in the raw record. + + .. versionadded:: 0.7.9 + + .. attribute:: SourcePkg + + Return the source package. + + .. attribute:: SourceVer + + Return the source version. + + .. attribute:: Maintainer + + Return the maintainer of the package. + + .. attribute:: ShortDesc + + Return the short description. This is the summary on the first line of + the 'Description' field. + + .. attribute:: LongDesc + + Return the long description. These are lines 2-END from the + 'Description' field. + + .. attribute:: Name + + Return the name of the package. This is the 'Package' field. + + .. attribute:: Homepage + + Return the Homepage. This is the 'Homepage' field. + + .. attribute:: Record + + Return the whole record as a string. If you want to access fields of + the record not available as an attribute, you can use + :func:`apt_pkg.ParseSection` to parse the record and access the field + name. + + Example:: + + section = apt_pkg.ParseSection(records.Record) + print section['SHA256'] + +:class:`PkgSrcRecords` +---------------------- + +.. class:: PkgSrcRecords + + This represents the entries in the Sources files, ie. the dsc files of + the source packages. + + .. note:: + + If the Lookup failed, because no package could be found, no error is + raised. Instead, the attributes listed below are simply not existing + anymore (same applies when no Lookup has been made, or when it has + been restarted). + + .. method:: Lookup(pkgname) + + Lookup the record for the package named *pkgname*. To access all + available records, you need to call it multiple times. + + Imagine a package P with two versions X, Y. The first ``Lookup(P)`` + would set the record to version X and the second ``Lookup(P)`` to + version Y. + + .. method:: Restart() + + Restart the lookup. + + Imagine a package P with two versions X, Y. The first ``Lookup(P)`` + would set the record to version X and the second ``Lookup(P)`` to + version Y. + + If you now call ``Restart()``, the internal position will be cleared. + Now you can call ``Lookup(P)`` again to move to X. + + .. attribute:: Package + + The name of the source package. + + .. attribute:: Version + + A string describing the version of the source package. + + .. attribute:: Maintainer + + A string describing the name of the maintainer. + + .. attribute:: Section + + A string describing the section. + + .. attribute:: Record + + The whole record, as a string. You can use :func:`apt_pkg.ParseSection` + if you need to parse it. + + You need to parse the record if you want to access fields not available + via the attributes, eg. 'Standards-Version' + + .. attribute:: Binaries + + Return a list of strings describing the package names of the binaries + created by the source package. This matches the 'Binary' field in the + raw record. + + .. attribute:: Index + + The index in the Sources files. + + .. attribute:: Files + + The list of files. This returns a list of tuples with the contents + ``(str: md5, int: size, str: path, str:type)``. + + .. attribute:: BuildDepends + + Return the list of Build dependencies, as + ``(str: package, str: version, int: op, int: type)``. + + .. table:: Values of *op* + + ===== ============================================= + Value Meaning + ===== ============================================= + 0x0 No Operation (no versioned build dependency) + 0x10 | (or) - this will be added to the other values + 0x1 <= (less than or equal) + 0x2 >= (greater than or equal) + 0x3 << (less than) + 0x4 >> (greater than) + 0x5 == (equal) + 0x6 != (not equal) + ===== ============================================= + + .. table:: Values of *type* + + ===== =================== + Value Meaning + ===== =================== + 0 Build-Depends + 1 Build-Depends-Indep + 2 Build-Conflicts + 3 Build-Conflicts-Indep + ===== =================== + + **Example**: In the following content, we will imagine a + build-dependency:: + + Build-Depends: A (>= 1) | B (>= 1), C + + This results in:: + + [('A', '1', 18, 0), # 18 = 16 + 2 = 0x10 + 0x2 + ('B', '1', 2, 0), + ('C', '', 0, 0)] + + This is **not** the same as returned by + :func:`apt_pkg.ParseSrcDepends`. + + +:class:`PkgSourceList` +----------------------- + +.. class:: PkgSourceList + + This is for :file:`/etc/apt/sources.list`. + + .. method:: FindIndex(pkgfile) + + Return a :class:`PackageIndexFile` object for the :class:`PackageFile` + *pkgfile*. + + .. method:: ReadMainList + + Read the main list. + + .. method:: GetIndexes(acq[, all]) + + Add the index files to the :class:`Acquire()` object *acq*. If *all* is + given and ``True``, all files are fetched. + + +:class:`ProblemResolver` +------------------------ +.. class:: ProblemResolver + + The problem resolver helps when there are problems in the package + selection. An example is a package which conflicts with another, already + installed package. + + .. method:: Protect(pkg) + + Protect the :class:`Package()` object given by the parameter *pkg*. + + .. todo:: + + Really document it. + + .. method:: InstallProtect() + + Protect all installed packages from being removed. + + .. method:: Remove(pkg) + + Remove the :class:`Package()` object given by the parameter *pkg*. + + .. todo:: + + Really document it. + + .. method:: Clear(pkg) + + Reset the :class:`Package()` *pkg* to the default state. + + .. todo:: + + Really document it. + + .. method:: Resolve() + + Try to resolve problems by installing and removing packages. + + .. method:: ResolveByKeep() + + Try to resolve problems only by using keep. + + +:class:`TagFile` +---------------- + +.. class:: TagFile + + An object which represents a typical debian control file. Can be used for + Packages, Sources, control, Release, etc. + + Use :func:`apt_pkg.ParseTagFile` to parse a file. + + .. method:: Step + + Step forward to the next section. This simply returns ``1`` if OK, and + ``0`` if there is no section + + .. method:: Offset + + Return the current offset (in bytes) from the beginning of the file. + + .. method:: Jump(offset) + + Jump back/forward to *offset*. Use ``Jump(0)`` to jump to the + beginning of the file again. + + .. attribute:: Section + + This is the current :class:`TagSection()` instance. + +:class:`TagSection` +------------------- + +.. class:: TagSection + + Represent a single section of a debian control file. + + .. describe:: section[key] + + Return the value of the field at *key*. If *key* is not available, + raise :exc:`KeyError`. + + .. method:: Bytes + + The number of bytes in the section. + + .. method:: Find(key, default='') + + Return the value of the field at the key *key* if available, + else return *default*. + + .. method:: FindFlag(key) + + Find a yes/no value for the key *key*. An example for such a + field is 'Essential'. + + .. method:: get(key, default='') + + Return the value of the field at the key *key* if available, else + return *default*. + + .. method:: has_key(key) + + Check whether the field with named by *key* exists. + + .. method:: keys() + + Return a list of keys in the section. diff --git a/doc/source/apt_pkg/index.rst b/doc/source/apt_pkg/index.rst new file mode 100644 index 00000000..1c5866a9 --- /dev/null +++ b/doc/source/apt_pkg/index.rst @@ -0,0 +1,261 @@ +:mod:`apt_pkg` --- The low-level bindings for apt-pkg +===================================================== +.. module:: apt_pkg + +The apt_pkg extensions provides a more low-level way to work with apt. It can +do everything apt can, and is written in C++. It has been in python-apt since +the beginning. + + +.. toctree:: + :maxdepth: 2 + :glob: + + * + + +Module Initialization +--------------------- + + +.. function:: initConfig + + Initialize the configuration of apt. This is needed for most operations. + +.. function:: initSystem + + Initialize the system. + +.. function:: init + + Deprecated function. Use initConfig() and initSystem() instead. + +Object initialization +---------------------- +.. function:: GetCache([progress]) + + Return a :class:`pkgCache` object. The optional parameter ``progress`` + specifies an instance of :class:`apt.progress.OpProgress()` which will + display the open progress. + +.. function:: GetCdrom() + + Return a Cdrom object with the following methods: + + .. method:: Cdrom.Ident(progress) + + Identify the cdrom. The parameter ``progress`` refers to an + :class:`apt.progress.CdromProgress()` object. + + .. method:: Cdrom.Add(progress) + + Add the cdrom to the sources.list file. The parameter ``progress`` + refers to an :class:`apt.progress.CdromProgress()` object. + + + +.. function:: GetDepCache(cache) + + Return a :class:`pkgDepCache` object. The parameter ``cache`` specifies an + instance of :class:`pkgCache` (see :func:`GetCache()`). + + +.. function:: GetPkgSourceList() + + Return a :class:`pkgSourceList` object. + + +The Acquire interface +---------------------- +.. function:: GetAcquire([progress]) + + Return an :class:`Acquire` object. This is a class which allows you + to fetch files, or archive contents. The parameter ``progress`` refers to + an :class:`apt.progress.FetchProgress()` object. + + Acquire items have multiple methods: + + .. method:: Acquire.Run() + + Fetch all the items which have been added by :func:`GetPkgAcqFile`. + + .. method:: Acquire.Shutdown() + + Shut the fetcher down. + + .. attribute:: Acquire.TotalNeeded + + The total amount of bytes needed (including those of files which are + already present) + + .. attribute:: Acquire.FetchNeeded + + The total amount of bytes which need to be fetched. + + .. attribute:: Acquire.PartialPresent + + Whether some files have been acquired already. (???) + + +.. function:: GetPkgAcqFile(aquire, uri[, md5, size, descr, shortDescr, destDir, destFile]) + + The parameter ``acquire`` refers to an :class:`Acquire()` object as returned + by :func:`GetAcquire`. The file will be added to the Acquire queue + automatically. + + The parameter ``uri`` refers to the location of the file, any protocol + of apt is supported. + + The parameter ``md5`` refers to the md5sum of the file. This can be used + for checking the file. + + The parameter ``size`` can be used to specify the size of the package, + which can then be used to calculate the progress and validate the download. + + The parameter ``descr`` is a descripition of the download. It may be + used to describe the item in the progress class. ``shortDescr`` is the + short form of it. + + You can use ``destDir`` to manipulate the directory where the file will + be saved in. Together with ``destFile`` you can specify the complete target + path. + + + +Hash functions +-------------- +The apt_pkg module also provides several hash functions. If you develop +applications with python-apt it is often easier to use these functions instead +of the ones provides in Python's :mod:`hashlib` module. + +.. function:: md5sum(object) + + Return the md5sum of the object. ``object`` may either be a string, in + which case the md5sum of the string is returned, or a :class:`file()` + object, in which case the md5sum of its contents is returned. + +.. function:: sha1sum(object) + + Return the sha1sum of the object. ``object`` may either be a string, in + which case the sha1sum of the string is returned, or a :class:`file()` + object, in which case the sha1sum of its contents is returned. + +.. function:: sha256sum(object) + + Return the sha256sum of the object. ``object`` may either be a string, in + which case the sha256sum of the string is returned, or a :class:`file()` + object, in which case the sha256sum of its contents is returned. + +Other functions +---------------- + +.. note:: + + This documentation is created automatically and should be rewritten. + +.. autofunction:: Base64Encode +.. autofunction:: CheckDep +.. autofunction:: CheckDomainList +.. autofunction:: DeQuoteString +.. autofunction:: GetLock +.. autofunction:: GetPackageManager +.. autofunction:: GetPkgActionGroup +.. autofunction:: GetPkgProblemResolver +.. autofunction:: GetPkgRecords +.. autofunction:: GetPkgSrcRecords +.. autofunction:: newConfiguration +.. autofunction:: ParseCommandLine +.. autofunction:: ParseDepends +.. autofunction:: ParseSection +.. autofunction:: ParseSrcDepends +.. autofunction:: ParseTagFile +.. autofunction:: PkgSystemLock +.. autofunction:: PkgSystemUnLock +.. autofunction:: QuoteString +.. autofunction:: ReadConfigFile +.. autofunction:: ReadConfigFileISC +.. autofunction:: RewriteSection +.. autofunction:: SizeToStr +.. autofunction:: StringToBool +.. autofunction:: StrToTime +.. autofunction:: TimeRFC1123 +.. autofunction:: TimeToStr +.. autofunction:: UpstreamVersion +.. autofunction:: URItoFileName +.. autofunction:: VersionCompare + + +Data +----- + +.. data:: Config + + An :class:`Configuration()` object with the default configuration. Actually, + this is a bit different object, but it is compatible. + +.. data:: RewritePackageOrder + +.. data:: RewriteSourceOrder + + +.. _CurStates: + +Package States +^^^^^^^^^^^^^^^ +.. data:: CurStateConfigFiles +.. data:: CurStateHalfConfigured +.. data:: CurStateHalfInstalled +.. data:: CurStateInstalled +.. data:: CurStateNotInstalled +.. data:: CurStateUnPacked + + + + +Dependency types +^^^^^^^^^^^^^^^^ +.. data:: DepConflicts +.. data:: DepDepends +.. data:: DepObsoletes +.. data:: DepPreDepends +.. data:: DepRecommends +.. data:: DepReplaces +.. data:: DepSuggests + +.. _InstStates: + +Installed states +^^^^^^^^^^^^^^^^^ +.. data:: InstStateHold +.. data:: InstStateHoldReInstReq +.. data:: InstStateOk +.. data:: InstStateReInstReq + +.. _Priorities: + +Priorities +^^^^^^^^^^ +.. data:: PriExtra +.. data:: PriImportant +.. data:: PriOptional +.. data:: PriRequired +.. data:: PriStandard + + +.. _SelStates: + +Select states +^^^^^^^^^^^^^^ +.. data:: SelStateDeInstall +.. data:: SelStateHold +.. data:: SelStateInstall +.. data:: SelStatePurge +.. data:: SelStateUnknown + + +Build information +^^^^^^^^^^^^^^^^^ +.. data:: Date +.. data:: LibVersion +.. data:: Time +.. data:: Version diff --git a/doc/source/aptsources/distinfo.rst b/doc/source/aptsources/distinfo.rst new file mode 100644 index 00000000..96f9445d --- /dev/null +++ b/doc/source/aptsources/distinfo.rst @@ -0,0 +1,10 @@ +:mod:`aptsources.distinfo` --- provide meta information for distro repositories +=============================================================================== + +.. automodule:: aptsources.distinfo + :members: + :undoc-members: + + .. note:: + + This part of the documentation is created automatically. diff --git a/doc/source/aptsources/distro.rst b/doc/source/aptsources/distro.rst new file mode 100644 index 00000000..06ca0fda --- /dev/null +++ b/doc/source/aptsources/distro.rst @@ -0,0 +1,10 @@ +:mod:`aptsources.distro` --- Distribution abstraction of the sources.list +=============================================================================== + +.. automodule:: aptsources.distro + :members: + :undoc-members: + + .. note:: + + This part of the documentation is created automatically. diff --git a/doc/source/aptsources/index.rst b/doc/source/aptsources/index.rst new file mode 100644 index 00000000..898fbf74 --- /dev/null +++ b/doc/source/aptsources/index.rst @@ -0,0 +1,10 @@ +:mod:`aptsources` --- Working with sources.list +===================================================== +.. automodule:: aptsources + +.. toctree:: + :maxdepth: 2 + :glob: + + * + diff --git a/doc/source/aptsources/sourceslist.rst b/doc/source/aptsources/sourceslist.rst new file mode 100644 index 00000000..509db3ce --- /dev/null +++ b/doc/source/aptsources/sourceslist.rst @@ -0,0 +1,10 @@ +:mod:`aptsources.sourceslist` --- Provide an abstraction of the sources.list +============================================================================ + +.. automodule:: aptsources.sourceslist + :members: + :undoc-members: + + .. note:: + + This part of the documentation is created automatically. diff --git a/doc/source/coding.rst b/doc/source/coding.rst new file mode 100644 index 00000000..1357ce14 --- /dev/null +++ b/doc/source/coding.rst @@ -0,0 +1,168 @@ +Coding for python-apt +====================== +Let's say you need a new feature, you can develop it, and you want to get it +included in python-apt. Then be sure to follow the following guidelines. + +Available branches +------------------- +First of all, let's talk a bit about the bzr branches of python-apt. In the +following parts, we will assume that you use bzr to create your changes and +submit them. + +**mvo:** http://people.ubuntu.com/~mvo/bzr/python-apt/mvo + This is Michael Vogt's branch. Most of the development of apt happens here, + as he is the lead maintainer of python-apt. + + This branch is also available from Launchpads super mirror, via + ``lp:python-apt``. Checkouts from Launchpad are generally faster and can + use the bzr protocoll. + + VCS-Browser: https://code.launchpad.net/~mvo/python-apt/python-apt--mvo + +**debian-sid:** http://bzr.debian.org/apt/python-apt/debian-sid + This is the official Debian branch of python-apt. All code which will be + uploaded to Debian is here. It is not as up-to-date as the mvo branch, + because this branch often gets updated just right before the release + happens. + + VCS-Browser: http://bzr.debian.org/loggerhead/apt/python-apt/debian-sid/changes + +**jak:** http://bzr.debian.org/users/jak/python-apt/jak + This is Julian Andres Klode's (the documentation author's) branch. This + is the place where cleanup and documentation updates happen. It is based + off debian-sid or mvo. + + VCS-Browser: http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/changes + +**ubuntu:** ``lp:~ubuntu-core-dev/python-apt/ubuntu`` + This is the official Ubuntu development branch. The same notes apply as + for the debian-sid branch above. + + VCS-Browser: https://code.launchpad.net/~ubuntu-core-dev/python-apt/ubuntu + + +C++ Coding style +---------------- +When you work on the C++ code in the python/ directory, you should follow some +basic rules. + +The indentation of the code is a bit non-standard. We currently use 3 spaces +indentation for the C++ code. + +When you create new functions, you should follow some naming conventions. All +C++ functions are named according to the ``CamelCase`` convention. + +The resulting Python functions should be ``CamelCase`` as well in apt_pkg, or +``mixedCase`` in apt_inst. The same applies for variables, parameters, +attributes, etc. + +.. note:: + + This coding style guidelines are incomplete. If you have any questions + send an email to deity@lists.debian.org. + +.. note:: + + The coding style may be changed completely during the port to Python 3.0. + But this will not happen very soon. + + +Python Coding Style +------------------- +The coding style for all code written in python is :PEP:`8`. For modules added +from version 0.7.9 on, there are no exceptions. + +Modules introduced prior to 0.7.9 use mixedCase names for methods, functions +and variables. These names will be replaced by names conforming to :PEP:`8` +in a future release of python-apt. + +Therefore, try to reduce the introduction of the mixedName code to the absolute +minimum (sometimes you can also use shorter names). + +To prepare the port to Python 3.0, code should not use any functionality which +is deprecated as of Python 2.6. + +The has_key() functionality may be used only on TagSection objects; as they +provide no other way to do this. If someone is willing to adapt TagSection to +support ``key in mapping`` and ``iter(mapping)``, this would be great. + +.. note:: + + You can use the tool pep8.py from http://svn.browsershots.org/trunk/devtools/pep8/ + to validate your code. Please also run pylint, pychecker, and pyflakes and + fix all new **errors** they report (undefined names, etc.). + +Submitting your patch +--------------------- +First of all, the patch you create should be based against the debian-sid +branch of python-apt. + +Once you have made your change, check that it: + + * conforms to :PEP:`8` (checked with pep8.py). It should, at least not + introduce new errors. (and never have whitespace at end of line) + * produces no new errors in pychecker, pyflakes and pylint (unless you + can't fix them, but please tell so when requesting the merge, so it can + be fixed before hitting one of the main branches). + * does not change the behaviour of existing code in a non-compatible way. + +If your change follows all points of the checklist, you can commit it to your +repository. (You could commit it first, and check later, and then commit the +fixes, but commits should be logical and it makes no sense to have to commits +for one logical unit). + +Once you have made all your changes, you can run ``bzr send -o patch-name`` +to create a so called *merge-directive*, which contains your changes and +allows us to preserve the history of your changes. (But please replace patch-name +with something useful). + +Now report a bug against the python-apt package, attach the merge directive +you created in the previous step, and tag it with 'patch'. It might also be +a good idea to prefix the bug report with '[PATCH]'. + +If your patch introduces new functions, parameters, etc. , but does not update +the content of this documentation, please CC. jak@debian.org, and add a short +notice to the bug report. Also see `Documentation updates` + +Once your patch got merged, you can *pull* the branch into which it has been +merged into your local one. If you have made changes since you submitted your +patch, you may need to *merge* the branch instead. + +.. note:: + + If you plan to work on python-apt for a longer time, it may be a good + idea to publish your branch somewhere. Alioth (http://alioth.debian.org) + and Launchpad (https://launchpad.net) provide bzr hosting. You can also + use any webspace with ftp or sftp connection (for the upload). Then you do + not need to send *merge directives*, but you can point to your branch + instead. + + +Documentation updates +--------------------- +If you want to update the documentation, please follow the procedure as written +above. But please CC: jak@debian.org in the bug report. + +You can send your content in plain text, but reStructuredText is the preferred +format. I (Julian Andres Klode) will review your patch and will forward them to +Michael Vogt, for inclusion in his branch. On release, this will be merged into +the debian-sid branch. + + +Example patch session +---------------------- +In the following example, we edit a file, create a merge directive (an enhanced +patch), and report a wishlist bug with this patch against the python-apt +package:: + + user@pc:~$ bzr clone http://bzr.debian.org/apt/python-apt/debian-sid/ + user@pc:~$ cd debian-sid + user@pc:~/debian-sid$ editor FILES + user@pc:~/debian-sid$ pep8.py FILES # PEP 8 check, see above. + user@pc:~/debian-sid$ pylint -e FILES # Check with pylint + user@pc:~/debian-sid$ pyflakes FILES # Check with pyflakes + user@pc:~/debian-sid$ pychecker FILES # Check with pychecker + user@pc:~/debian-sid$ bzr commit + user@pc:~/debian-sid$ bzr send -o my-patch + user@pc:~/debian-sid$ reportbug --severity=wishlist --tag=patch --attach=my-patch python-apt + user@pc:~/debian-sid$ # Add --list-cc=jak@debian.org if you change docs. diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 00000000..8f71e3e3 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# +# python-apt documentation build configuration file, created by +# sphinx-quickstart on Wed Jan 7 17:04:36 2009. +# +# This file is execfile()d with the current directory set to its containing +# dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed +# automatically). +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. +import os +import sys + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, os.path.abspath('../..')) +if os.path.exists("../../build"): + for dirname in os.listdir('../../build'): + sys.path.insert(0, os.path.abspath('../../build/' + dirname)) + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', 'sphinx.ext.todo'] +intersphinx_mapping = {'http://docs.python.org/': None} + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'python-apt' +copyright = u'2009, Julian Andres Klode <jak@debian.org>' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.7' +# The full version, including alpha/beta/rc tags. +release = '0.7.9~exp2' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['.static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/<name>. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-aptdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source index, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'python-apt.tex', ur'python-apt Documentation', + ur'Julian Andres Klode <jak@debian.org>', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + +todo_include_todos = True diff --git a/doc/source/examples/apt-gtk.py b/doc/source/examples/apt-gtk.py new file mode 100644 index 00000000..c3bb09d5 --- /dev/null +++ b/doc/source/examples/apt-gtk.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +"""Example for gtk widgets""" +import pygtk +pygtk.require("2.0") +import gtk + +import apt.gtk.widgets + + +def main(): + """Main function.""" + win = gtk.Window() + win.connect("destroy", gtk.main_quit) + progress = apt.gtk.widgets.GtkAptProgress() + win.set_title("GtkAptProgress Demo") + win.add(progress) + progress.show() + win.show() + cache = apt.cache.Cache(progress.open) + if cache["xterm"].isInstalled: + cache["xterm"].markDelete() + else: + cache["xterm"].markInstall() + progress.show_terminal(expanded=True) + cache.commit(progress.fetch, progress.install) + gtk.main() + +if __name__ == "__main__": + main() diff --git a/doc/source/examples/cache-packages.py b/doc/source/examples/cache-packages.py new file mode 100644 index 00000000..1abe7cf2 --- /dev/null +++ b/doc/source/examples/cache-packages.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +"""Example for packages. Print all essential and important packages""" + +import apt_pkg + + +def main(): + """Main.""" + apt_pkg.InitConfig() + apt_pkg.InitSystem() + cache = apt_pkg.GetCache() + print "Essential packages:" + for pkg in cache.Packages: + if pkg.Essential: + print " ", pkg.Name + print "Important packages:" + for pkg in cache.Packages: + if pkg.Important: + print " ", pkg.Name + +if __name__ == "__main__": + main() diff --git a/doc/source/examples/cache-pkgfile.py b/doc/source/examples/cache-pkgfile.py new file mode 100644 index 00000000..f25975d3 --- /dev/null +++ b/doc/source/examples/cache-pkgfile.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +import apt_pkg + + +def main(): + """Example for PackageFile()""" + apt_pkg.init() + cache = apt_pkg.GetCache() + for pkgfile in cache.FileList: + print 'Package-File:', pkgfile.FileName + print 'Index-Type:', pkgfile.IndexType # 'Debian Package Index' + if pkgfile.NotSource: + print 'Source: None' + else: + if pkgfile.Site: + # There is a source, and a site, print the site + print 'Source:', pkgfile.Site + else: + # It seems to be a local repository + print 'Source: Local package file' + if pkgfile.NotAutomatic: + # The system won't be updated automatically (eg. experimental) + print 'Automatic: No' + else: + print 'Automatic: Yes' + print + +if __name__ == '__main__': + main() diff --git a/doc/source/examples/dpkg-contents.py b/doc/source/examples/dpkg-contents.py new file mode 100644 index 00000000..99d1596f --- /dev/null +++ b/doc/source/examples/dpkg-contents.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +"""Emulate dpkg --contents""" + +import grp +import pwd +import stat +import sys +import time + +import apt_inst + + +def format_mode(what, mode): + """Return the symbolic mode""" + s_mode = dict(DIR="d", HARDLINK="h", FILE="-").get(what) + s_mode += ((mode & stat.S_IRUSR) and "r" or "-") + s_mode += ((mode & stat.S_IWUSR) and "w" or "-") + s_mode += ((mode & stat.S_IXUSR) and (mode & stat.S_ISUID and "s" or "x") + or (mode & stat.S_ISUID and "S" or "-")) + s_mode += ((mode & stat.S_IRGRP) and "r" or "-") + s_mode += ((mode & stat.S_IWGRP) and "w" or "-") + s_mode += ((mode & stat.S_IXGRP) and (mode & stat.S_ISGID and "s" or "x") + or (mode & stat.S_ISGID and "S" or "-")) + s_mode += ((mode & stat.S_IROTH) and "r" or "-") + s_mode += ((mode & stat.S_IWOTH) and "w" or "-") + s_mode += ((mode & stat.S_IXOTH) and "x" or "-") + return s_mode + + +def callback(what, name, link, mode, uid, gid, size, mtime, major, minor): + """callback for debExtract""" + s_mode = format_mode(what, mode) + s_owner = "%s/%s" % (pwd.getpwuid(uid)[0], grp.getgrgid(gid)[0]) + s_size = "%9d" % size + s_time = time.strftime("%Y-%m-%d %H:%M", time.localtime(mtime)) + s_name = name.startswith(".") and name or ("./" + name) + if link: + s_name += " link to %s" % link + print s_mode, s_owner, s_size, s_time, s_name + + +def main(): + """Main function""" + if len(sys.argv) < 2: + print >> sys.stderr, "need filename argumnet" + sys.exit(1) + + fobj = open(sys.argv[1]) + try: + apt_inst.debExtract(fobj, callback, "data.tar.gz") + finally: + fobj.close() + +if __name__ == "__main__": + main() diff --git a/doc/source/examples/dpkg-extract.py b/doc/source/examples/dpkg-extract.py new file mode 100644 index 00000000..ced8652f --- /dev/null +++ b/doc/source/examples/dpkg-extract.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +"""Emulate dpkg --extract package.deb outdir""" +import os +import sys + +import apt_inst + + +def main(): + """Main function.""" + if len(sys.argv) < 3: + print >> sys.stderr, "Usage:", __file__, "package.deb outdir" + sys.exit(1) + if not os.path.exists(sys.argv[2]): + print >> sys.stderr, "The directory %s does not exist" % sys.argv[2] + sys.exit(1) + + fobj = open(sys.argv[1]) + try: + apt_inst.debExtractArchive(fobj, sys.argv[2]) + finally: + fobj.close() + +if __name__ == "__main__": + main() diff --git a/doc/source/examples/dpkg-info.py b/doc/source/examples/dpkg-info.py new file mode 100644 index 00000000..ff98d8b1 --- /dev/null +++ b/doc/source/examples/dpkg-info.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +"""Emulate dpkg --info package.deb control-file""" +import sys + +from apt_inst import debExtractControl + + +def main(): + """Main function.""" + if len(sys.argv) < 3: + print >> sys.stderr, 'Usage: tool file.deb control-file' + sys.exit(0) + fobj = open(sys.argv[1]) + try: + print debExtractControl(fobj, sys.argv[2]) + finally: + fobj.close() + +if __name__ == '__main__': + main() diff --git a/doc/source/examples/missing-deps.py b/doc/source/examples/missing-deps.py new file mode 100644 index 00000000..3ca16e45 --- /dev/null +++ b/doc/source/examples/missing-deps.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +"""Check the archive for missing dependencies""" +import apt_pkg + + +def fmt_dep(dep): + """Format a Dependency object [of apt_pkg] as a string.""" + ret = dep.TargetPkg.Name + if dep.TargetVer: + ret += " (%s %s)" % (dep.CompType, dep.TargetVer) + return ret + + +def check_version(pkgver): + """Check the version of the package""" + missing = [] + + for or_group in pkgver.DependsList.get("Pre-Depends", []) + \ + pkgver.DependsList.get("Depends", []): + if not any(dep.AllTargets() for dep in or_group): + # If none of the or-choices can be satisfied, add it to missing + missing.append(or_group) + + if missing: + print "Package:", pkgver.ParentPkg.Name + print "Version:", pkgver.VerStr + print "Missing:", + print ", ".join(" | ".join(fmt_dep(dep) for dep in or_group) + for or_group in missing) + print + + +def main(): + """The main function.""" + apt_pkg.InitConfig() + apt_pkg.InitSystem() + + cache = apt_pkg.GetCache() + + for pkg in sorted(cache.Packages, key=lambda pkg: pkg.Name): + # pkg is from a list of packages, sorted by name. + for version in pkg.VersionList: + # Check every version + for pfile, _ in version.FileList: + if (pfile.Origin == "Debian" and pfile.Component == "main" and + pfile.Archive == "unstable"): + # We only want packages from Debian unstable main. + check_version(version) + break + +if __name__ == "__main__": + main() diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 00000000..23ea4cca --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,41 @@ +Welcome to python-apt's documentation! +====================================== + +.. note:: + + This documentation can not be considered complete at the moment. But it + provides better documentation than the documentation available through + pydoc. + +.. note:: + + + This documentation has been created by Sphinx, using reStructuredText files + written by Julian Andres Klode <jak@debian.org>, and in case of the apt + package, from the documentation shipped in the modules. + + +Contents: + +.. toctree:: + :maxdepth: 2 + + apt/index + apt_pkg/index + apt_inst + aptsources/index + coding + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + + +TODO +====== +.. todolist:: diff --git a/po/python-apt.pot b/po/python-apt.pot index 7a1002fb..6af898db 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: 2008-11-24 14:45+0100\n" +"POT-Creation-Date: 2009-01-09 18:08+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -336,25 +336,25 @@ msgstr "" msgid "Custom servers" msgstr "" -#: ../apt/gtk/widgets.py:173 +#: ../apt/gtk/widgets.py:243 #, python-format msgid "Downloading file %(current)li of %(total)li with %(speed)s/s" msgstr "" -#: ../apt/gtk/widgets.py:179 +#: ../apt/gtk/widgets.py:249 #, python-format msgid "Downloading file %(current)li of %(total)li" msgstr "" #. Setup some child widgets -#: ../apt/gtk/widgets.py:220 +#: ../apt/gtk/widgets.py:269 msgid "Details" msgstr "" -#: ../apt/gtk/widgets.py:310 +#: ../apt/gtk/widgets.py:351 msgid "Starting..." msgstr "" -#: ../apt/gtk/widgets.py:313 +#: ../apt/gtk/widgets.py:357 msgid "Complete" msgstr "" diff --git a/python/acquire.cc b/python/acquire.cc index 9cf84928..1ecf55a5 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -16,7 +16,7 @@ static PyObject *AcquireItemAttr(PyObject *Self,char *Name) { pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self); - + if (strcmp("ID",Name) == 0) return Py_BuildValue("i",(*I)->ID); else if (strcmp("Status",Name) == 0) @@ -56,7 +56,7 @@ static PyObject *AcquireItemAttr(PyObject *Self,char *Name) static PyObject *AcquireItemRepr(PyObject *Self) { pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self); - + char S[300]; snprintf(S,sizeof(S),"<pkgAcquire::ItemIterator object: " "Status: %i Complete: %i Local: %i IsTrusted: %i " @@ -91,11 +91,11 @@ PyTypeObject AcquireItemType = static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) -{ +{ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); int pulseInterval = 500000; - if (PyArg_ParseTuple(Args, "|i", &pulseInterval) == 0) + if (PyArg_ParseTuple(Args, "|i", &pulseInterval) == 0) return 0; pkgAcquire::RunResult run = fetcher->Run(pulseInterval); @@ -104,19 +104,19 @@ static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) } static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) -{ +{ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); - if (PyArg_ParseTuple(Args, "") == 0) + if (PyArg_ParseTuple(Args, "") == 0) return 0; fetcher->Shutdown(); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } -static PyMethodDef PkgAcquireMethods[] = +static PyMethodDef PkgAcquireMethods[] = { {"Run",PkgAcquireRun,METH_VARARGS,"Run the fetcher"}, {"Shutdown",PkgAcquireShutdown, METH_VARARGS,"Shutdown the fetcher"}, @@ -128,16 +128,16 @@ static PyObject *AcquireAttr(PyObject *Self,char *Name) { pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); - if(strcmp("TotalNeeded",Name) == 0) + if(strcmp("TotalNeeded",Name) == 0) return Py_BuildValue("d", fetcher->TotalNeeded()); - if(strcmp("FetchNeeded",Name) == 0) + if(strcmp("FetchNeeded",Name) == 0) return Py_BuildValue("d", fetcher->FetchNeeded()); - if(strcmp("PartialPresent",Name) == 0) + if(strcmp("PartialPresent",Name) == 0) return Py_BuildValue("d", fetcher->PartialPresent()); - if(strcmp("Items",Name) == 0) + if(strcmp("Items",Name) == 0) { PyObject *List = PyList_New(0); - for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); + for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); I != fetcher->ItemsEnd(); I++) { PyObject *Obj; @@ -149,11 +149,11 @@ static PyObject *AcquireAttr(PyObject *Self,char *Name) return List; } // some constants - if(strcmp("ResultContinue",Name) == 0) + if(strcmp("ResultContinue",Name) == 0) return Py_BuildValue("i", pkgAcquire::Continue); - if(strcmp("ResultFailed",Name) == 0) + if(strcmp("ResultFailed",Name) == 0) return Py_BuildValue("i", pkgAcquire::Failed); - if(strcmp("ResultCancelled",Name) == 0) + if(strcmp("ResultCancelled",Name) == 0) return Py_BuildValue("i", pkgAcquire::Cancelled); return Py_FindMethod(PkgAcquireMethods,Self,Name); @@ -201,7 +201,7 @@ PyObject *GetAcquire(PyObject *Self,PyObject *Args) CppPyObject<pkgAcquire*> *FetcherObj = CppPyObject_NEW<pkgAcquire*>(&PkgAcquireType, fetcher); - + return FetcherObj; } @@ -255,8 +255,8 @@ PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) "destDir", "destFile", NULL}; if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, - &PkgAcquireType, &pyfetcher, &uri, &md5, - &size, &descr, &shortDescr, &destDir, &destFile) == 0) + &PkgAcquireType, &pyfetcher, &uri, &md5, + &size, &descr, &shortDescr, &destDir, &destFile) == 0) return 0; pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher); diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index ea703b21..48868d86 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -5,10 +5,10 @@ apt_intmodule - Top level for the python module. Create the internal structures for the module in the interpriter. - + Note, this module shares state (particularly global config) with the apt_pkg module. - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -17,7 +17,7 @@ #include <apt-pkg/debfile.h> #include <apt-pkg/error.h> - + #include <sys/stat.h> #include <unistd.h> #include <Python.h> @@ -37,7 +37,7 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args) PyObject *File; if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Member) == 0) return 0; - + // Subscope makes sure any clean up errors are properly handled. PyObject *Res = 0; { @@ -46,13 +46,13 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args) debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); - + debDebFile::MemControlExtract Extract(Member); if (Extract.Read(Deb) == false) return HandleErrors(); - + // Build the return result - + if (Extract.Control == 0) { Py_INCREF(Py_None); @@ -61,7 +61,7 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args) else Res = PyString_FromStringAndSize(Extract.Control,Extract.Length+2); } - + return HandleErrors(Res); } /*}}}*/ @@ -78,11 +78,11 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) PyObject *File; if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Rootdir) == 0) return 0; - + // Subscope makes sure any clean up errors are properly handled. bool res = false; { - if(Rootdir != NULL) + if(Rootdir != NULL) { getcwd(cwd, sizeof(cwd)); chdir(Rootdir); @@ -105,7 +105,7 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) chdir (cwd); if (res == false) return HandleErrors(Py_BuildValue("b",res)); - } + } return HandleErrors(Py_BuildValue("b",res)); } /*}}}*/ @@ -120,13 +120,13 @@ static PyObject *arCheckMember(PyObject *Self,PyObject *Args) PyObject *File; if (PyArg_ParseTuple(Args,"O!s",&PyFile_Type,&File,&Member) == 0) return 0; - + // Open the file and associate the .deb FileFd Fd(fileno(PyFile_AsFile(File)),false); ARArchive AR(Fd); if (_error->PendingError() == true) return HandleErrors(Py_BuildValue("b",res)); - + if(AR.FindMember(Member) != 0) res = true; diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index c8d09736..45ba5f85 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -4,7 +4,7 @@ /* ###################################################################### Prototypes for the module - + ##################################################################### */ /*}}}*/ #ifndef APT_INSTMODULE_H diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 7b13c838..2e488d58 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -5,7 +5,7 @@ apt_pkgmodule - Top level for the python module. Create the internal structures for the module in the interpriter. - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -22,7 +22,7 @@ #include <apt-pkg/sha256.h> #include <apt-pkg/init.h> #include <apt-pkg/pkgsystem.h> - + #include <sys/stat.h> #include <unistd.h> #include <Python.h> @@ -46,16 +46,16 @@ static PyObject *VersionCompare(PyObject *Self,PyObject *Args) char *B; int LenA; int LenB; - + if (PyArg_ParseTuple(Args,"s#s#",&A,&LenA,&B,&LenB) == 0) return 0; - + if (_system == 0) { PyErr_SetString(PyExc_ValueError,"_system not initialized"); return 0; } - + return Py_BuildValue("i",_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB)); } @@ -66,7 +66,7 @@ static PyObject *CheckDep(PyObject *Self,PyObject *Args) char *B; char *OpStr; unsigned int Op = 0; - + if (PyArg_ParseTuple(Args,"sss",&A,&OpStr,&B) == 0) return 0; if (*debListParser::ConvertRelation(OpStr,Op) != 0) @@ -80,7 +80,7 @@ static PyObject *CheckDep(PyObject *Self,PyObject *Args) PyErr_SetString(PyExc_ValueError,"_system not initialized"); return 0; } - + return Py_BuildValue("i",_system->VS->CheckDep(A,Op,B)); // return Py_BuildValue("i",pkgCheckDep(B,A,Op)); } @@ -94,7 +94,7 @@ static PyObject *UpstreamVersion(PyObject *Self,PyObject *Args) return CppPyString(_system->VS->UpstreamVersion(Ver)); } -static char *doc_ParseDepends = +static char *doc_ParseDepends = "ParseDepends(s) -> list of tuples\n" "\n" "The resulting tuples are (Pkg,Ver,Operation). Each anded dependency is a\n" @@ -107,11 +107,11 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, string Package; string Version; unsigned int Op; - + const char *Start; const char *Stop; int Len; - + if (PyArg_ParseTuple(Args,"s#",&Start,&Len) == 0) return 0; Stop = Start + Len; @@ -121,7 +121,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, { if (Start == Stop) break; - + Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op, ParseArchFlags); if (Start == 0) @@ -130,10 +130,10 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, Py_DECREF(List); return 0; } - + if (LastRow == 0) LastRow = PyList_New(0); - + if (Package.empty() == false) { PyObject *Obj; @@ -142,7 +142,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, pkgCache::CompTypeDeb(Op))); Py_DECREF(Obj); } - + // Group ORd deps into a single row.. if ((Op & pkgCache::Dep::Or) != pkgCache::Dep::Or) { @@ -150,7 +150,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, PyList_Append(List,LastRow); Py_DECREF(LastRow); LastRow = 0; - } + } } return List; } @@ -171,7 +171,7 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) PyObject *Obj; if (PyArg_ParseTuple(Args,"O",&Obj) == 0) return 0; - + // Digest of a string. if (PyString_Check(Obj) != 0) { @@ -181,8 +181,8 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) PyString_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); - } - + } + // Digest of a file if (PyFile_Check(Obj) != 0) { @@ -195,10 +195,10 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) PyErr_SetFromErrno(PyExc_SystemError); return 0; } - + return CppPyString(Sum.Result().Value()); } - + PyErr_SetString(PyExc_TypeError,"Only understand strings and files"); return 0; } @@ -211,7 +211,7 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) PyObject *Obj; if (PyArg_ParseTuple(Args,"O",&Obj) == 0) return 0; - + // Digest of a string. if (PyString_Check(Obj) != 0) { @@ -221,8 +221,8 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) PyString_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); - } - + } + // Digest of a file if (PyFile_Check(Obj) != 0) { @@ -235,10 +235,10 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) PyErr_SetFromErrno(PyExc_SystemError); return 0; } - + return CppPyString(Sum.Result().Value()); } - + PyErr_SetString(PyExc_TypeError,"Only understand strings and files"); return 0; } @@ -251,7 +251,7 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) PyObject *Obj; if (PyArg_ParseTuple(Args,"O",&Obj) == 0) return 0; - + // Digest of a string. if (PyString_Check(Obj) != 0) { @@ -261,8 +261,8 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) PyString_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); - } - + } + // Digest of a file if (PyFile_Check(Obj) != 0) { @@ -275,27 +275,27 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) PyErr_SetFromErrno(PyExc_SystemError); return 0; } - + return CppPyString(Sum.Result().Value()); } - + PyErr_SetString(PyExc_TypeError,"Only understand strings and files"); return 0; } /*}}}*/ // init - 3 init functions /*{{{*/ // --------------------------------------------------------------------- -static char *doc_Init = +static char *doc_Init = "init() -> None\n" "Legacy. Do InitConfig then parse the command line then do InitSystem\n"; static PyObject *Init(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - - pkgInitConfig(*_config); + + pkgInitConfig(*_config); pkgInitSystem(*_config,_system); - + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -307,9 +307,9 @@ static PyObject *InitConfig(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - - pkgInitConfig(*_config); - + + pkgInitConfig(*_config); + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -321,9 +321,9 @@ static PyObject *InitSystem(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + pkgInitSystem(*_config,_system); - + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -331,7 +331,7 @@ static PyObject *InitSystem(PyObject *Self,PyObject *Args) // fileutils.cc: GetLock /*{{{*/ // --------------------------------------------------------------------- -static char *doc_GetLock = +static char *doc_GetLock = "GetLock(string) -> int\n" "This will create an empty file of the given name and lock it. Once this" " is done all other calls to GetLock in any other process will fail with" @@ -343,7 +343,7 @@ static PyObject *GetLock(PyObject *Self,PyObject *Args) char errors = false; if (PyArg_ParseTuple(Args,"s|b",&file,&errors) == 0) return 0; - + int fd = GetLock(file, errors); return HandleErrors(Py_BuildValue("i", fd)); @@ -356,9 +356,9 @@ static PyObject *PkgSystemLock(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + bool res = _system->Lock(); - + Py_INCREF(Py_None); return HandleErrors(Py_BuildValue("b", res)); } @@ -370,9 +370,9 @@ static PyObject *PkgSystemUnLock(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + bool res = _system->UnLock(); - + Py_INCREF(Py_None); return HandleErrors(Py_BuildValue("b", res)); } @@ -382,7 +382,7 @@ static PyObject *PkgSystemUnLock(PyObject *Self,PyObject *Args) // initapt_pkg - Core Module Initialization /*{{{*/ // --------------------------------------------------------------------- /* */ -static PyMethodDef methods[] = +static PyMethodDef methods[] = { // Constructors {"newConfiguration",newConfiguration,METH_VARARGS,doc_newConfiguration}, @@ -404,16 +404,16 @@ static PyMethodDef methods[] = {"ReadConfigFile",LoadConfig,METH_VARARGS,doc_LoadConfig}, {"ReadConfigFileISC",LoadConfigISC,METH_VARARGS,doc_LoadConfig}, {"ParseCommandLine",ParseCommandLine,METH_VARARGS,doc_ParseCommandLine}, - + // Versioning {"VersionCompare",VersionCompare,METH_VARARGS,doc_VersionCompare}, {"CheckDep",CheckDep,METH_VARARGS,doc_CheckDep}, {"UpstreamVersion",UpstreamVersion,METH_VARARGS,doc_UpstreamVersion}, - + // Depends {"ParseDepends",ParseDepends,METH_VARARGS,doc_ParseDepends}, {"ParseSrcDepends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends}, - + // Stuff {"md5sum",md5sum,METH_VARARGS,doc_md5sum}, {"sha1sum",sha1sum,METH_VARARGS,doc_sha1sum}, @@ -473,13 +473,13 @@ extern "C" void initapt_pkg() { PyObject *Module = Py_InitModule("apt_pkg",methods); PyObject *Dict = PyModule_GetDict(Module); - + // Global variable linked to the global configuration class CppPyObject<Configuration *> *Config = CppPyObject_NEW<Configuration *>(&ConfigurationPtrType); Config->Object = _config; PyDict_SetItemString(Dict,"Config",Config); Py_DECREF(Config); - + // Tag file constants PyObject *Obj; PyDict_SetItemString(Dict,"RewritePackageOrder", @@ -488,7 +488,7 @@ extern "C" void initapt_pkg() PyDict_SetItemString(Dict,"RewriteSourceOrder", Obj = CharCharToList(TFRewriteSourceOrder)); Py_DECREF(Obj); - + // Version.. AddStr(Dict,"Version",pkgVersion); AddStr(Dict,"LibVersion",pkgLibVersion); @@ -529,4 +529,4 @@ extern "C" void initapt_pkg() AddInt(Dict,"InstStateHoldReInstReq",pkgCache::State::HoldReInstReq); } /*}}}*/ - + diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 6e02d8e3..38486182 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -4,7 +4,7 @@ /* ###################################################################### Prototypes for the module - + ##################################################################### */ /*}}}*/ #ifndef APT_PKGMODULE_H @@ -49,7 +49,7 @@ PyObject *StrStringToBool(PyObject *self,PyObject *Args); PyObject *StrTimeRFC1123(PyObject *self,PyObject *Args); PyObject *StrStrToTime(PyObject *self,PyObject *Args); PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args); - + // Cache Stuff extern PyTypeObject PkgCacheType; extern PyTypeObject PkgCacheFileType; diff --git a/python/cache.cc b/python/cache.cc index bd280dec..1c59bece 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -32,7 +32,7 @@ struct PkgListStruct { pkgCache::PkgIterator Iter; unsigned long LastIndex; - + PkgListStruct(pkgCache::PkgIterator const &I) : Iter(I), LastIndex(0) {} PkgListStruct() {abort();}; // G++ Bug.. }; @@ -43,7 +43,7 @@ struct RDepListStruct pkgCache::DepIterator Start; unsigned long LastIndex; unsigned long Len; - + RDepListStruct(pkgCache::DepIterator const &I) : Iter(I), Start(I), LastIndex(0) { @@ -68,14 +68,14 @@ static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I) Ver); PyList_Append(List,Obj); Py_DECREF(Obj); - } + } return List; } // Cache Class /*{{{*/ // --------------------------------------------------------------------- static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) -{ +{ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); @@ -94,7 +94,7 @@ static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) } static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) -{ +{ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); Cache->Close(); @@ -104,7 +104,7 @@ static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) } static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) -{ +{ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); @@ -134,7 +134,7 @@ static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) } -static PyMethodDef PkgCacheMethods[] = +static PyMethodDef PkgCacheMethods[] = { {"Update",PkgCacheUpdate,METH_VARARGS,"Update the cache"}, {"Open", PkgCacheOpen, METH_VARARGS,"Open the cache"}, @@ -145,7 +145,7 @@ static PyMethodDef PkgCacheMethods[] = static PyObject *CacheAttr(PyObject *Self,char *Name) { pkgCache *Cache = GetCpp<pkgCache *>(Self); - + if (strcmp("Packages",Name) == 0) return CppOwnedPyObject_NEW<PkgListStruct>(Self,&PkgListType,Cache->PkgBegin()); else if (strcmp("PackageCount",Name) == 0) @@ -169,7 +169,7 @@ static PyObject *CacheAttr(PyObject *Self,char *Name) Obj = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PackageFileType,I); PyList_Append(List,Obj); Py_DECREF(Obj); - } + } return List; } @@ -180,15 +180,15 @@ static PyObject *CacheAttr(PyObject *Self,char *Name) static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) { pkgCache *Cache = GetCpp<pkgCache *>(Self); - + if (PyString_Check(Arg) == 0) { PyErr_SetNone(PyExc_TypeError); return 0; } - + // Search for the package - const char *Name = PyString_AsString(Arg); + const char *Name = PyString_AsString(Arg); pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); if (Pkg.end() == true) { @@ -274,7 +274,7 @@ static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index) Self.LastIndex = 0; Self.Iter = Self.Iter.Cache()->PkgBegin(); } - + while ((unsigned)Index > Self.LastIndex) { Self.LastIndex++; @@ -285,12 +285,12 @@ static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index) return 0; } } - + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PackageType, Self.Iter); } -static PySequenceMethods PkgListSeq = +static PySequenceMethods PkgListSeq = { PkgListLen, 0, // concat @@ -298,9 +298,9 @@ static PySequenceMethods PkgListSeq = PkgListItem, 0, // slice 0, // assign item - 0 // assign slice + 0 // assign slice }; - + PyTypeObject PkgListType = { PyObject_HEAD_INIT(&PyType_Type) @@ -320,7 +320,7 @@ PyTypeObject PkgListType = 0, // tp_as_mapping 0, // tp_hash }; - + /*}}}*/ // Package Class /*{{{*/ // --------------------------------------------------------------------- @@ -328,7 +328,7 @@ static PyObject *PackageAttr(PyObject *Self,char *Name) { pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self); - + if (strcmp("Name",Name) == 0) return PyString_FromString(Pkg.Name()); else if (strcmp("VersionList",Name) == 0) @@ -340,7 +340,7 @@ static PyObject *PackageAttr(PyObject *Self,char *Name) Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,I); PyList_Append(List,Obj); Py_DECREF(Obj); - } + } return List; } else if (strcmp("CurrentVer",Name) == 0) @@ -350,7 +350,7 @@ static PyObject *PackageAttr(PyObject *Self,char *Name) Py_INCREF(Py_None); return Py_None; } - + return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType, Pkg.CurrentVer()); } @@ -375,7 +375,7 @@ static PyObject *PackageAttr(PyObject *Self,char *Name) return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Essential) != 0); else if (strcmp("Important",Name) == 0) return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Important) != 0); - + PyErr_SetString(PyExc_AttributeError,Name); return 0; } @@ -383,7 +383,7 @@ static PyObject *PackageAttr(PyObject *Self,char *Name) static PyObject *PackageRepr(PyObject *Self) { pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); - + char S[300]; snprintf(S,sizeof(S),"<pkgCache::Package object: Name:'%s' Section: '%s'" " ID:%u Flags:0x%lX>", @@ -417,7 +417,7 @@ static PyObject *DescriptionAttr(PyObject *Self,char *Name) { pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DescIterator>(Self); - + if (strcmp("LanguageCode",Name) == 0) return PyString_FromString(Desc.LanguageCode()); else if (strcmp("md5",Name) == 0) @@ -425,8 +425,8 @@ static PyObject *DescriptionAttr(PyObject *Self,char *Name) else if (strcmp("FileList",Name) == 0) { /* The second value in the tuple is the index of the VF item. If the - user wants to request a lookup then that number will be used. - Maybe later it can become an object. */ + user wants to request a lookup then that number will be used. + Maybe later it can become an object. */ PyObject *List = PyList_New(0); for (pkgCache::DescFileIterator I = Desc.FileList(); I.end() == false; I++) { @@ -436,7 +436,7 @@ static PyObject *DescriptionAttr(PyObject *Self,char *Name) Obj = Py_BuildValue("Nl",DescFile,I.Index()); PyList_Append(List,Obj); Py_DECREF(Obj); - } + } return List; } PyErr_SetString(PyExc_AttributeError,Name); @@ -446,7 +446,7 @@ static PyObject *DescriptionAttr(PyObject *Self,char *Name) static PyObject *DescriptionRepr(PyObject *Self) { pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); - + char S[300]; snprintf(S,sizeof(S), "<pkgCache::Description object: language_code:'%s' md5:'%s' ", @@ -477,14 +477,14 @@ PyTypeObject DescriptionType = // Version Class /*{{{*/ // --------------------------------------------------------------------- -/* This is the simple depends result, the elements are split like +/* This is the simple depends result, the elements are split like ParseDepends does */ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, bool AsObj) { PyObject *Dict = PyDict_New(); PyObject *LastDep = 0; - unsigned LastDepType = 0; + unsigned LastDepType = 0; for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) { pkgCache::DepIterator Start; @@ -498,7 +498,7 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, // it sucks to have it here duplicated, but we get it // translated from libapt and that is certainly not what // we want in a programing interface - const char *Types[] = + const char *Types[] = { "", "Depends","PreDepends","Suggests", "Recommends","Conflicts","Replaces", @@ -512,10 +512,10 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, LastDep = PyList_New(0); PyDict_SetItem(Dict,Dep,LastDep); Py_DECREF(LastDep); - } + } Py_DECREF(Dep); } - + PyObject *OrGroup = PyList_New(0); while (1) { @@ -535,19 +535,19 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, Start.TargetPkg().Name(), Start.TargetVer(), Start.CompType()); - } + } PyList_Append(OrGroup,Obj); Py_DECREF(Obj); - + if (Start == End) break; Start++; } - + PyList_Append(LastDep,OrGroup); Py_DECREF(OrGroup); - } - + } + return Dict; } @@ -555,7 +555,7 @@ static PyObject *VersionAttr(PyObject *Self,char *Name) { pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); - + if (strcmp("VerStr",Name) == 0) return PyString_FromString(Ver.VerStr()); else if (strcmp("Section",Name) == 0) @@ -565,8 +565,8 @@ static PyObject *VersionAttr(PyObject *Self,char *Name) else if (strcmp("FileList",Name) == 0) { /* The second value in the tuple is the index of the VF item. If the - user wants to request a lookup then that number will be used. - Maybe later it can become an object. */ + user wants to request a lookup then that number will be used. + Maybe later it can become an object. */ PyObject *List = PyList_New(0); for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; I++) { @@ -576,7 +576,7 @@ static PyObject *VersionAttr(PyObject *Self,char *Name) Obj = Py_BuildValue("Nl",PkgFile,I.Index()); PyList_Append(List,Obj); Py_DECREF(Obj); - } + } return List; } else if (strcmp("DependsListStr",Name) == 0) @@ -629,7 +629,7 @@ static PyObject *VersionAttr(PyObject *Self,char *Name) static PyObject *VersionRepr(PyObject *Self) { pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); - + char S[300]; snprintf(S,sizeof(S),"<pkgCache::Version object: Pkg:'%s' Ver:'%s' " "Section:'%s' Arch:'%s' Size:%lu ISize:%lu Hash:%u " @@ -659,16 +659,16 @@ PyTypeObject VersionType = 0, // tp_as_mapping 0, // tp_hash }; - + /*}}}*/ - + // PackageFile Class /*{{{*/ // --------------------------------------------------------------------- static PyObject *PackageFileAttr(PyObject *Self,char *Name) { pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); // PyObject *Owner = GetOwner<pkgCache::PkgFileIterator>(Self); - + if (strcmp("FileName",Name) == 0) return Safe_FromString(File.FileName()); else if (strcmp("Archive",Name) == 0) @@ -695,7 +695,7 @@ static PyObject *PackageFileAttr(PyObject *Self,char *Name) return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotAutomatic) != 0); else if (strcmp("ID",Name) == 0) return Py_BuildValue("i",File->ID); - + PyErr_SetString(PyExc_AttributeError,Name); return 0; } @@ -703,7 +703,7 @@ static PyObject *PackageFileAttr(PyObject *Self,char *Name) static PyObject *PackageFileRepr(PyObject *Self) { pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); - + char S[300]; snprintf(S,sizeof(S),"<pkgCache::PackageFile object: " "File:'%s' a=%s,c=%s,v=%s,o=%s,l=%s " @@ -734,7 +734,7 @@ PyTypeObject PackageFileType = 0, // tp_as_mapping 0, // tp_hash }; - + // depends class static PyObject *DependencyRepr(PyObject *Self) @@ -754,7 +754,7 @@ static PyObject *DepSmartTargetPkg(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); @@ -764,7 +764,7 @@ static PyObject *DepSmartTargetPkg(PyObject *Self,PyObject *Args) Py_INCREF(Py_None); return Py_None; } - + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType,P); } @@ -772,7 +772,7 @@ static PyObject *DepAllTargets(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); @@ -789,7 +789,7 @@ static PyObject *DepAllTargets(PyObject *Self,PyObject *Args) return List; } -static PyMethodDef DependencyMethods[] = +static PyMethodDef DependencyMethods[] = { {"SmartTargetPkg",DepSmartTargetPkg,METH_VARARGS,"Returns the natural Target or None"}, {"AllTargets",DepAllTargets,METH_VARARGS,"Returns all possible Versions that match this dependency"}, @@ -798,18 +798,18 @@ static PyMethodDef DependencyMethods[] = // Dependency Class /*{{{*/ // --------------------------------------------------------------------- - + static PyObject *DependencyAttr(PyObject *Self,char *Name) { pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); - + if (strcmp("TargetVer",Name) == 0) { if (Dep->Version == 0) return PyString_FromString(""); return PyString_FromString(Dep.TargetVer()); - } + } else if (strcmp("TargetPkg",Name) == 0) return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType, Dep.TargetPkg()); @@ -824,7 +824,7 @@ static PyObject *DependencyAttr(PyObject *Self,char *Name) return PyString_FromString(Dep.DepType()); else if (strcmp("ID",Name) == 0) return Py_BuildValue("i",Dep->ID); - + return Py_FindMethod(DependencyMethods,Self,Name); } @@ -847,7 +847,7 @@ PyTypeObject DependencyType = 0, // tp_as_mapping 0, // tp_hash }; - + /*}}}*/ /*}}}*/ // Reverse Dependency List Class /*{{{*/ @@ -865,13 +865,13 @@ static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index) PyErr_SetNone(PyExc_IndexError); return 0; } - + if ((unsigned)Index < Self.LastIndex) { Self.LastIndex = 0; Self.Iter = Self.Start; } - + while ((unsigned)Index > Self.LastIndex) { Self.LastIndex++; @@ -882,12 +882,12 @@ static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index) return 0; } } - + return CppOwnedPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf), &DependencyType,Self.Iter); } -static PySequenceMethods RDepListSeq = +static PySequenceMethods RDepListSeq = { RDepListLen, 0, // concat @@ -895,9 +895,9 @@ static PySequenceMethods RDepListSeq = RDepListItem, 0, // slice 0, // assign item - 0 // assign slice + 0 // assign slice }; - + PyTypeObject RDepListType = { PyObject_HEAD_INIT(&PyType_Type) @@ -917,7 +917,7 @@ PyTypeObject RDepListType = 0, // tp_as_mapping 0, // tp_hash }; - + /*}}}*/ @@ -948,7 +948,7 @@ PyObject *TmpGetCache(PyObject *Self,PyObject *Args) CppOwnedPyObject<pkgCacheFile*> *CacheFileObj = CppOwnedPyObject_NEW<pkgCacheFile*>(0,&PkgCacheFileType, Cache); - + CppOwnedPyObject<pkgCache *> *CacheObj = CppOwnedPyObject_NEW<pkgCache *>(CacheFileObj,&PkgCacheType, (pkgCache *)(*Cache)); diff --git a/python/cdrom.cc b/python/cdrom.cc index aca1be26..0831548e 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -19,7 +19,7 @@ struct PkgCdromStruct }; static PyObject *PkgCdromAdd(PyObject *Self,PyObject *Args) -{ +{ PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self); PyObject *pyCdromProgressInst = 0; @@ -32,11 +32,11 @@ static PyObject *PkgCdromAdd(PyObject *Self,PyObject *Args) bool res = Struct.cdrom.Add(&progress); - return HandleErrors(Py_BuildValue("b", res)); + return HandleErrors(Py_BuildValue("b", res)); } static PyObject *PkgCdromIdent(PyObject *Self,PyObject *Args) -{ +{ PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self); PyObject *pyCdromProgressInst = 0; @@ -52,11 +52,11 @@ static PyObject *PkgCdromIdent(PyObject *Self,PyObject *Args) PyObject *result = Py_BuildValue("(bs)", res, ident.c_str()); - return HandleErrors(result); + return HandleErrors(result); } -static PyMethodDef PkgCdromMethods[] = +static PyMethodDef PkgCdromMethods[] = { {"Add",PkgCdromAdd,METH_VARARGS,"Add a cdrom"}, {"Ident",PkgCdromIdent,METH_VARARGS,"Ident a cdrom"}, @@ -100,7 +100,7 @@ PyObject *GetCdrom(PyObject *Self,PyObject *Args) CppOwnedPyObject<pkgCdrom> *CdromObj = CppOwnedPyObject_NEW<pkgCdrom>(0,&PkgCdromType, *cdrom); - + return CdromObj; } diff --git a/python/configuration.cc b/python/configuration.cc index 55eac1bf..f52c3c97 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -10,10 +10,10 @@ ConfigurationPtr - A pointer to a configuration instance, used only for the global instance (_config) ConfigurationSub - A subtree - has a reference to its owner. - + The wrapping is mostly 1:1 with the C++ code, but there are additions to - wrap the linked tree walking into nice flat sequence walking. - + wrap the linked tree walking into nice flat sequence walking. + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -113,7 +113,7 @@ static PyObject *CnfSet(PyObject *Self,PyObject *Args) char *Value = 0; if (PyArg_ParseTuple(Args,"ss",&Name,&Value) == 0) return 0; - + GetSelf(Self).Set(Name,Value); Py_INCREF(Py_None); return Py_None; @@ -134,9 +134,9 @@ static PyObject *CnfClear(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"s",&Name) == 0) return 0; - + GetSelf(Self).Clear(Name); - + Py_INCREF(Py_None); return Py_None; } @@ -170,7 +170,7 @@ static PyObject *CnfList(PyObject *Self,PyObject *Args) char *RootName = 0; if (PyArg_ParseTuple(Args,"|s",&RootName) == 0) return 0; - + // Convert the whole configuration space into a list PyObject *List = PyList_New(0); const Configuration::Item *Top = GetSelf(Self).Tree(RootName); @@ -180,10 +180,10 @@ static PyObject *CnfList(PyObject *Self,PyObject *Args) for (; Top != 0; Top = Top->Next) { PyObject *Obj; - PyList_Append(List,Obj = CppPyString(Top->FullTag(Root))); + PyList_Append(List,Obj = CppPyString(Top->FullTag(Root))); Py_DECREF(Obj); } - + return List; } @@ -195,7 +195,7 @@ static PyObject *CnfValueList(PyObject *Self,PyObject *Args) char *RootName = 0; if (PyArg_ParseTuple(Args,"|s",&RootName) == 0) return 0; - + // Convert the whole configuration space into a list PyObject *List = PyList_New(0); const Configuration::Item *Top = GetSelf(Self).Tree(RootName); @@ -207,7 +207,7 @@ static PyObject *CnfValueList(PyObject *Self,PyObject *Args) PyList_Append(List,Obj = CppPyString(Top->Value)); Py_DECREF(Obj); } - + return List; } @@ -216,7 +216,7 @@ static PyObject *CnfMyTag(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + const Configuration::Item *Top = GetSelf(Self).Tree(0); if (Top == 0) return Py_BuildValue("s",""); @@ -230,7 +230,7 @@ static PyObject *CnfKeys(PyObject *Self,PyObject *Args) char *RootName = 0; if (PyArg_ParseTuple(Args,"|s",&RootName) == 0) return 0; - + // Convert the whole configuration space into a list PyObject *List = PyList_New(0); const Configuration::Item *Top = GetSelf(Self).Tree(RootName); @@ -241,17 +241,17 @@ static PyObject *CnfKeys(PyObject *Self,PyObject *Args) if (Top != 0) Root = GetSelf(Self).Tree(0)->Parent; for (; Top != 0;) - { + { PyObject *Obj; PyList_Append(List,Obj = CppPyString(Top->FullTag(Root))); Py_DECREF(Obj); - + if (Top->Child != 0) { Top = Top->Child; continue; } - + while (Top != 0 && Top->Next == 0 && Top != Root && Top->Parent != Stop) Top = Top->Parent; @@ -270,13 +270,13 @@ static PyObject *CnfMap(PyObject *Self,PyObject *Arg) PyErr_SetNone(PyExc_TypeError); return 0; } - + if (GetSelf(Self).Exists(PyString_AsString(Arg)) == false) - { + { PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg)); return 0; } - + return CppPyString(GetSelf(Self).Find(PyString_AsString(Arg))); } @@ -288,7 +288,7 @@ static int CnfMapSet(PyObject *Self,PyObject *Arg,PyObject *Val) PyErr_SetNone(PyExc_TypeError); return -1; } - + GetSelf(Self).Set(PyString_AsString(Arg),PyString_AsString(Val)); return 0; } @@ -305,10 +305,10 @@ PyObject *LoadConfig(PyObject *Self,PyObject *Args) PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; } - + if (ReadConfigFile(GetSelf(Self),Name,false) == false) return HandleErrors(); - + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -323,10 +323,10 @@ PyObject *LoadConfigISC(PyObject *Self,PyObject *Args) PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; } - + if (ReadConfigFile(GetSelf(Self),Name,true) == false) return HandleErrors(); - + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -336,7 +336,7 @@ PyObject *LoadConfigISC(PyObject *Self,PyObject *Args) // --------------------------------------------------------------------- char *doc_ParseCommandLine = "ParseCommandLine(Configuration,ListOfOptions,List-argv) -> List\n" -"\n" +"\n" "This function is like getopt except it manipulates a configuration space.\n" "output is a list of non-option arguments (filenames, etc).\n" "ListOfOptions is a list of tuples of the form:\n" @@ -355,13 +355,13 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration."); return 0; } - + // Convert the option list int Length = PySequence_Length(POList); CommandLine::Args *OList = new CommandLine::Args[Length+1]; OList[Length].ShortOpt = 0; OList[Length].LongOpt = 0; - + for (int I = 0; I != Length; I++) { char *Type = 0; @@ -373,7 +373,7 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) return 0; } OList[I].Flags = 0; - + // Convert the type over to flags.. if (Type != 0) { @@ -389,7 +389,7 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) OList[I].Flags = CommandLine::ConfigFile; else if (strcasecmp(Type,"ArbItem") == 0) OList[I].Flags = CommandLine::ArbItem; - } + } } // Convert the argument list into a char ** @@ -399,7 +399,7 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) delete [] OList; return 0; } - + // Do the command line processing PyObject *List = 0; { @@ -410,16 +410,16 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) delete [] OList; return HandleErrors(); } - + // Convert the file listing into a python sequence for (Length = 0; CmdL.FileList[Length] != 0; Length++); - List = PyList_New(Length); + List = PyList_New(Length); for (int I = 0; CmdL.FileList[I] != 0; I++) { PyList_SetItem(List,I,PyString_FromString(CmdL.FileList[I])); - } + } } - + delete [] argv; delete [] OList; return HandleErrors(List); @@ -427,7 +427,7 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) /*}}}*/ // Method table for the Configuration object -static PyMethodDef CnfMethods[] = +static PyMethodDef CnfMethods[] = { // Query {"Find",CnfFind,METH_VARARGS,doc_Find}, @@ -444,7 +444,7 @@ static PyMethodDef CnfMethods[] = {"ValueList",CnfValueList,METH_VARARGS,doc_ValueList}, {"MyTag",CnfMyTag,METH_VARARGS,doc_MyTag}, {"Clear",CnfClear,METH_VARARGS,doc_Clear}, - + // Python Special {"keys",CnfKeys,METH_VARARGS,doc_Keys}, {"has_key",CnfExists,METH_VARARGS,doc_Exists}, @@ -462,7 +462,7 @@ static PyObject *CnfGetAttr(PyObject *Self,char *Name) // Type for a Normal Configuration object static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet}; -PyTypeObject ConfigurationType = +PyTypeObject ConfigurationType = { PyObject_HEAD_INIT(&PyType_Type) 0, // ob_size @@ -481,8 +481,8 @@ PyTypeObject ConfigurationType = &ConfigurationMap, // tp_as_mapping 0, // tp_hash }; - -PyTypeObject ConfigurationPtrType = + +PyTypeObject ConfigurationPtrType = { PyObject_HEAD_INIT(&PyType_Type) 0, // ob_size @@ -501,7 +501,7 @@ PyTypeObject ConfigurationPtrType = &ConfigurationMap, // tp_as_mapping 0, // tp_hash }; - + PyTypeObject ConfigurationSubType = { PyObject_HEAD_INIT(&PyType_Type) @@ -521,4 +521,4 @@ PyTypeObject ConfigurationSubType = &ConfigurationMap, // tp_as_mapping 0, // tp_hash }; - + diff --git a/python/depcache.cc b/python/depcache.cc index 2446dc71..0e83c956 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -39,7 +39,7 @@ static PyObject *PkgDepCacheInit(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *pyCallbackInst = 0; @@ -57,18 +57,18 @@ static PyObject *PkgDepCacheInit(PyObject *Self,PyObject *Args) pkgApplyStatus(*depcache); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) -{ +{ PyObject *result; pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *pyInstallProgressInst = 0; PyObject *pyFetchProgressInst = 0; - if (PyArg_ParseTuple(Args, "OO", + if (PyArg_ParseTuple(Args, "OO", &pyFetchProgressInst, &pyInstallProgressInst) == 0) { return 0; } @@ -78,7 +78,7 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) if (_error->PendingError() == true) return HandleErrors(); } - + pkgRecords Recs(*depcache); if (_error->PendingError() == true) HandleErrors(Py_None); @@ -108,22 +108,22 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) while (1) { bool Transient = false; - + if (Fetcher.Run() == pkgAcquire::Failed) return false; - + // Print out errors bool Failed = false; for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) { - - //std::cout << "looking at: " << (*I)->DestFile + + //std::cout << "looking at: " << (*I)->DestFile // << " status: " << (*I)->Status << std::endl; if ((*I)->Status == pkgAcquire::Item::StatDone && (*I)->Complete == true) continue; - + if ((*I)->Status == pkgAcquire::Item::StatIdle) { //std::cout << "transient failure" << std::endl; @@ -146,7 +146,7 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) Py_INCREF(Py_None); return HandleErrors(Py_None); } - + // Try to deal with missing package files if (Failed == true && PM->FixMissing() == false) { @@ -156,9 +156,9 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } - // fail if something else went wrong - //FIXME: make this more flexible, e.g. with a failedDl handler - if(Failed) + // fail if something else went wrong + //FIXME: make this more flexible, e.g. with a failedDl handler + if(Failed) return Py_BuildValue("b", false); _system->UnLock(true); @@ -174,25 +174,25 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) } //std::cout << "looping again, install unfinished" << std::endl; - + // Reload the fetcher object and loop again for media swapping Fetcher.Shutdown(); if (PM->GetArchives(&Fetcher,&List,&Recs) == false) { return Py_BuildValue("b", false); } _system->Lock(); - } - + } + return HandleErrors(Py_None); } static PyObject *PkgDepCacheSetCandidateVer(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; PyObject *VersionObj; if (PyArg_ParseTuple(Args,"O!O!", - &PackageType, &PackageObj, + &PackageType, &PackageObj, &VersionType, &VersionObj) == 0) return 0; @@ -202,12 +202,12 @@ static PyObject *PkgDepCacheSetCandidateVer(PyObject *Self,PyObject *Args) return HandleErrors(Py_BuildValue("b",false)); } depcache->SetCandidateVersion(I); - + return HandleErrors(Py_BuildValue("b",true)); } static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; PyObject *CandidateObj; @@ -228,7 +228,7 @@ static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args) } static PyObject *PkgDepCacheUpgrade(PyObject *Self,PyObject *Args) -{ +{ bool res; pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); @@ -244,11 +244,11 @@ static PyObject *PkgDepCacheUpgrade(PyObject *Self,PyObject *Args) Py_END_ALLOW_THREADS Py_INCREF(Py_None); - return HandleErrors(Py_BuildValue("b",res)); + return HandleErrors(Py_BuildValue("b",res)); } static PyObject *PkgDepCacheMinimizeUpgrade(PyObject *Self,PyObject *Args) -{ +{ bool res; pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); @@ -260,33 +260,33 @@ static PyObject *PkgDepCacheMinimizeUpgrade(PyObject *Self,PyObject *Args) Py_END_ALLOW_THREADS Py_INCREF(Py_None); - return HandleErrors(Py_BuildValue("b",res)); + return HandleErrors(Py_BuildValue("b",res)); } static PyObject *PkgDepCacheReadPinFile(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); - + char *file=NULL; if (PyArg_ParseTuple(Args,"|s",&file) == 0) return 0; - if(file == NULL) + if(file == NULL) ReadPinFile((pkgPolicy&)depcache->GetPolicy()); else ReadPinFile((pkgPolicy&)depcache->GetPolicy(), file); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheFixBroken(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); - + bool res=true; if (PyArg_ParseTuple(Args,"") == 0) return 0; @@ -294,12 +294,12 @@ static PyObject *PkgDepCacheFixBroken(PyObject *Self,PyObject *Args) res &=pkgFixBroken(*depcache); res &=pkgMinimizeUpgrade(*depcache); - return HandleErrors(Py_BuildValue("b",res)); + return HandleErrors(Py_BuildValue("b",res)); } static PyObject *PkgDepCacheMarkKeep(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self); PyObject *PackageObj; @@ -310,11 +310,11 @@ static PyObject *PkgDepCacheMarkKeep(PyObject *Self,PyObject *Args) depcache->MarkKeep(Pkg); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheSetReInstall(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self); PyObject *PackageObj; @@ -326,12 +326,12 @@ static PyObject *PkgDepCacheSetReInstall(PyObject *Self,PyObject *Args) depcache->SetReInstall(Pkg,value); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheMarkDelete(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -343,18 +343,18 @@ static PyObject *PkgDepCacheMarkDelete(PyObject *Self,PyObject *Args) depcache->MarkDelete(Pkg,purge); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; char autoInst=1; char fromUser=1; - if (PyArg_ParseTuple(Args,"O!|bb",&PackageType,&PackageObj, + if (PyArg_ParseTuple(Args,"O!|bb",&PackageType,&PackageObj, &autoInst, &fromUser) == 0) return 0; @@ -364,11 +364,11 @@ static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args) Py_END_ALLOW_THREADS Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -378,11 +378,11 @@ static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Upgradable())); + return HandleErrors(Py_BuildValue("b",state.Upgradable())); } static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -392,11 +392,11 @@ static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Garbage)); + return HandleErrors(Py_BuildValue("b",state.Garbage)); } static PyObject *PkgDepCacheIsAutoInstalled(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -406,11 +406,11 @@ static PyObject *PkgDepCacheIsAutoInstalled(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Flags & pkgCache::Flag::Auto)); + return HandleErrors(Py_BuildValue("b",state.Flags & pkgCache::Flag::Auto)); } static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -420,11 +420,11 @@ static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.NowBroken())); + return HandleErrors(Py_BuildValue("b",state.NowBroken())); } static PyObject *PkgDepCacheIsInstBroken(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -434,12 +434,12 @@ static PyObject *PkgDepCacheIsInstBroken(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.InstBroken())); + return HandleErrors(Py_BuildValue("b",state.InstBroken())); } static PyObject *PkgDepCacheMarkedInstall(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -449,12 +449,12 @@ static PyObject *PkgDepCacheMarkedInstall(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.NewInstall())); + return HandleErrors(Py_BuildValue("b",state.NewInstall())); } static PyObject *PkgDepCacheMarkedUpgrade(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -464,11 +464,11 @@ static PyObject *PkgDepCacheMarkedUpgrade(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Upgrade())); + return HandleErrors(Py_BuildValue("b",state.Upgrade())); } static PyObject *PkgDepCacheMarkedDelete(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -478,11 +478,11 @@ static PyObject *PkgDepCacheMarkedDelete(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Delete())); + return HandleErrors(Py_BuildValue("b",state.Delete())); } static PyObject *PkgDepCacheMarkedKeep(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -492,11 +492,11 @@ static PyObject *PkgDepCacheMarkedKeep(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Keep())); + return HandleErrors(Py_BuildValue("b",state.Keep())); } static PyObject *PkgDepCacheMarkedDowngrade(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -506,11 +506,11 @@ static PyObject *PkgDepCacheMarkedDowngrade(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgDepCache::StateCache &state = (*depcache)[Pkg]; - return HandleErrors(Py_BuildValue("b",state.Downgrade())); + return HandleErrors(Py_BuildValue("b",state.Downgrade())); } static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; @@ -522,11 +522,11 @@ static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args) bool res = state.Install() && (state.iFlags & pkgDepCache::ReInstall); - return HandleErrors(Py_BuildValue("b",res)); + return HandleErrors(Py_BuildValue("b",res)); } -static PyMethodDef PkgDepCacheMethods[] = +static PyMethodDef PkgDepCacheMethods[] = { {"Init",PkgDepCacheInit,METH_VARARGS,"Init the depcache (done on construct automatically)"}, {"GetCandidateVer",PkgDepCacheGetCandidateVer,METH_VARARGS,"Get candidate version"}, @@ -566,20 +566,20 @@ static PyObject *DepCacheAttr(PyObject *Self,char *Name) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); // size querries - if(strcmp("KeepCount",Name) == 0) + if(strcmp("KeepCount",Name) == 0) return Py_BuildValue("l", depcache->KeepCount()); - else if(strcmp("InstCount",Name) == 0) + else if(strcmp("InstCount",Name) == 0) return Py_BuildValue("l", depcache->InstCount()); - else if(strcmp("DelCount",Name) == 0) + else if(strcmp("DelCount",Name) == 0) return Py_BuildValue("l", depcache->DelCount()); - else if(strcmp("BrokenCount",Name) == 0) + else if(strcmp("BrokenCount",Name) == 0) return Py_BuildValue("l", depcache->BrokenCount()); - else if(strcmp("UsrSize",Name) == 0) + else if(strcmp("UsrSize",Name) == 0) return Py_BuildValue("d", depcache->UsrSize()); - else if(strcmp("DebSize",Name) == 0) + else if(strcmp("DebSize",Name) == 0) return Py_BuildValue("d", depcache->DebSize()); - - + + return Py_FindMethod(PkgDepCacheMethods,Self,Name); } @@ -660,7 +660,7 @@ PyObject *GetPkgProblemResolver(PyObject *Self,PyObject *Args) static PyObject *PkgProblemResolverResolve(PyObject *Self,PyObject *Args) -{ +{ bool res; pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); @@ -676,7 +676,7 @@ static PyObject *PkgProblemResolverResolve(PyObject *Self,PyObject *Args) } static PyObject *PkgProblemResolverResolveByKeep(PyObject *Self,PyObject *Args) -{ +{ bool res; pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); if (PyArg_ParseTuple(Args,"") == 0) @@ -690,7 +690,7 @@ static PyObject *PkgProblemResolverResolveByKeep(PyObject *Self,PyObject *Args) } static PyObject *PkgProblemResolverProtect(PyObject *Self,PyObject *Args) -{ +{ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); PyObject *PackageObj; if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) @@ -710,11 +710,11 @@ static PyObject *PkgProblemResolverRemove(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); fixer->Remove(Pkg); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } static PyObject *PkgProblemResolverClear(PyObject *Self,PyObject *Args) -{ +{ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); PyObject *PackageObj; if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) @@ -722,11 +722,11 @@ static PyObject *PkgProblemResolverClear(PyObject *Self,PyObject *Args) pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); fixer->Clear(Pkg); Py_INCREF(Py_None); - return HandleErrors(Py_None); -} + return HandleErrors(Py_None); +} static PyObject *PkgProblemResolverInstallProtect(PyObject *Self,PyObject *Args) -{ +{ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); if (PyArg_ParseTuple(Args,"") == 0) return 0; @@ -735,7 +735,7 @@ static PyObject *PkgProblemResolverInstallProtect(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } -static PyMethodDef PkgProblemResolverMethods[] = +static PyMethodDef PkgProblemResolverMethods[] = { // config {"Protect", PkgProblemResolverProtect, METH_VARARGS, "Protect(PkgIterator)"}, @@ -753,7 +753,7 @@ static PyMethodDef PkgProblemResolverMethods[] = static PyObject *ProblemResolverAttr(PyObject *Self,char *Name) { pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); - + return Py_FindMethod(PkgProblemResolverMethods,Self,Name); } @@ -785,7 +785,7 @@ PyTypeObject PkgProblemResolverType = static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args) -{ +{ pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self); if (PyArg_ParseTuple(Args,"") == 0) return 0; @@ -794,7 +794,7 @@ static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } -static PyMethodDef PkgActionGroupMethods[] = +static PyMethodDef PkgActionGroupMethods[] = { {"release", PkgActionGroupRelease, METH_VARARGS, "release()"}, {} @@ -804,7 +804,7 @@ static PyMethodDef PkgActionGroupMethods[] = static PyObject *ActionGroupAttr(PyObject *Self,char *Name) { pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self); - + return Py_FindMethod(PkgActionGroupMethods,Self,Name); } diff --git a/python/generic.cc b/python/generic.cc index 044569b9..7309d978 100644 --- a/python/generic.cc +++ b/python/generic.cc @@ -4,7 +4,7 @@ /* ###################################################################### generic - Some handy functions to make integration a tad simpler - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -24,10 +24,10 @@ PyObject *HandleErrors(PyObject *Res) _error->Discard(); return Res; } - + if (Res != 0) Py_DECREF(Res); - + string Err; int errcnt = 0; while (_error->empty() == false) @@ -55,7 +55,7 @@ const char **ListToCharChar(PyObject *List,bool NullTerm) int Length = PySequence_Length(List); const char **Res = new const char *[Length + (NullTerm == true?1:0)]; for (int I = 0; I != Length; I++) - { + { PyObject *Itm = PySequence_GetItem(List,I); if (PyString_Check(Itm) == 0) { @@ -80,12 +80,12 @@ PyObject *CharCharToList(const char **List,unsigned long Size) for (const char **I = List; *I != 0; I++) Size++; } - + // Convert the whole configuration space into a list PyObject *PList = PyList_New(Size); for (unsigned long I = 0; I != Size; I++, List++) PyList_SetItem(PList,I,PyString_FromString(*List)); - + return PList; } /*}}}*/ diff --git a/python/generic.h b/python/generic.h index a1b662bb..ce79a54c 100644 --- a/python/generic.h +++ b/python/generic.h @@ -4,24 +4,24 @@ /* ###################################################################### generic - Some handy functions to make integration a tad simpler - - Python needs this little _HEAD tacked onto the front of the object.. + + Python needs this little _HEAD tacked onto the front of the object.. This complicates the integration with C++. We use some templates to make that quite transparent to us. It would have been nice if Python internally used a page from the C++ ref counting book to hide its little header from the world, but it doesn't. - The CppPyObject has the target object and the Python header, this is - needed to ensure proper alignment. + The CppPyObject has the target object and the Python header, this is + needed to ensure proper alignment. GetCpp returns the C++ object from a PyObject. CppPyObject_NEW creates the Python object and then uses placement new to init the C++ class.. This is good for simple situations and as an example on how to do it in other more specific cases. - CppPyObject_Dealloc should be used in the Type as the destructor + CppPyObject_Dealloc should be used in the Type as the destructor function. HandleErrors converts errors from the internal _error stack into Python exceptions and makes sure the _error stack is empty. - + ##################################################################### */ /*}}}*/ #ifndef GENERIC_H @@ -38,7 +38,7 @@ typedef int Py_ssize_t; template <class T> struct CppPyObject : public PyObject { // We are only using CppPyObject and friends as dumb structs only, ie the - // c'tor is never called. + // c'tor is never called. // However if T doesn't have a default c'tor C++ doesn't generate one for // CppPyObject (since it can't know how it should initialize Object). // diff --git a/python/indexfile.cc b/python/indexfile.cc index 4e32f2ab..107eae27 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -16,7 +16,7 @@ #include <Python.h> static PyObject *PackageIndexFileArchiveURI(PyObject *Self,PyObject *Args) -{ +{ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self); char *path; @@ -26,7 +26,7 @@ static PyObject *PackageIndexFileArchiveURI(PyObject *Self,PyObject *Args) return HandleErrors(Safe_FromString(File->ArchiveURI(path).c_str())); } -static PyMethodDef PackageIndexFileMethods[] = +static PyMethodDef PackageIndexFileMethods[] = { {"ArchiveURI",PackageIndexFileArchiveURI,METH_VARARGS,"Returns the ArchiveURI"}, {} @@ -48,20 +48,20 @@ static PyObject *PackageIndexFileAttr(PyObject *Self,char *Name) return Py_BuildValue("i",(File->Size())); else if (strcmp("IsTrusted",Name) == 0) return Py_BuildValue("i",(File->IsTrusted())); - + return Py_FindMethod(PackageIndexFileMethods,Self,Name); } static PyObject *PackageIndexFileRepr(PyObject *Self) { pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self); - + char S[1024]; snprintf(S,sizeof(S),"<pkIndexFile object: " "Label:'%s' Describe='%s' Exists='%i' " "HasPackages='%i' Size='%i' " "IsTrusted='%i' ArchiveURI='%s'>", - File->GetType()->Label, File->Describe().c_str(), File->Exists(), + File->GetType()->Label, File->Describe().c_str(), File->Exists(), File->HasPackages(), File->Size(), File->IsTrusted(), File->ArchiveURI("").c_str()); return PyString_FromString(S); @@ -86,7 +86,7 @@ PyTypeObject PackageIndexFileType = 0, // tp_as_mapping 0, // tp_hash }; - + diff --git a/python/makefile b/python/makefile index e0c62541..3e6458f4 100644 --- a/python/makefile +++ b/python/makefile @@ -7,20 +7,20 @@ include ../buildlib/defaults.mak # The apt_pkg module MODULE=apt_pkg -SLIBS = -lapt-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 -SOURCE := $(APT_PKG_SRC) +SOURCE := $(APT_PKG_SRC) include $(PYTHON_H) progress.h -# The apt_int module.. +# 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) +SOURCE := $(APT_INST_SRC) include $(PYTHON_H) diff --git a/python/metaindex.cc b/python/metaindex.cc index 45c8ef2a..efbc38af 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -29,13 +29,13 @@ static PyObject *MetaIndexAttr(PyObject *Self,char *Name) { PyObject *List = PyList_New(0); vector<pkgIndexFile *> *indexFiles = meta->GetIndexFiles(); - for (vector<pkgIndexFile *>::const_iterator I = indexFiles->begin(); + for (vector<pkgIndexFile *>::const_iterator I = indexFiles->begin(); I != indexFiles->end(); I++) { PyObject *Obj; Obj = CppPyObject_NEW<pkgIndexFile*>(&PackageIndexFileType,*I); PyList_Append(List,Obj); - } + } return List; } @@ -46,7 +46,7 @@ static PyObject *MetaIndexAttr(PyObject *Self,char *Name) static PyObject *MetaIndexRepr(PyObject *Self) { metaIndex *meta = GetCpp<metaIndex*>(Self); - + char S[1024]; snprintf(S,sizeof(S),"<metaIndex object: " "Type='%s', URI:'%s' Dist='%s' IsTrusted='%i'>", @@ -75,7 +75,7 @@ PyTypeObject MetaIndexType = 0, // tp_as_mapping 0, // tp_hash }; - + diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index 9670f238..0eaa28cd 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -19,14 +19,14 @@ static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args) -{ +{ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self); PyObject *fetcher, *list, *recs; - + if (PyArg_ParseTuple(Args, "O!O!O!", &PkgAcquireType,&fetcher, &PkgSourceListType, &list, - &PkgRecordsType, &recs) == 0) + &PkgRecordsType, &recs) == 0) return 0; pkgAcquire *s_fetcher = GetCpp<pkgAcquire*>(fetcher); @@ -44,12 +44,12 @@ static PyObject *PkgManagerDoInstall(PyObject *Self,PyObject *Args) //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self); pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self); int status_fd = -1; - + if (PyArg_ParseTuple(Args, "|i", &status_fd) == 0) return 0; pkgPackageManager::OrderResult res = pm->DoInstall(status_fd); - + return HandleErrors(Py_BuildValue("i",res)); } @@ -62,11 +62,11 @@ static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args) return 0; bool res = pm->FixMissing(); - + return HandleErrors(Py_BuildValue("b",res)); } -static PyMethodDef PkgManagerMethods[] = +static PyMethodDef PkgManagerMethods[] = { {"GetArchives",PkgManagerGetArchives,METH_VARARGS,"Load the selected archives into the fetcher"}, {"DoInstall",PkgManagerDoInstall,METH_VARARGS,"Do the actual install"}, @@ -81,11 +81,11 @@ static PyObject *PkgManagerAttr(PyObject *Self,char *Name) pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self); // some constants - if(strcmp("ResultCompleted",Name) == 0) + if(strcmp("ResultCompleted",Name) == 0) return Py_BuildValue("i", pkgPackageManager::Completed); - if(strcmp("ResultFailed",Name) == 0) + if(strcmp("ResultFailed",Name) == 0) return Py_BuildValue("i", pkgPackageManager::Failed); - if(strcmp("ResultIncomplete",Name) == 0) + if(strcmp("ResultIncomplete",Name) == 0) return Py_BuildValue("i", pkgPackageManager::Incomplete); return Py_FindMethod(PkgManagerMethods,Self,Name); @@ -125,7 +125,7 @@ PyObject *GetPkgManager(PyObject *Self,PyObject *Args) CppPyObject<pkgPackageManager*> *PkgManagerObj = CppPyObject_NEW<pkgPackageManager*>(&PkgManagerType,pm); - + return PkgManagerObj; } diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 93bc54d9..5359ee6f 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -16,20 +16,20 @@ #include <Python.h> /*}}}*/ - + // PkgRecords Class /*{{{*/ // --------------------------------------------------------------------- static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args) -{ +{ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self); - + PyObject *PkgFObj; long int Index; if (PyArg_ParseTuple(Args,"(O!l)",&PackageFileType,&PkgFObj,&Index) == 0) return 0; - + // Get the index and check to make sure it is reasonable pkgCache::PkgFileIterator &PkgF = GetCpp<pkgCache::PkgFileIterator>(PkgFObj); pkgCache *Cache = PkgF.Cache(); @@ -39,15 +39,15 @@ static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args) PyErr_SetNone(PyExc_IndexError); return 0; } - + // Do the lookup Struct.Last = &Struct.Records.Lookup(pkgCache::VerFileIterator(*Cache,Cache->VerFileP+Index)); // always return true (to make it consistent with the pkgsrcrecords object return Py_BuildValue("i", 1); } - -static PyMethodDef PkgRecordsMethods[] = + +static PyMethodDef PkgRecordsMethods[] = { {"Lookup",PkgRecordsLookup,METH_VARARGS,"Changes to a new package"}, {} @@ -65,6 +65,8 @@ static PyObject *PkgRecordsAttr(PyObject *Self,char *Name) return CppPyString(Struct.Last->MD5Hash()); else if (strcmp("SHA1Hash",Name) == 0) return CppPyString(Struct.Last->SHA1Hash()); + else if (strcmp("SHA256Hash",Name) == 0) + return CppPyString(Struct.Last->SHA256Hash()); else if (strcmp("SourcePkg",Name) == 0) return CppPyString(Struct.Last->SourcePkg()); else if (strcmp("SourceVer",Name) == 0) @@ -79,14 +81,14 @@ static PyObject *PkgRecordsAttr(PyObject *Self,char *Name) return CppPyString(Struct.Last->Name()); else if (strcmp("Homepage",Name) == 0) return CppPyString(Struct.Last->Homepage()); - else if (strcmp("Record", Name) == 0) + else if (strcmp("Record", Name) == 0) { const char *start, *stop; Struct.Last->GetRec(start, stop); return PyString_FromStringAndSize(start,stop-start); } } - + return Py_FindMethod(PkgRecordsMethods,Self,Name); } PyTypeObject PkgRecordsType = diff --git a/python/pkgrecords.h b/python/pkgrecords.h index 78787eab..1e26c8cf 100644 --- a/python/pkgrecords.h +++ b/python/pkgrecords.h @@ -4,7 +4,7 @@ struct PkgRecordsStruct { pkgRecords Records; pkgRecords::Parser *Last; - + PkgRecordsStruct(pkgCache *Cache) : Records(*Cache), Last(0) {}; PkgRecordsStruct() : Records(*(pkgCache *)0) {abort();}; // G++ Bug.. }; diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index c698a925..f7f5d7a2 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -21,7 +21,7 @@ struct PkgSrcRecordsStruct pkgSourceList List; pkgSrcRecords *Records; pkgSrcRecords::Parser *Last; - + PkgSrcRecordsStruct() : Last(0) { List.ReadMainList(); Records = new pkgSrcRecords(List); @@ -30,24 +30,24 @@ struct PkgSrcRecordsStruct delete Records; }; }; - + // PkgSrcRecords Class /*{{{*/ // --------------------------------------------------------------------- static char *doc_PkgSrcRecordsLookup = "xxx"; static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args) -{ +{ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self); - + char *Name = 0; if (PyArg_ParseTuple(Args,"s",&Name) == 0) return 0; - + Struct.Last = Struct.Records->Find(Name, false); if (Struct.Last == 0) { Struct.Records->Restart(); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } return Py_BuildValue("i", 1); @@ -55,20 +55,20 @@ static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args) static char *doc_PkgSrcRecordsRestart = "Start Lookup from the begining"; static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args) -{ +{ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self); - + char *Name = 0; if (PyArg_ParseTuple(Args,"") == 0) return 0; - + Struct.Records->Restart(); Py_INCREF(Py_None); - return HandleErrors(Py_None); + return HandleErrors(Py_None); } -static PyMethodDef PkgSrcRecordsMethods[] = +static PyMethodDef PkgSrcRecordsMethods[] = { {"Lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup}, {"Restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart}, @@ -111,10 +111,10 @@ static PyObject *PkgSrcRecordsAttr(PyObject *Self,char *Name) PyObject *v; for(unsigned int i=0;i<f.size();i++) { - v = Py_BuildValue("(siss)", - f[i].MD5Hash.c_str(), - f[i].Size, - f[i].Path.c_str(), + v = Py_BuildValue("(siss)", + f[i].MD5Hash.c_str(), + f[i].Size, + f[i].Path.c_str(), f[i].Type.c_str()); PyList_Append(List, v); Py_DECREF(v); @@ -129,7 +129,7 @@ static PyObject *PkgSrcRecordsAttr(PyObject *Self,char *Name) PyObject *v; for(unsigned int i=0;i<bd.size();i++) { - v = Py_BuildValue("(ssii)", bd[i].Package.c_str(), + v = Py_BuildValue("(ssii)", bd[i].Package.c_str(), bd[i].Version.c_str(), bd[i].Op, bd[i].Type); PyList_Append(List, v); Py_DECREF(v); @@ -137,7 +137,7 @@ static PyObject *PkgSrcRecordsAttr(PyObject *Self,char *Name) return List; } } - + return Py_FindMethod(PkgSrcRecordsMethods,Self,Name); } PyTypeObject PkgSrcRecordsType = @@ -174,7 +174,7 @@ PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args) #endif if (PyArg_ParseTuple(Args,"") == 0) return 0; - + return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(&PkgSrcRecordsType)); } diff --git a/python/progress.cc b/python/progress.cc index 99ad0a25..c5a1c138 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -14,7 +14,7 @@ // generic -bool PyCallbackObj::RunSimpleCallback(const char* method_name, +bool PyCallbackObj::RunSimpleCallback(const char* method_name, PyObject *arglist, PyObject **res) { @@ -50,8 +50,8 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name, } -// OpProgress interface -void PyOpProgress::Update() +// OpProgress interface +void PyOpProgress::Update() { PyObject *o; o = Py_BuildValue("s", Op.c_str()); @@ -64,7 +64,7 @@ void PyOpProgress::Update() PyObject_SetAttrString(callbackInst, "majorChange", o); Py_XDECREF(o); - // Build up the argument list... + // Build up the argument list... if(CheckChange(0.05)) { PyObject *arglist = Py_BuildValue("(f)", Percent); @@ -128,7 +128,7 @@ void PyFetchProgress::Fail(pkgAcquire::ItemDesc &Itm) // Ignore certain kinds of transient failures (bad code) if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) return; - + if (Itm.Owner->Status == pkgAcquire::Item::StatDone) { UpdateStatus(Itm, DLIgnored); @@ -159,7 +159,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) //std::cout << "Pulse" << std::endl; if(callbackInst == 0) return false; - + // set stats PyObject *o; o = Py_BuildValue("f", CurrentCPS); @@ -179,11 +179,11 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) Py_XDECREF(o); PyObject *arglist = Py_BuildValue("()"); - PyObject *result; + PyObject *result; RunSimpleCallback("pulse", arglist, &result); bool res = true; - if(!PyArg_Parse(result, "b", &res)) + if(!PyArg_Parse(result, "b", &res)) { // most of the time the user who subclasses the pulse() // method forgot to add a return {True,False} so we just @@ -199,22 +199,22 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) // install progress -void PyInstallProgress::StartUpdate() +void PyInstallProgress::StartUpdate() { RunSimpleCallback("startUpdate"); } -void PyInstallProgress::UpdateInterface() +void PyInstallProgress::UpdateInterface() { RunSimpleCallback("updateInterface"); } - -void PyInstallProgress::FinishUpdate() + +void PyInstallProgress::FinishUpdate() { RunSimpleCallback("finishUpdate"); } -pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) +pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) { void *dummy; pkgPackageManager::OrderResult res; @@ -233,7 +233,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) std::cerr << "custom fork found" << std::endl; PyObject *arglist = Py_BuildValue("()"); PyObject *result = PyEval_CallObject(method, arglist); - Py_DECREF(arglist); + Py_DECREF(arglist); if (result == NULL) { std::cerr << "fork method invalid" << std::endl; PyErr_Print(); @@ -248,7 +248,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) //std::cerr << "using build-in fork()" << std::endl; child_id = fork(); } - + #if 0 // FIXME: this needs to be merged into apt to support medium swaping if (child_id == 0) { @@ -277,7 +277,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) //std::cerr << "custom waitChild found" << std::endl; PyObject *arglist = Py_BuildValue("(i)",child_id); PyObject *result = PyEval_CallObject(method, arglist); - Py_DECREF(arglist); + Py_DECREF(arglist); if (result == NULL) { std::cerr << "waitChild method invalid" << std::endl; PyErr_Print(); @@ -291,7 +291,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) //std::cerr << "got child_res: " << res << std::endl; } else { //std::cerr << "using build-in waitpid()" << std::endl; - + while (waitpid(child_id, &ret, WNOHANG) == 0) UpdateInterface(); diff --git a/python/progress.h b/python/progress.h index f04bd683..5ac67b1c 100644 --- a/python/progress.h +++ b/python/progress.h @@ -53,7 +53,7 @@ struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj virtual bool MediaChange(string Media, string Drive); - /* apt stuff */ + /* apt stuff */ virtual void IMSHit(pkgAcquire::ItemDesc &Itm); virtual void Fetch(pkgAcquire::ItemDesc &Itm); virtual void Done(pkgAcquire::ItemDesc &Itm); diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 76df015d..5dcaf86b 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -17,18 +17,18 @@ /*}}}*/ - + // PkgsourceList Class /*{{{*/ // --------------------------------------------------------------------- static char *doc_PkgSourceListFindIndex = "xxx"; static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args) -{ +{ pkgSourceList *list = GetCpp<pkgSourceList*>(Self); PyObject *pyPkgFileIter; PyObject *pyPkgIndexFile; - if (PyArg_ParseTuple(Args, "O!", &PackageFileType,&pyPkgFileIter) == 0) + if (PyArg_ParseTuple(Args, "O!", &PackageFileType,&pyPkgFileIter) == 0) return 0; pkgCache::PkgFileIterator &i = GetCpp<pkgCache::PkgFileIterator>(pyPkgFileIter); @@ -40,7 +40,7 @@ static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args) } //&PackageIndexFileType,&pyPkgIndexFile) - + Py_INCREF(Py_None); return Py_None; } @@ -61,7 +61,7 @@ static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args) PyObject *pyFetcher; char all = 0; - if (PyArg_ParseTuple(Args, "O!|b",&PkgAcquireType,&pyFetcher, &all) == 0) + if (PyArg_ParseTuple(Args, "O!|b",&PkgAcquireType,&pyFetcher, &all) == 0) return 0; pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyFetcher); @@ -70,7 +70,7 @@ static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args) return HandleErrors(Py_BuildValue("b",res)); } -static PyMethodDef PkgSourceListMethods[] = +static PyMethodDef PkgSourceListMethods[] = { {"FindIndex",PkgSourceListFindIndex,METH_VARARGS,doc_PkgSourceListFindIndex}, {"ReadMainList",PkgSourceListReadMainList,METH_VARARGS,doc_PkgSourceListReadMainList}, @@ -85,13 +85,13 @@ static PyObject *PkgSourceListAttr(PyObject *Self,char *Name) if (strcmp("List",Name) == 0) { PyObject *List = PyList_New(0); - for (vector<metaIndex *>::const_iterator I = list->begin(); + for (vector<metaIndex *>::const_iterator I = list->begin(); I != list->end(); I++) { PyObject *Obj; Obj = CppPyObject_NEW<metaIndex*>(&MetaIndexType,*I); PyList_Append(List,Obj); - } + } return List; } return Py_FindMethod(PkgSourceListMethods,Self,Name); diff --git a/python/string.cc b/python/string.cc index 1fa5a901..8168ea5b 100644 --- a/python/string.cc +++ b/python/string.cc @@ -3,22 +3,22 @@ // $Id: string.cc,v 1.3 2002/01/08 06:53:04 jgg Exp $ /* ###################################################################### - string - Mappings for the string functions that are worthwile for + string - Mappings for the string functions that are worthwile for Python users - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ #include "apt_pkgmodule.h" #include "generic.h" - + #include <apt-pkg/strutl.h> #include <Python.h> /*}}}*/ - + // Templated function /*{{{*/ -/* Macro for the generic string in string out function */ +/* Macro for the generic string in string out function */ #define MkStr(Python,CFunc) \ PyObject *Python(PyObject *Self,PyObject *Args) \ { \ @@ -36,7 +36,7 @@ PyObject *Python(PyObject *Self,PyObject *Args) \ return 0; \ return CppPyString(CFunc(Val)); \ } - + MkStr(StrDeQuote,DeQuoteString); MkStr(StrBase64Encode,Base64Encode); MkStr(StrURItoFileName,URItoFileName); @@ -58,7 +58,7 @@ PyObject *StrSizeToStr(PyObject *Self,PyObject *Args) return CppPyString(SizeToStr(PyLong_AsDouble(Obj))); if (PyFloat_Check(Obj)) return CppPyString(SizeToStr(PyFloat_AsDouble(Obj))); - + PyErr_SetString(PyExc_TypeError,"Only understand integers and floats"); return 0; } @@ -69,14 +69,14 @@ PyObject *StrQuoteString(PyObject *Self,PyObject *Args) char *Bad = 0; if (PyArg_ParseTuple(Args,"ss",&Str,&Bad) == 0) return 0; - return CppPyString(QuoteString(Str,Bad)); + return CppPyString(QuoteString(Str,Bad)); } PyObject *StrStringToBool(PyObject *Self,PyObject *Args) { char *Str = 0; if (PyArg_ParseTuple(Args,"s",&Str) == 0) - return 0; + return 0; return Py_BuildValue("i",StringToBool(Str)); } @@ -85,14 +85,14 @@ PyObject *StrStrToTime(PyObject *Self,PyObject *Args) char *Str = 0; if (PyArg_ParseTuple(Args,"s",&Str) == 0) return 0; - + time_t Result; if (StrToTime(Str,Result) == false) { Py_INCREF(Py_None); return Py_None; } - + return Py_BuildValue("i",Result); } diff --git a/python/tag.cc b/python/tag.cc index 4b378a55..217be290 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -4,18 +4,18 @@ /* ###################################################################### Tag - Binding for the RFC 822 tag file parser - + Upon reflection I have make the TagSection wrapper look like a map.. The other option was to use a sequence (which nicely matches the internal - storage) but really makes no sense to a Python Programmer.. One - specialized lookup is provided, the FindFlag lookup - as well as the + storage) but really makes no sense to a Python Programmer.. One + specialized lookup is provided, the FindFlag lookup - as well as the usual set of duplicate things to match the C++ interface. - - The TagFile interface is also slightly different, it has a built in + + The TagFile interface is also slightly different, it has a built in internal TagSection object that is used. Do not hold onto a reference to a TagSection and let TagFile go out of scope! The underlying storage for the section will go away and it will seg. - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -80,7 +80,7 @@ static PyObject *TagSecFind(PyObject *Self,PyObject *Args) char *Default = 0; if (PyArg_ParseTuple(Args,"s|z",&Name,&Default) == 0) return 0; - + const char *Start; const char *Stop; if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false) @@ -98,7 +98,7 @@ static PyObject *TagSecFindFlag(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"s",&Name) == 0) return 0; - + unsigned long Flag = 0; if (GetCpp<pkgTagSection>(Self).FindFlag(Name,Flag,1) == false) { @@ -116,15 +116,15 @@ static PyObject *TagSecMap(PyObject *Self,PyObject *Arg) PyErr_SetNone(PyExc_TypeError); return 0; } - + const char *Start; const char *Stop; if (GetCpp<pkgTagSection>(Self).Find(PyString_AsString(Arg),Start,Stop) == false) - { + { PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg)); return 0; } - + return PyString_FromStringAndSize(Start,Stop-Start); } @@ -142,17 +142,17 @@ static PyObject *TagSecKeys(PyObject *Self,PyObject *Args) pkgTagSection &Tags = GetCpp<pkgTagSection>(Self); if (PyArg_ParseTuple(Args,"") == 0) return 0; - + // Convert the whole configuration space into a list PyObject *List = PyList_New(0); for (unsigned int I = 0; I != Tags.Count(); I++) - { + { const char *Start; const char *Stop; Tags.Get(Start,Stop,I); const char *End = Start; for (; End < Stop && *End != ':'; End++); - + PyObject *Obj; PyList_Append(List,Obj = PyString_FromStringAndSize(Start,End-Start)); Py_DECREF(Obj); @@ -166,7 +166,7 @@ static PyObject *TagSecExists(PyObject *Self,PyObject *Args) char *Name = 0; if (PyArg_ParseTuple(Args,"s",&Name) == 0) return 0; - + const char *Start; const char *Stop; if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false) @@ -179,7 +179,7 @@ static PyObject *TagSecBytes(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + return Py_BuildValue("i",GetCpp<pkgTagSection>(Self).size()); } @@ -197,11 +197,11 @@ static PyObject *TagFileStep(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - + TagFileData &Obj = *(TagFileData *)Self; if (Obj.Object.Step(Obj.Section->Object) == false) return HandleErrors(Py_BuildValue("i",0)); - + return HandleErrors(Py_BuildValue("i",1)); } @@ -219,11 +219,11 @@ static PyObject *TagFileJump(PyObject *Self,PyObject *Args) int Offset; if (PyArg_ParseTuple(Args,"i",&Offset) == 0) return 0; - + TagFileData &Obj = *(TagFileData *)Self; if (Obj.Object.Jump(Obj.Section->Object,Offset) == false) return HandleErrors(Py_BuildValue("i",0)); - + return HandleErrors(Py_BuildValue("i",1)); } /*}}}*/ @@ -235,23 +235,23 @@ PyObject *ParseSection(PyObject *self,PyObject *Args) char *Data; if (PyArg_ParseTuple(Args,"s",&Data) == 0) return 0; - + // Create the object.. TagSecData *New = PyObject_NEW(TagSecData,&TagSecType); new (&New->Object) pkgTagSection(); New->Data = new char[strlen(Data)+2]; snprintf(New->Data,strlen(Data)+2,"%s\n",Data); - + if (New->Object.Scan(New->Data,strlen(New->Data)) == false) { cerr << New->Data << endl; Py_DECREF((PyObject *)New); PyErr_SetString(PyExc_ValueError,"Unable to parse section data"); return 0; - } - + } + New->Object.Trim(); - + return New; } /*}}}*/ @@ -264,26 +264,26 @@ PyObject *ParseTagFile(PyObject *self,PyObject *Args) PyObject *File; if (PyArg_ParseTuple(Args,"O!",&PyFile_Type,&File) == 0) return 0; - + TagFileData *New = PyObject_NEW(TagFileData,&TagFileType); new (&New->Fd) FileFd(fileno(PyFile_AsFile(File)),false); New->File = File; Py_INCREF(New->File); new (&New->Object) pkgTagFile(&New->Fd); - + // Create the section New->Section = PyObject_NEW(TagSecData,&TagSecType); new (&New->Section->Object) pkgTagSection(); New->Section->Data = 0; - + return HandleErrors(New); } - /*}}}*/ + /*}}}*/ // RewriteSection - Rewrite a section.. /*{{{*/ // --------------------------------------------------------------------- -/* An interesting future extension would be to add a user settable +/* An interesting future extension would be to add a user settable order list */ -char *doc_RewriteSection = +char *doc_RewriteSection = "RewriteSection(Section,Order,RewriteList) -> String\n" "\n" "The section rewriter allows a section to be taken in, have fields added,\n" @@ -306,10 +306,10 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) if (PyArg_ParseTuple(Args,"O!O!O!",&TagSecType,&Section, &PyList_Type,&Order,&PyList_Type,&Rewrite) == 0) return 0; - + // Convert the order list const char **OrderList = ListToCharChar(Order,true); - + // Convert the Rewrite list. TFRewriteData *List = new TFRewriteData[PySequence_Length(Rewrite)+1]; memset(List,0,sizeof(*List)*(PySequence_Length(Rewrite)+1)); @@ -324,7 +324,7 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) return 0; } } - + /* This is a glibc extension.. If not running on glibc I'd just take this whole function out, it is probably infrequently used */ char *bp = 0; @@ -336,13 +336,13 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) delete [] OrderList; delete [] List; fclose(F); - + if (Res == false) { free(bp); return HandleErrors(); } - + // Return the string PyObject *ResObj = PyString_FromStringAndSize(bp,size); free(bp); @@ -351,13 +351,13 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) /*}}}*/ // Method table for the Tag Section object -static PyMethodDef TagSecMethods[] = +static PyMethodDef TagSecMethods[] = { // Query {"Find",TagSecFind,METH_VARARGS,doc_Find}, {"FindFlag",TagSecFindFlag,METH_VARARGS,doc_FindFlag}, {"Bytes",TagSecBytes,METH_VARARGS,doc_Bytes}, - + // Python Special {"keys",TagSecKeys,METH_VARARGS,doc_Keys}, {"has_key",TagSecExists,METH_VARARGS,doc_Exists}, @@ -398,13 +398,13 @@ PyTypeObject TagSecType = }; // Method table for the Tag File object -static PyMethodDef TagFileMethods[] = +static PyMethodDef TagFileMethods[] = { // Query {"Step",TagFileStep,METH_VARARGS,doc_Step}, {"Offset",TagFileOffset,METH_VARARGS,doc_Offset}, {"Jump",TagFileJump,METH_VARARGS,doc_Jump}, - + {} }; @@ -418,8 +418,8 @@ static PyObject *TagFileGetAttr(PyObject *Self,char *Name) PyObject *Obj = ((TagFileData *)Self)->Section; Py_INCREF(Obj); return Obj; - } - + } + return Py_FindMethod(TagFileMethods,Self,Name); } diff --git a/python/tar.cc b/python/tar.cc index 61c9d708..e5aaee6f 100644 --- a/python/tar.cc +++ b/python/tar.cc @@ -4,7 +4,7 @@ /* ###################################################################### Tar Inteface - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -23,9 +23,9 @@ class ProcessTar : public pkgDirStream public: PyObject *Function; - + virtual bool DoItem(Item &Itm,int &Fd); - + ProcessTar(PyObject *Function) : Function(Function) { Py_INCREF(Function); @@ -48,55 +48,55 @@ bool ProcessTar::DoItem(Item &Itm,int &Fd) case Item::File: Type = "FILE"; break; - + case Item::HardLink: Type = "HARDLINK"; break; - + case Item::SymbolicLink: Type = "SYMLINK"; break; - + case Item::CharDevice: Type = "CHARDEV"; break; - + case Item::BlockDevice: Type = "BLKDEV"; break; - + case Item::Directory: Type = "DIR"; break; - + case Item::FIFO: Type = "FIFO"; break; } - + if (PyObject_CallFunction(Function,"sssiiiiiii",Type,Itm.Name, Itm.LinkTarget,Itm.Mode,Itm.UID,Itm.GID,Itm.Size, Itm.MTime,Itm.Major,Itm.Minor) == 0) return false; - + Fd = -1; return true; } /*}}}*/ - + // tarExtract - Examine files from a tar /*{{{*/ // --------------------------------------------------------------------- /* */ char *doc_tarExtract = "tarExtract(File,Func,Comp) -> None\n" "The tar file referenced by the file object File, Func called for each\n" -"Tar member. Comp must be the string \"gzip\" (gzip is automatically invoked) \n"; +"Tar member. Comp must be the string \"gzip\" (gzip is automatically invoked) \n"; PyObject *tarExtract(PyObject *Self,PyObject *Args) { PyObject *File; PyObject *Function; char *Comp; - + if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, &Function,&Comp) == 0) return 0; @@ -106,19 +106,19 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args) PyErr_SetString(PyExc_TypeError,"argument 2: expected something callable."); return 0; } - + { // Open the file and associate the tar FileFd Fd(fileno(PyFile_AsFile(File)),false); ExtractTar Tar(Fd,0xFFFFFFFF,Comp); if (_error->PendingError() == true) return HandleErrors(); - + ProcessTar Proc(Function); if (Tar.Go(Proc) == false) return HandleErrors(); - } - + } + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -138,11 +138,11 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) PyObject *Function; char *Chunk; const char *Comp = "gzip"; - + if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, &Function,&Chunk) == 0) return 0; - + if (PyCallable_Check(Function) == 0) { PyErr_SetString(PyExc_TypeError,"argument 2: expected something callable."); @@ -156,15 +156,15 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); - - // Get the archive member and positition the file + + // Get the archive member and positition the file const ARArchive::Member *Member = Deb.GotoMember(Chunk); if (Member == 0) { _error->Error("Cannot find chunk %s",Chunk); return HandleErrors(); } - + // Extract it. if (strcmp(".bz2", &Chunk[strlen(Chunk)-4]) == 0) Comp = "bzip2"; @@ -174,8 +174,8 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) ProcessTar Proc(Function); if (Tar.Go(Proc) == false) return HandleErrors(); - } - + } + Py_INCREF(Py_None); return HandleErrors(Py_None); } @@ -3,72 +3,67 @@ from distutils.core import setup, Extension from distutils.sysconfig import parse_makefile -from DistUtilsExtra.command import * +from DistUtilsExtra.command import build_extra, build_i18n import glob import os -import os.path -import pydoc import shutil -import string import sys -def build_docs(dir="html", modules=["apt","aptsources"]): - htmldir = os.path.join(os.getcwd(), dir) - for d in modules: - for (dirpath, dirnames, filenames) in os.walk(d): - pydoc.writedoc(dirpath.replace("/",".")) - for file in filenames: - if not file.endswith(".py"): - continue - if file in ["__init__.py"]: - continue - pydoc.writedoc(dirpath.replace("/",".")+"."+file.split(".py")[0]) - if not os.path.exists(htmldir): - os.mkdir(htmldir) - for f in glob.glob("*.html"): - shutil.move(f, htmldir) - return True # The apt_pkg module files = map(lambda source: "python/"+source, - string.split(parse_makefile("python/makefile")["APT_PKG_SRC"])) -apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]); + 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, - string.split(parse_makefile("python/makefile")["APT_INST_SRC"])) -apt_inst = Extension("apt_inst", files, libraries=["apt-pkg","apt-inst"]); + 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 = [] -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() # build doc -if sys.argv[1] == "build": - build_docs() +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() -setup(name="python-apt", - version="0.6.17", + +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", + version="0.7.9", description="Python bindings for APT", author="APT Development Team", author_email="deity@lists.debian.org", - ext_modules=[apt_pkg,apt_inst], + ext_modules=[apt_pkg, apt_inst], packages=['apt', 'apt.gtk', '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 }, + cmdclass = {"build": build_extra.build_extra, + "build_i18n": build_i18n.build_i18n}, license = 'GNU GPL', - platforms = 'posix' - ) + platforms = 'posix') + +if len(sys.argv) > 1 and sys.argv[1] == "build": + import sphinx + 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/tests/apt-test.py b/tests/apt-test.py index 6205cf60..fac2ff43 100644 --- a/tests/apt-test.py +++ b/tests/apt-test.py @@ -20,7 +20,7 @@ if __name__ == "__main__": cache = apt.Cache(progress) for name in cache.keys(): import random - if random.randint(0,1) == 1: + if random.randint(0, 1) == 1: cache[name].markDelete() print "Broken: %s " % cache._depcache.BrokenCount print "DelCount: %s " % cache._depcache.DelCount diff --git a/tests/cache.py b/tests/cache.py index 47d9a3b4..87a544e8 100644 --- a/tests/cache.py +++ b/tests/cache.py @@ -1,49 +1,51 @@ -#!/usr/bin/env python2.4 +#!/usr/bin/python # # Test for the pkgCache code -# +# import apt_pkg import sys + def main(): - apt_pkg.init() - cache = apt_pkg.GetCache() - depcache = apt_pkg.GetDepCache(cache) - depcache.Init() - i=0 - all=cache.PackageCount - print "Running Cache test on all packages:" - # first, get all pkgs - for pkg in cache.Packages: - i += 1 - x = pkg.Name - # then get each version - for ver in pkg.VersionList: - # get some version information - a = ver.FileList - b = ver.VerStr - c = ver.Arch - d = ver.DependsListStr - dl = ver.DependsList - # get all dependencies (a dict of string->list, - # e.g. "depends:" -> [ver1,ver2,..] - for dep in dl.keys(): - # get the list of each dependency object - for depVerList in dl[dep]: - for z in depVerList: - # get all TargetVersions of - # the dependency object - for j in z.AllTargets(): - f = j.FileList - g = ver.VerStr - h = ver.Arch - k = ver.DependsListStr - j = ver.DependsList - pass - - print "\r%i/%i=%.3f%% " % (i,all,(float(i)/float(all)*100)), + apt_pkg.init() + cache = apt_pkg.GetCache() + depcache = apt_pkg.GetDepCache(cache) + depcache.Init() + i=0 + all=cache.PackageCount + print "Running Cache test on all packages:" + # first, get all pkgs + for pkg in cache.Packages: + i += 1 + x = pkg.Name + # then get each version + for ver in pkg.VersionList: + # get some version information + a = ver.FileList + b = ver.VerStr + c = ver.Arch + d = ver.DependsListStr + dl = ver.DependsList + # get all dependencies (a dict of string->list, + # e.g. "depends:" -> [ver1,ver2,..] + for dep in dl.keys(): + # get the list of each dependency object + for depVerList in dl[dep]: + for z in depVerList: + # get all TargetVersions of + # the dependency object + for j in z.AllTargets(): + f = j.FileList + g = ver.VerStr + h = ver.Arch + k = ver.DependsListStr + j = ver.DependsList + pass + + print "\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)), + if __name__ == "__main__": - main() - sys.exit(0) + main() + sys.exit(0) diff --git a/tests/depcache.py b/tests/depcache.py index f4821b4f..19aba680 100644 --- a/tests/depcache.py +++ b/tests/depcache.py @@ -1,52 +1,54 @@ #!/usr/bin/env python2.4 # # Test for the DepCache code -# +# import apt_pkg import sys + def main(): - apt_pkg.init() - cache = apt_pkg.GetCache() - depcache = apt_pkg.GetDepCache(cache) - depcache.Init() - i=0 - all=cache.PackageCount - print "Running DepCache test on all packages" - print "(trying to install each and then mark it keep again):" - # first, get all pkgs - for pkg in cache.Packages: - i += 1 - x = pkg.Name - # then get each version - ver =depcache.GetCandidateVer(pkg) - if ver != None: - depcache.MarkInstall(pkg) - if depcache.InstCount == 0: - if depcache.IsUpgradable(pkg): - print "Error marking %s for install" % x - for p in cache.Packages: - if depcache.MarkedInstall(p): - depcache.MarkKeep(p) - if depcache.InstCount != 0: - print "Error undoing the selection for %s (InstCount: %s)" % (x,depcache.InstCount) - print "\r%i/%i=%.3f%% " % (i,all,(float(i)/float(all)*100)), + apt_pkg.init() + cache = apt_pkg.GetCache() + depcache = apt_pkg.GetDepCache(cache) + depcache.Init() + i=0 + all=cache.PackageCount + print "Running DepCache test on all packages" + print "(trying to install each and then mark it keep again):" + # first, get all pkgs + for pkg in cache.Packages: + i += 1 + x = pkg.Name + # then get each version + ver =depcache.GetCandidateVer(pkg) + if ver is not None: + depcache.MarkInstall(pkg) + if depcache.InstCount == 0: + if depcache.IsUpgradable(pkg): + print "Error marking %s for install" % x + for p in cache.Packages: + if depcache.MarkedInstall(p): + depcache.MarkKeep(p) + if depcache.InstCount != 0: + print "Error undoing the selection for %s (InstCount: %s)" % ( + x, depcache.InstCount) + print "\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)), - print - print "Trying Upgrade:" - depcache.Upgrade() - print "To install: %s " % depcache.InstCount - print "To remove: %s " % depcache.DelCount - print "Kept back: %s " % depcache.KeepCount + print + print "Trying Upgrade:" + depcache.Upgrade() + print "To install: %s " % depcache.InstCount + print "To remove: %s " % depcache.DelCount + print "Kept back: %s " % depcache.KeepCount - print "Trying DistUpgrade:" - depcache.Upgrade(True) - print "To install: %s " % depcache.InstCount - print "To remove: %s " % depcache.DelCount - print "Kept back: %s " % depcache.KeepCount + print "Trying DistUpgrade:" + depcache.Upgrade(True) + print "To install: %s " % depcache.InstCount + print "To remove: %s " % depcache.DelCount + print "Kept back: %s " % depcache.KeepCount if __name__ == "__main__": - main() - sys.exit(0) + main() + sys.exit(0) diff --git a/tests/lock.py b/tests/lock.py index 5d2697f1..d45b3964 100644 --- a/tests/lock.py +++ b/tests/lock.py @@ -1,15 +1,16 @@ #!/usr/bin/env python2.4 # # Test for the pkgCache code -# +# import apt_pkg -import sys, os +import sys +import os if __name__ == "__main__": lock = "/tmp/test.lck" - + apt_pkg.init() # system-lock @@ -21,27 +22,26 @@ if __name__ == "__main__": apt_pkg.PkgSystemLock() except SystemError, s: print "Can't get lock: (error text:\n%s)" % s - sys.exit(0) + sys.exit(0) apt_pkg.PkgSystemUnLock() # low-level lock - fd = apt_pkg.GetLock(lock,True) + fd = apt_pkg.GetLock(lock, True) print "Lockfile fd: %s" % fd # try to get lock without error flag pid = os.fork() if pid == 0: # child - fd = apt_pkg.GetLock(lock,False) + fd = apt_pkg.GetLock(lock, False) print "Lockfile fd (child): %s" % fd - sys.exit(0) + sys.exit(0) # try to get lock with error flag pid = os.fork() if pid == 0: # child - fd = apt_pkg.GetLock(lock,True) + fd = apt_pkg.GetLock(lock, True) print "Lockfile fd (child): %s" % fd - sys.exit(0) - + sys.exit(0) diff --git a/tests/memleak.py b/tests/memleak.py index b5d05afc..659091fc 100755 --- a/tests/memleak.py +++ b/tests/memleak.py @@ -11,36 +11,36 @@ cache = apt.Cache() # memleak for i in range(100): - cache.open(None) - print cache["apt"].name - time.sleep(1) - gc.collect() - f = open("%s" % i,"w") - for obj in gc.get_objects(): - f.write("%s\n" % str(obj)) - f.close() - -# memleak + cache.open(None) + print cache["apt"].name + time.sleep(1) + gc.collect() + f = open("%s" % i, "w") + for obj in gc.get_objects(): + f.write("%s\n" % str(obj)) + f.close() + +# memleak #for i in range(100): -# cache = apt.Cache() -# time.sleep(1) -# cache = None -# gc.collect() +# cache = apt.Cache() +# time.sleep(1) +# cache = None +# gc.collect() # no memleak, but more or less the apt.Cache.open() code for i in range(100): - cache = apt_pkg.GetCache() - depcache = apt_pkg.GetDepCache(cache) - records = apt_pkg.GetPkgRecords(cache) - list = apt_pkg.GetPkgSourceList() - list.ReadMainList() - dict = {} - for pkg in cache.Packages: - if len(pkg.VersionList) > 0: - dict[pkg.Name] = apt.Package(cache,depcache, - records, list, None, pkg) - - print cache["apt"] - time.sleep(1) - - gc.collect() + cache = apt_pkg.GetCache() + depcache = apt_pkg.GetDepCache(cache) + records = apt_pkg.GetPkgRecords(cache) + list = apt_pkg.GetPkgSourceList() + list.ReadMainList() + dict = {} + for pkg in cache.Packages: + if len(pkg.VersionList) > 0: + dict[pkg.Name] = apt.Package(cache, depcache, + records, list, None, pkg) + + print cache["apt"] + time.sleep(1) + + gc.collect() diff --git a/tests/pkgproblemresolver.py b/tests/pkgproblemresolver.py index 27747e43..a21d8d9d 100644 --- a/tests/pkgproblemresolver.py +++ b/tests/pkgproblemresolver.py @@ -1,69 +1,70 @@ #!/usr/bin/env python2.4 # # Test for the DepCache code -# +# import apt_pkg import sys + def main(): - apt_pkg.init() - cache = apt_pkg.GetCache() - depcache = apt_pkg.GetDepCache(cache) - depcache.Init() - i=0 - all=cache.PackageCount - print "Running DepCache test on all packages" - print "(trying to install each and then mark it keep again):" - # first, get all pkgs - for pkg in cache.Packages: - i += 1 - x = pkg.Name - # then get each version - ver =depcache.GetCandidateVer(pkg) - if ver != None: - depcache.MarkInstall(pkg) - if depcache.BrokenCount > 0: - fixer = apt_pkg.GetPkgProblemResolver(depcache) - fixer.Clear(pkg) - fixer.Protect(pkg) - # we first try to resolve the problem - # with the package that should be installed - # protected - try: - fixer.Resolve(True) - except SystemError: - # the pkg seems to be broken, the - # returns a exception - fixer.Clear(pkg) - fixer.Resolve(True) - if not depcache.MarkedInstall(pkg): - print "broken in archive: %s " % pkg.Name - fixer = None - if depcache.InstCount == 0: - if depcache.IsUpgradable(pkg): - print "Error marking %s for install" % x - for p in cache.Packages: - if depcache.MarkedInstall(p) or depcache.MarkedUpgrade(p): - depcache.MarkKeep(p) - if depcache.InstCount != 0: - print "Error undoing the selection for %s" % x - print "\r%i/%i=%.3f%% " % (i,all,(float(i)/float(all)*100)), + apt_pkg.init() + cache = apt_pkg.GetCache() + depcache = apt_pkg.GetDepCache(cache) + depcache.Init() + i=0 + all=cache.PackageCount + print "Running DepCache test on all packages" + print "(trying to install each and then mark it keep again):" + # first, get all pkgs + for pkg in cache.Packages: + i += 1 + x = pkg.Name + # then get each version + ver =depcache.GetCandidateVer(pkg) + if ver is not None: + depcache.MarkInstall(pkg) + if depcache.BrokenCount > 0: + fixer = apt_pkg.GetPkgProblemResolver(depcache) + fixer.Clear(pkg) + fixer.Protect(pkg) + # we first try to resolve the problem + # with the package that should be installed + # protected + try: + fixer.Resolve(True) + except SystemError: + # the pkg seems to be broken, the + # returns a exception + fixer.Clear(pkg) + fixer.Resolve(True) + if not depcache.MarkedInstall(pkg): + print "broken in archive: %s " % pkg.Name + fixer = None + if depcache.InstCount == 0: + if depcache.IsUpgradable(pkg): + print "Error marking %s for install" % x + for p in cache.Packages: + if depcache.MarkedInstall(p) or depcache.MarkedUpgrade(p): + depcache.MarkKeep(p) + if depcache.InstCount != 0: + print "Error undoing the selection for %s" % x + print "\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)), - print - print "Trying Upgrade:" - depcache.Upgrade() - print "To install: %s " % depcache.InstCount - print "To remove: %s " % depcache.DelCount - print "Kept back: %s " % depcache.KeepCount + print + print "Trying Upgrade:" + depcache.Upgrade() + print "To install: %s " % depcache.InstCount + print "To remove: %s " % depcache.DelCount + print "Kept back: %s " % depcache.KeepCount - print "Trying DistUpgrade:" - depcache.Upgrade(True) - print "To install: %s " % depcache.InstCount - print "To remove: %s " % depcache.DelCount - print "Kept back: %s " % depcache.KeepCount + print "Trying DistUpgrade:" + depcache.Upgrade(True) + print "To install: %s " % depcache.InstCount + print "To remove: %s " % depcache.DelCount + print "Kept back: %s " % depcache.KeepCount if __name__ == "__main__": - main() - sys.exit(0) + main() + sys.exit(0) diff --git a/tests/pkgrecords.py b/tests/pkgrecords.py index d0616d29..5866847d 100644 --- a/tests/pkgrecords.py +++ b/tests/pkgrecords.py @@ -2,35 +2,39 @@ # # Test for the PkgSrcRecords code # it segfaults for python-apt < 0.5.37 -# +# import apt_pkg import sys + def main(): - apt_pkg.init() - cache = apt_pkg.GetCache() - depcache = apt_pkg.GetDepCache(cache) - depcache.Init() - i=0 - print "Running PkgRecords test on all packages:" - for pkg in cache.Packages: - i += 1 - records = apt_pkg.GetPkgRecords(cache) - if len(pkg.VersionList) == 0: - #print "no available version, cruft" - continue - version = depcache.GetCandidateVer(pkg) - if not version: - continue - file, index = version.FileList.pop(0) - if records.Lookup((file,index)): - #print records.FileName - x = records.FileName - y = records.LongDesc - pass - print "\r%i/%i=%.3f%% " % (i,cache.PackageCount, (float(i)/float(cache.PackageCount)*100)), + apt_pkg.init() + cache = apt_pkg.GetCache() + depcache = apt_pkg.GetDepCache(cache) + depcache.Init() + i=0 + print "Running PkgRecords test on all packages:" + for pkg in cache.Packages: + i += 1 + records = apt_pkg.GetPkgRecords(cache) + if len(pkg.VersionList) == 0: + #print "no available version, cruft" + continue + version = depcache.GetCandidateVer(pkg) + if not version: + continue + file, index = version.FileList.pop(0) + if records.Lookup((file, index)): + #print records.FileName + x = records.FileName + y = records.LongDesc + pass + print "\r%i/%i=%.3f%% " % ( + i, cache.PackageCount, + (float(i) / float(cache.PackageCount) * 100)), + if __name__ == "__main__": - main() - sys.exit(0) + main() + sys.exit(0) diff --git a/tests/pkgsrcrecords.py b/tests/pkgsrcrecords.py index 28df3f7c..77670540 100644 --- a/tests/pkgsrcrecords.py +++ b/tests/pkgsrcrecords.py @@ -2,24 +2,28 @@ # # Test for the PkgSrcRecords code # it segfaults for python-apt < 0.5.37 -# +# import apt_pkg import sys + def main(): - apt_pkg.init() - cache = apt_pkg.GetCache() - i=0 - print "Running PkgSrcRecords test on all packages:" - for x in cache.Packages: - i += 1 - src = apt_pkg.GetPkgSrcRecords() - if src.Lookup(x.Name): - #print src.Package - pass - print "\r%i/%i=%.3f%% " % (i,cache.PackageCount, (float(i)/float(cache.PackageCount)*100)), + apt_pkg.init() + cache = apt_pkg.GetCache() + i=0 + print "Running PkgSrcRecords test on all packages:" + for x in cache.Packages: + i += 1 + src = apt_pkg.GetPkgSrcRecords() + if src.Lookup(x.Name): + #print src.Package + pass + print "\r%i/%i=%.3f%% " % ( + i, cache.PackageCount, + (float(i) / float(cache.PackageCount) * 100)), + if __name__ == "__main__": - main() - sys.exit(0) + main() + sys.exit(0) diff --git a/tests/refcount.py b/tests/refcount.py index f3230bd3..a29744ae 100755 --- a/tests/refcount.py +++ b/tests/refcount.py @@ -1,6 +1,6 @@ #!/usr/bin/python-dbg -from pprint import pprint,pformat +from pprint import pprint, pformat import apt import sys import gc diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index 49fe6afa..3761f3ff 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -1,31 +1,35 @@ #!/usr/bin/env python import unittest -import apt_pkg import os import copy - import sys + sys.path.insert(0, "../") +import apt_pkg import aptsources import aptsources.sourceslist import aptsources.distro + class TestAptSources(unittest.TestCase): + def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) apt_pkg.init() apt_pkg.Config.Set("Dir::Etc", os.getcwd()) - apt_pkg.Config.Set("Dir::Etc::sourceparts","/xxx") + apt_pkg.Config.Set("Dir::Etc::sourceparts", "/xxx") def testIsMirror(self): - self.assertTrue(aptsources.sourceslist.is_mirror("http://archive.ubuntu.com", - "http://de.archive.ubuntu.com")) - self.assertFalse(aptsources.sourceslist.is_mirror("http://archive.ubuntu.com", - "http://ftp.debian.org")) + yes = aptsources.sourceslist.is_mirror("http://archive.ubuntu.com", + "http://de.archive.ubuntu.com") + no = aptsources.sourceslist.is_mirror("http://archive.ubuntu.com", + "http://ftp.debian.org") + self.assertTrue(yes) + self.assertFalse(no) def testSourcesListReading(self): - apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list") + apt_pkg.Config.Set("Dir::Etc::sourcelist", "data/sources.list") sources = aptsources.sourceslist.SourcesList() self.assertEqual(len(sources.list), 6) # test load @@ -34,22 +38,22 @@ class TestAptSources(unittest.TestCase): self.assertEqual(len(sources.list), 6) def testSourcesListAdding(self): - apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list") + apt_pkg.Config.Set("Dir::Etc::sourcelist", "data/sources.list") sources = aptsources.sourceslist.SourcesList() # test to add something that is already there (main) before = copy.deepcopy(sources) - sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"]) self.assertTrue(sources.list == before.list) # test to add something that is already there (restricted) before = copy.deepcopy(sources) - sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["restricted"]) self.assertTrue(sources.list == before.list) # test to add something new: multiverse - sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"]) found = False @@ -60,10 +64,10 @@ class TestAptSources(unittest.TestCase): "multiverse" in entry.comps): found = True self.assertTrue(found) - # test to add something new: multiverse *and* + # test to add something new: multiverse *and* # something that is already there before = copy.deepcopy(sources) - sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["universe", "something"]) found_universe = 0 @@ -82,7 +86,8 @@ class TestAptSources(unittest.TestCase): self.assertEqual(found_universe, 1) def testMatcher(self): - apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list.testDistribution") + apt_pkg.Config.Set("Dir::Etc::sourcelist", "data/sources.list.test" + "Distribution") sources = aptsources.sourceslist.SourcesList() distro = aptsources.distro.get_distro() distro.get_sources(sources) @@ -93,7 +98,8 @@ class TestAptSources(unittest.TestCase): self.fail("source entry '%s' has no matcher" % s) def testDistribution(self): - apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list.testDistribution") + apt_pkg.Config.Set("Dir::Etc::sourcelist", "data/sources.list.test" + "Distribution") sources = aptsources.sourceslist.SourcesList() distro = aptsources.distro.get_distro() distro.get_sources(sources) @@ -103,9 +109,10 @@ class TestAptSources(unittest.TestCase): if s.template: dist_templates.add(s.template.name) #print dist_templates - for d in ["hardy","hardy-security","hardy-updates","intrepid","hardy-backports"]: + for d in ("hardy", "hardy-security", "hardy-updates", "intrepid", + "hardy-backports"): self.assertTrue(d in dist_templates) - # test enable + # test enable comp = "restricted" distro.enable_component(comp) found = {} @@ -115,7 +122,7 @@ class TestAptSources(unittest.TestCase): "edgy" in entry.dist): for c in entry.comps: if c == comp: - if not found.has_key(entry.dist): + if not entry.dist in found: found[entry.dist] = 0 found[entry.dist] += 1 #print "".join([s.str() for s in sources]) @@ -132,12 +139,13 @@ class TestAptSources(unittest.TestCase): entry.template.name == "edgy"): for c in entry.comps: if c == comp: - if not found.has_key(entry.dist): + if not entry.dist in found.has_key: found[entry.dist] = 0 found[entry.dist] += 1 #print "".join([s.str() for s in sources]) for key in found: self.assertEqual(found[key], 1) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_aptsources_ports.py b/tests/test_aptsources_ports.py index 203721c7..09d6e9d9 100644 --- a/tests/test_aptsources_ports.py +++ b/tests/test_aptsources_ports.py @@ -1,28 +1,32 @@ #!/usr/bin/env python import unittest -import apt_pkg + import os import copy - import sys + sys.path.insert(0, "../") +import apt_pkg import aptsources import aptsources.sourceslist import aptsources.distro + class TestAptSources(unittest.TestCase): + def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) apt_pkg.init() - apt_pkg.Config.Set("APT::Architecture","powerpc") - apt_pkg.Config.Set("Dir::Etc", os.path.join(os.getcwd(),"test-data-ports")) - apt_pkg.Config.Set("Dir::Etc::sourceparts","/xxx") + apt_pkg.Config.Set("APT::Architecture", "powerpc") + apt_pkg.Config.Set("Dir::Etc", os.path.abspath("test-data-ports")) + apt_pkg.Config.Set("Dir::Etc::sourceparts", "/xxx") def testMatcher(self): - apt_pkg.Config.Set("Dir::Etc::sourcelist","sources.list") + apt_pkg.Config.Set("Dir::Etc::sourcelist", "sources.list") sources = aptsources.sourceslist.SourcesList() - distro = aptsources.distro.get_distro("Ubuntu","hardy","desc","8.04") + distro = aptsources.distro.get_distro("Ubuntu", "hardy", "desc", + "8.04") distro.get_sources(sources) # test if all suits of the current distro were detected correctly dist_templates = set() diff --git a/tests/test_debextract.py b/tests/test_debextract.py index 53241e92..4ba498ae 100755 --- a/tests/test_debextract.py +++ b/tests/test_debextract.py @@ -1,13 +1,18 @@ #!/usr/bin/python +import sys import apt_inst -import sys -def Callback(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor): + +def Callback(What, Name, Link, Mode, UID, GID, Size, MTime, Major, Minor): print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u" % ( - What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor) + What, Name, Link, Mode, UID, GID, Size, MTime, Major, Minor) + + +def main(): + member = "data.tar.lzma" + if len(sys.argv) > 2: + member = sys.argv[2] + apt_inst.debExtract(open(sys.argv[1]), Callback, member) -member = "data.tar.lzma" -if len(sys.argv) > 2: - member = sys.argv[2] -apt_inst.debExtract(open(sys.argv[1]), Callback, member) +main() diff --git a/tests/test_hashsums.py b/tests/test_hashsums.py index 7fa6eb60..0cf6beb7 100644 --- a/tests/test_hashsums.py +++ b/tests/test_hashsums.py @@ -3,6 +3,7 @@ import unittest import apt_pkg + class testHashes(unittest.TestCase): " test the hashsum functions against strings and files " @@ -45,7 +46,8 @@ class testHashes(unittest.TestCase): def testSHA256(self): # simple s = "foo" - s_hash = "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" + s_hash = \ + "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" res = apt_pkg.sha256sum(s) self.assert_(res == s_hash) # file @@ -53,7 +55,8 @@ class testHashes(unittest.TestCase): self.assert_(res == s_hash) # with zero (\0) in the string s = "foo\0bar" - s_hash = "d6b681bfce7155d44721afb79c296ef4f0fa80a9dd6b43c5cf74dd0f64c85512" + s_hash = \ + "d6b681bfce7155d44721afb79c296ef4f0fa80a9dd6b43c5cf74dd0f64c85512" res = apt_pkg.sha256sum(s) self.assert_(res == s_hash) # file diff --git a/utils/get_debian_mirrors.py b/utils/get_debian_mirrors.py index ccddf8ed..2e3c7296 100755 --- a/utils/get_debian_mirrors.py +++ b/utils/get_debian_mirrors.py @@ -2,23 +2,23 @@ # # get_debian_mirrors.py # -# Download the latest list with available mirrors from the Debian +# Download the latest list with available mirrors from the Debian # website and extract the hosts from the raw page # # Copyright (c) 2006 Free Software Foundation Europe # # Author: Sebastian Heinlein <glatzor@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -39,11 +39,13 @@ req = urllib2.Request("http://www.debian.org/mirror/mirrors_full") match = re.compile("^.*>([A-Za-z0-9-.\/_]+)<\/a>.*\n$") match_location = re.compile('^<strong><a name="([A-Z]+)">.*') + def add_sites(line, proto, sites, mirror_type): path = match.sub(r"\1", line) for site in sites: mirror_type.append("%s://%s%s\n" % (proto, site.lstrip(), path)) + try: print "Downloading mirrors list from the Debian website..." uri=urllib2.urlopen(req) diff --git a/utils/get_ubuntu_mirrors.py b/utils/get_ubuntu_mirrors.py index 62b18ba6..ddd1e369 100755 --- a/utils/get_ubuntu_mirrors.py +++ b/utils/get_ubuntu_mirrors.py @@ -8,17 +8,17 @@ # Copyright (c) 2006 Free Software Foundation Europe # # Author: Sebastian Heinlein <glatzor@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -42,10 +42,10 @@ try: uri=urllib2.urlopen(req) p = re.compile('^.*((http|ftp):\/\/[A-Za-z0-9-.:\/_]+).*\n*$') for line in uri.readlines(): - if r"[[Anchor(dvd-images)]]" in line: - break - if "http://" in line or "ftp://" in line: - mirrors.append(p.sub(r"\1", line)) + if r"[[Anchor(dvd-images)]]" in line: + break + if "http://" in line or "ftp://" in line: + mirrors.append(p.sub(r"\1", line)) uri.close() except: print "Failed to download or extract the mirrors list!" @@ -57,5 +57,3 @@ for mirror in mirrors: list.write("%s\n" % mirror) list.close() print "Done." - - diff --git a/utils/get_ubuntu_mirrors_from_lp.py b/utils/get_ubuntu_mirrors_from_lp.py index 7d9116f2..b912f28d 100755 --- a/utils/get_ubuntu_mirrors_from_lp.py +++ b/utils/get_ubuntu_mirrors_from_lp.py @@ -8,17 +8,17 @@ # Copyright (c) 2006 Free Software Foundation Europe # # Author: Sebastian Heinlein <glatzor@ubuntu.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,11 +64,13 @@ content_splits = re.split(r'<tr class="highlighted"', 'id="mirrors_list">.+?</table>', content)[0]) lines=[] + + def find(split): country = re.search(r"<strong>(.+?)</strong>", split) if not country: return - if countries.has_key(country.group(1)): + if country.group(1) in countries: lines.append("#LOC:%s" % countries[country.group(1)].upper()) else: lines.append("#LOC:%s" % country.group(1)) @@ -78,6 +80,7 @@ def find(split): split) map(lambda u: lines.append(u[0]), urls) + map(find, content_splits) print "Writing local mirrors list: %s" % list_path diff --git a/utils/mirrortest b/utils/mirrortest index 75ef917b..a724c81f 100755 --- a/utils/mirrortest +++ b/utils/mirrortest @@ -24,8 +24,8 @@ class MirrorTest: host = mirror.hostname except: continue - print "Pinging (Worker %s) %s (%s) ..." % (self.id, - host, + print "Pinging (Worker %s) %s (%s) ..." % (self.id, + host, MirrorTest.completed_pings) commando = os.popen("ping -q -c 4 -W 2 -i 0.3 %s" % host, "r") |
