summaryrefslogtreecommitdiff
path: root/apt/package.py
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2008-11-24 14:46:48 +0100
committerMichael Vogt <michael.vogt@ubuntu.com>2008-11-24 14:46:48 +0100
commit59937b2d3b6319773ab174066222c81ecd176628 (patch)
tree10863dc97ff1d44e9b4732896d03eb0f3257004f /apt/package.py
parentb90575e96622f14dc3d25972d0498faf0a02259e (diff)
parentd7b8902c36f77b7ae87b88cb4fdfbba7aa2ff833 (diff)
downloadpython-apt-59937b2d3b6319773ab174066222c81ecd176628.tar.gz
merged from the consolidation-bracn (with some modificatins)
Diffstat (limited to 'apt/package.py')
-rw-r--r--apt/package.py199
1 files changed, 193 insertions, 6 deletions
diff --git a/apt/package.py b/apt/package.py
index c1c2b1e1..94242e35 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -19,10 +19,18 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
-import apt_pkg
+import httplib
import sys
import random
+import re
+import socket
import string
+import urllib2
+
+import apt_pkg
+
+# Set a timeout for the changelog download
+socket.setdefaulttimeout(2)
#from gettext import gettext as _
import gettext
@@ -68,6 +76,7 @@ class Package(object):
self._pkg = pkgiter
self._list = sourcelist # sourcelist
self._pcache = pcache # python cache in cache.py
+ self._changelog = "" # Cached changelog
pass
# helper
@@ -236,7 +245,12 @@ class Package(object):
summary = property(summary)
def description(self, format=True):
- """ Return the formated 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
+ for more information.
+ """
if not self._lookupRecord():
return ""
# get the translated description
@@ -249,12 +263,35 @@ class Package(object):
except UnicodeDecodeError,e:
s = _("Invalid unicode in description for '%s' (%s). "
"Please report.") % (self.name,e)
- for line in string.split(s,"\n"):
- tmp = string.strip(line)
- if tmp == ".":
+ lines = string.split(s, "\n")
+ for i in range(len(lines)):
+ # Skip the first line, since its a duplication of the summary
+ if i == 0: continue
+ raw_line = lines[i]
+ if raw_line.strip() == ".":
+ # The line is just line break
+ if not desc.endswith("\n"):
desc += "\n"
+ continue
+ elif raw_line.startswith(" "):
+ # The line should be displayed verbatim without word wrapping
+ if not desc.endswith("\n"):
+ line = "\n%s\n" % raw_line[2:]
+ else:
+ line = "%s\n" % raw_line[2:]
+ elif raw_line.startswith(" "):
+ # The line is part of a paragraph.
+ if desc.endswith("\n") or desc == "":
+ # Skip the leading white space
+ line = raw_line[1:]
else:
- desc += tmp + "\n"
+ line = raw_line
+ else:
+ line = raw_line
+ # Use dots for lists
+ line = re.sub(r"^(\s*)(\*|0|o|-) ", ur"\1\u2022 ", line, 1)
+ # Add current line to the description
+ desc += line
return desc
description = property(description)
@@ -354,6 +391,156 @@ class Package(object):
return ver.InstalledSize
installedSize = property(installedSize)
+ def installedFiles(self):
+ """
+ Return the 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:
+ 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
+ """
+ # Return a cached changelog if available
+ if self._changelog != "":
+ return self._changelog
+
+ if uri == None:
+ if self.candidateOrigin[0].origin == "Debian":
+ uri = "http://packages.debian.org/changelogs/pool" \
+ "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
+ "/%(src_pkg)s_%(src_ver)s/changelog"
+ elif self.candidateOrigin[0].origin == "Ubuntu":
+ uri = "http://changelogs.ubuntu.com/changelogs/pool" \
+ "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
+ "/%(src_pkg)s_%(src_ver)s/changelog"
+ else:
+ return _("The list of changes is not available")
+
+ # get the src package name
+ src_pkg = self.sourcePackageName
+
+ # assume "main" section
+ src_section = "main"
+ # use the section of the candidate as a starting point
+ section = self._depcache.GetCandidateVer(self._pkg).Section
+
+ # get the source version, start with the binaries version
+ bin_ver = self.candidateVersion
+ src_ver = self.candidateVersion
+ #print "bin: %s" % binver
+ try:
+ # 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
+ # sources.list
+ # otherwise we fall back to the binary version number
+ src_records = apt_pkg.GetPkgSrcRecords()
+ src_rec = src_records.Lookup(src_pkg)
+ if src_rec:
+ src_ver = src_records.Version
+ #if apt_pkg.VersionCompare(binver, srcver) > 0:
+ # srcver = binver
+ if not src_ver:
+ src_ver = bin_ver
+ #print "srcver: %s" % src_ver
+ section = src_records.Section
+ #print "srcsect: %s" % section
+ else:
+ # fail into the error handler
+ raise SystemError
+ except SystemError, e:
+ src_ver = bin_ver
+
+ l = section.split("/")
+ if len(l) > 1:
+ src_section = l[0]
+
+ # lib is handled special
+ prefix = src_pkg[0]
+ if src_pkg.startswith("lib"):
+ prefix = "lib" + src_pkg[3]
+
+ # stip epoch
+ l = string.split(src_ver,":")
+ 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}
+ try:
+ # Check if the download was canceled
+ 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 ""
+ # Read changelog line by line
+ line_raw = changelog_file.readline()
+ if line_raw == "":
+ break
+ # The changelog is encoded in utf-8, but since there isn't any
+ # http header, urllib2 seems to treat it as ascii
+ line = line_raw.decode("utf-8")
+
+ #print line.encode('utf-8')
+ match = re.match(regexp, line)
+ if match:
+ # strip epoch from installed version
+ # and from changelog too
+ installed = self.installedVersion
+ if installed and ":" in installed:
+ installed = installed.split(":",1)[1]
+ changelog_ver = match.group(1)
+ if changelog_ver and ":" in changelog_ver:
+ changelog_ver = changelog_ver.split(":", 1)[1]
+ if installed and \
+ apt_pkg.VersionCompare(changelog_ver, installed) <= 0:
+ break
+ # EOF (shouldn't really happen)
+ changelog += line
+
+ # Print an error if we failed to extract a changelog
+ if len(changelog) == 0:
+ changelog = _("The list of changes is not available")
+ self._changelog = changelog
+ except urllib2.HTTPError,e:
+ 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.")
+ return self._changelog
+
# canidate origin
class Origin:
def __init__(self, pkg, VerFileIter):