[Python-checkins] python/dist/src/Lib/plat-mac pimp.py, 1.27.4.1, 1.27.4.2

jackjansen at users.sourceforge.net jackjansen at users.sourceforge.net
Thu Jun 3 09:07:42 EDT 2004


Update of /cvsroot/python/python/dist/src/Lib/plat-mac
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26052

Modified Files:
      Tag: release23-maint
	pimp.py 
Log Message:
Backport of 1.31-1.34:
- Added a downloader using urllib2 in stead of curl, based on code
donated by Kevin Ollivier. This is now the default downloader.
- Added a watcher mechanism, whereby downloaders and unpackers (and,
later builders) can give status feedback to the user. When running
pimp as a command line tool in verbose mode print this output.
- Force option should be applied to a single package, not recursively
to its dependencies. Fixes #733819.
- Don't use "dict" as a variable, it shadows the builtin. Spotted by
Bob Ippolito.
Two issues spotted by Ronald OUssoren:
- there were no accessor functions for the global per-database fields
- packages and their dependencies were installed in order in stead
  of in reverse order.



Index: pimp.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/pimp.py,v
retrieving revision 1.27.4.1
retrieving revision 1.27.4.2
diff -C2 -d -r1.27.4.1 -r1.27.4.2
*** pimp.py	28 Feb 2004 23:21:50 -0000	1.27.4.1
--- pimp.py	3 Jun 2004 13:07:39 -0000	1.27.4.2
***************
*** 26,29 ****
--- 26,30 ----
  import tempfile
  import shutil
+ import time
  
  __all__ = ["PimpPreferences", "PimpDatabase", "PimpPackage", "main", 
***************
*** 48,94 ****
  
  def getDefaultDatabase(experimental=False):
! 	if experimental:
! 		status = "exp"
! 	else:
! 		status = "prod"
! 		
! 	major, minor, micro, state, extra = sys.version_info
! 	pyvers = '%d.%d' % (major, minor)
! 	if state != 'final':
! 		pyvers = pyvers + '%s%d' % (state, extra)
! 		
! 	longplatform = distutils.util.get_platform()
! 	osname, release, machine = longplatform.split('-')
! 	# For some platforms we may want to differentiate between
! 	# installation types
! 	if osname == 'darwin':
! 		if sys.prefix.startswith('/System/Library/Frameworks/Python.framework'):
! 			osname = 'darwin_apple'
! 		elif sys.prefix.startswith('/Library/Frameworks/Python.framework'):
! 			osname = 'darwin_macpython'
! 		# Otherwise we don't know...
! 	# Now we try various URLs by playing with the release string.
! 	# We remove numbers off the end until we find a match.
! 	rel = release
! 	while True:
! 		url = DEFAULT_PIMPDATABASE_FMT % (PIMP_VERSION, status, pyvers, osname, rel, machine)
! 		try:
! 			urllib2.urlopen(url)
! 		except urllib2.HTTPError, arg:
! 			pass
! 		else:
! 			break
! 		if not rel:
! 			# We're out of version numbers to try. Use the
! 			# full release number, this will give a reasonable
! 			# error message later
! 			url = DEFAULT_PIMPDATABASE_FMT % (PIMP_VERSION, status, pyvers, osname, release, machine)
! 			break
! 		idx = rel.rfind('.')
! 		if idx < 0:
! 			rel = ''
! 		else:
! 			rel = rel[:idx]
! 	return url
  
  def _cmd(output, dir, *cmditems):
--- 49,95 ----
  
  def getDefaultDatabase(experimental=False):
!     if experimental:
!         status = "exp"
!     else:
!         status = "prod"
!         
!     major, minor, micro, state, extra = sys.version_info
!     pyvers = '%d.%d' % (major, minor)
!     if state != 'final':
!         pyvers = pyvers + '%s%d' % (state, extra)
!         
!     longplatform = distutils.util.get_platform()
!     osname, release, machine = longplatform.split('-')
!     # For some platforms we may want to differentiate between
!     # installation types
!     if osname == 'darwin':
!         if sys.prefix.startswith('/System/Library/Frameworks/Python.framework'):
!             osname = 'darwin_apple'
!         elif sys.prefix.startswith('/Library/Frameworks/Python.framework'):
!             osname = 'darwin_macpython'
!         # Otherwise we don't know...
!     # Now we try various URLs by playing with the release string.
!     # We remove numbers off the end until we find a match.
!     rel = release
!     while True:
!         url = DEFAULT_PIMPDATABASE_FMT % (PIMP_VERSION, status, pyvers, osname, rel, machine)
!         try:
!             urllib2.urlopen(url)
!         except urllib2.HTTPError, arg:
!             pass
!         else:
!             break
!         if not rel:
!             # We're out of version numbers to try. Use the
!             # full release number, this will give a reasonable
!             # error message later
!             url = DEFAULT_PIMPDATABASE_FMT % (PIMP_VERSION, status, pyvers, osname, release, machine)
!             break
!         idx = rel.rfind('.')
!         if idx < 0:
!             rel = ''
!         else:
!             rel = rel[:idx]
!     return url
  
  def _cmd(output, dir, *cmditems):
***************
*** 110,113 ****
--- 111,176 ----
      return child.wait()
  
+ class PimpDownloader:
+     """Abstract base class - Downloader for archives"""
+     
+     def __init__(self, argument,
+             dir="",
+             watcher=None):
+         self.argument = argument
+         self._dir = dir
+         self._watcher = watcher
+                 
+     def download(self, url, filename, output=None):
+         return None
+         
+     def update(self, str):
+         if self._watcher:
+             return self._watcher.update(str)
+         return True
+             
+ class PimpCurlDownloader(PimpDownloader):
+ 
+     def download(self, url, filename, output=None):
+         self.update("Downloading %s..." % url)
+         exitstatus = _cmd(output, self._dir,
+                     "curl",
+                     "--output", filename,
+                     url)
+         self.update("Downloading %s: finished" % url)
+         return (not exitstatus)
+             
+ class PimpUrllibDownloader(PimpDownloader):
+ 
+     def download(self, url, filename, output=None):
+         output = open(filename, 'wb')
+         self.update("Downloading %s: opening connection" % url)
+         keepgoing = True
+         download = urllib2.urlopen(url)
+         if download.headers.has_key("content-length"):
+             length = long(download.headers['content-length'])
+         else:
+             length = -1
+         
+         data = download.read(4096) #read 4K at a time
+         dlsize = 0
+         lasttime = 0
+         while keepgoing:
+             dlsize = dlsize + len(data)
+             if len(data) == 0: 
+                 #this is our exit condition
+                 break
+             output.write(data)
+             if int(time.time()) != lasttime:
+                 # Update at most once per second
+                 lasttime = int(time.time())
+                 if length == -1:
+                     keepgoing = self.update("Downloading %s: %d bytes..." % (url, dlsize))
+                 else:
+                     keepgoing = self.update("Downloading %s: %d%% (%d bytes)..." % (url, int(100.0*dlsize/length), dlsize))
+             data = download.read(4096)
+         if keepgoing:
+             self.update("Downloading %s: finished" % url)
+         return keepgoing
+         
  class PimpUnpacker:
      """Abstract base class - Unpacker for archives"""
***************
*** 117,121 ****
      def __init__(self, argument,
              dir="",
!             renames=[]):
          self.argument = argument
          if renames and not self._can_rename:
--- 180,185 ----
      def __init__(self, argument,
              dir="",
!             renames=[],
!             watcher=None):
          self.argument = argument
          if renames and not self._can_rename:
***************
*** 123,130 ****
--- 187,200 ----
          self._dir = dir
          self._renames = renames
+         self._watcher = watcher
                  
      def unpack(self, archive, output=None, package=None):
          return None
          
+     def update(self, str):
+         if self._watcher:
+             return self._watcher.update(str)
+         return True
+         
  class PimpCommandUnpacker(PimpUnpacker):
      """Unpack archives by calling a Unix utility"""
***************
*** 174,178 ****
--- 244,250 ----
          for member in members:
              if member in skip:
+                 self.update("Skipping %s" % member.name)
                  continue
+             self.update("Extracting %s" % member.name)
              tf.extract(member, self._dir)
          if skip:
***************
*** 215,218 ****
--- 287,294 ----
          self.buildDir = buildDir
          self.pimpDatabase = pimpDatabase
+         self.watcher = None
+         
+     def setWatcher(self, watcher):
+         self.watcher = watcher
          
      def setInstallDir(self, installDir=None):
***************
*** 283,286 ****
--- 359,363 ----
          self._packages = []
          self.preferences = prefs
+         self._url = ""
          self._urllist = []
          self._version = ""
***************
*** 288,291 ****
--- 365,374 ----
          self._description = ""
          
+     # Accessor functions
+     def url(self): return self._url
+     def version(self): return self._version
+     def maintainer(self): return self._maintainer
+     def description(self): return self._description
+         
      def close(self):
          """Clean up"""
***************
*** 302,314 ****
          self._urllist.append(url)
          fp = urllib2.urlopen(url).fp
!         dict = plistlib.Plist.fromFile(fp)
          # Test here for Pimp version, etc
          if included:
!             version = dict.get('Version')
              if version and version > self._version:
                  sys.stderr.write("Warning: included database %s is for pimp version %s\n" %
                      (url, version))
          else:
!             self._version = dict.get('Version')
              if not self._version:
                  sys.stderr.write("Warning: database has no Version information\n")
--- 385,397 ----
          self._urllist.append(url)
          fp = urllib2.urlopen(url).fp
!         plistdata = plistlib.Plist.fromFile(fp)
          # Test here for Pimp version, etc
          if included:
!             version = plistdata.get('Version')
              if version and version > self._version:
                  sys.stderr.write("Warning: included database %s is for pimp version %s\n" %
                      (url, version))
          else:
!             self._version = plistdata.get('Version')
              if not self._version:
                  sys.stderr.write("Warning: database has no Version information\n")
***************
*** 316,323 ****
                  sys.stderr.write("Warning: database version %s newer than pimp version %s\n" 
                      % (self._version, PIMP_VERSION))
!             self._maintainer = dict.get('Maintainer', '')
!             self._description = dict.get('Description', '').strip()
!         self._appendPackages(dict['Packages'])
!         others = dict.get('Include', [])
          for url in others:
              self.appendURL(url, included=1)
--- 399,407 ----
                  sys.stderr.write("Warning: database version %s newer than pimp version %s\n" 
                      % (self._version, PIMP_VERSION))
!             self._maintainer = plistdata.get('Maintainer', '')
!             self._description = plistdata.get('Description', '').strip()
!             self._url = url
!         self._appendPackages(plistdata['Packages'])
!         others = plistdata.get('Include', [])
          for url in others:
              self.appendURL(url, included=1)
***************
*** 362,366 ****
          for pkg in self._packages:
              packages.append(pkg.dump())
!         dict = {
              'Version': self._version,
              'Maintainer': self._maintainer,
--- 446,450 ----
          for pkg in self._packages:
              packages.append(pkg.dump())
!         plistdata = {
              'Version': self._version,
              'Maintainer': self._maintainer,
***************
*** 368,372 ****
              'Packages': packages
              }
!         plist = plistlib.Plist(**dict)
          plist.write(pathOrFile)
          
--- 452,456 ----
              'Packages': packages
              }
!         plist = plistlib.Plist(**plistdata)
          plist.write(pathOrFile)
          
***************
*** 429,439 ****
      """Class representing a single package."""
      
!     def __init__(self, db, dict):
          self._db = db
!         name = dict["Name"]
!         for k in dict.keys():
              if not k in ALLOWED_KEYS:
                  sys.stderr.write("Warning: %s: unknown key %s\n" % (name, k))
!         self._dict = dict
      
      def __getitem__(self, key):
--- 513,523 ----
      """Class representing a single package."""
      
!     def __init__(self, db, plistdata):
          self._db = db
!         name = plistdata["Name"]
!         for k in plistdata.keys():
              if not k in ALLOWED_KEYS:
                  sys.stderr.write("Warning: %s: unknown key %s\n" % (name, k))
!         self._dict = plistdata
      
      def __getitem__(self, key):
***************
*** 583,590 ****
              if scheme == 'manual':
                  return "Please download package manually and save as %s" % self.archiveFilename
!             if _cmd(output, self._db.preferences.downloadDir,
!                     "curl",
!                     "--output", self.archiveFilename,
!                     self._dict['Download-URL']):
                  return "download command failed"
          if not os.path.exists(self.archiveFilename) and not NO_EXECUTE:
--- 667,674 ----
              if scheme == 'manual':
                  return "Please download package manually and save as %s" % self.archiveFilename
!             downloader = PimpUrllibDownloader(None, self._db.preferences.downloadDir, 
!                 watcher=self._db.preferences.watcher)
!             if not downloader.download(self._dict['Download-URL'],
!                     self.archiveFilename, output):
                  return "download command failed"
          if not os.path.exists(self.archiveFilename) and not NO_EXECUTE:
***************
*** 615,619 ****
              return "unknown extension for archive file: %s" % filename
          self.basename = filename[:-len(ext)]
!         unpacker = unpackerClass(arg, dir=self._db.preferences.buildDir)
          rv = unpacker.unpack(self.archiveFilename, output=output)
          if rv:
--- 699,704 ----
              return "unknown extension for archive file: %s" % filename
          self.basename = filename[:-len(ext)]
!         unpacker = unpackerClass(arg, dir=self._db.preferences.buildDir, 
!                 watcher=self._db.preferences.watcher)
          rv = unpacker.unpack(self.archiveFilename, output=output)
          if rv:
***************
*** 824,828 ****
          for package in packages:
              if not package in self._todo:
!                 self._todo.insert(0, package)
              
      def _prepareInstall(self, package, force=0, recursive=1):
--- 909,913 ----
          for package in packages:
              if not package in self._todo:
!                 self._todo.append(package)
              
      def _prepareInstall(self, package, force=0, recursive=1):
***************
*** 845,849 ****
          for pkg, descr in prereqs:
              if pkg:
!                 self._prepareInstall(pkg, force, recursive)
              else:
                  self._curmessages.append("Problem with dependency: %s" % descr)
--- 930,934 ----
          for pkg, descr in prereqs:
              if pkg:
!                 self._prepareInstall(pkg, False, recursive)
              else:
                  self._curmessages.append("Problem with dependency: %s" % descr)
***************
*** 880,887 ****
          
      
! def _run(mode, verbose, force, args, prefargs):
      """Engine for the main program"""
      
      prefs = PimpPreferences(**prefargs)
      rv = prefs.check()
      if rv:
--- 965,974 ----
          
      
! def _run(mode, verbose, force, args, prefargs, watcher):
      """Engine for the main program"""
      
      prefs = PimpPreferences(**prefargs)
+     if watcher:
+         prefs.setWatcher(watcher)
      rv = prefs.check()
      if rv:
***************
*** 980,983 ****
--- 1067,1075 ----
          sys.exit(1)
          
+     class _Watcher:
+         def update(self, msg):
+             sys.stderr.write(msg + '\r')
+             return 1
+         
      try:
          opts, args = getopt.getopt(sys.argv[1:], "slifvdD:Vu:")
***************
*** 990,993 ****
--- 1082,1086 ----
      verbose = 0
      prefargs = {}
+     watcher = None
      for o, a in opts:
          if o == '-s':
***************
*** 1013,1016 ****
--- 1106,1110 ----
          if o == '-v':
              verbose = 1
+             watcher = _Watcher()
          if o == '-D':
              prefargs['installDir'] = a
***************
*** 1022,1026 ****
          print 'Pimp version %s; module name is %s' % (PIMP_VERSION, __name__)
      else:
!         _run(mode, verbose, force, args, prefargs)
  
  # Finally, try to update ourselves to a newer version.
--- 1116,1120 ----
          print 'Pimp version %s; module name is %s' % (PIMP_VERSION, __name__)
      else:
!         _run(mode, verbose, force, args, prefargs, watcher)
  
  # Finally, try to update ourselves to a newer version.




More information about the Python-checkins mailing list