home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / pycentral / python-apt / site-packages / apt / progress.py < prev   
Encoding:
Python Source  |  2006-03-02  |  7.7 KB  |  232 lines

  1. # Progress.py - progress reporting classes
  2. #  
  3. #  Copyright (c) 2005 Canonical
  4. #  
  5. #  Author: Michael Vogt <michael.vogt@ubuntu.com>
  6. #  This program is free software; you can redistribute it and/or 
  7. #  modify it under the terms of the GNU General Public License as 
  8. #  published by the Free Software Foundation; either version 2 of the
  9. #  License, or (at your option) any later version.
  10. #  This program is distributed in the hope that it will be useful,
  11. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #  GNU General Public License for more details.
  14. #  You should have received a copy of the GNU General Public License
  15. #  along with this program; if not, write to the Free Software
  16. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. #  USA
  18.  
  19. import sys, apt_pkg, os, fcntl, string, re
  20.  
  21. class OpProgress(object):
  22.     """ Abstract class to implement reporting on cache opening
  23.         Subclass this class to implement simple Operation progress reporting
  24.     """
  25.     def __init__(self):
  26.         pass
  27.     def update(self, percent):
  28.         pass
  29.     def done(self):
  30.         pass
  31.  
  32. class OpTextProgress(OpProgress):
  33.     """ A simple text based cache open reporting class """
  34.     def __init__(self):
  35.         OpProgress.__init__(self)
  36.     def update(self, percent):
  37.         sys.stdout.write("\r%s: %.2i  " % (self.subOp,percent))
  38.         sys.stdout.flush()
  39.     def done(self):
  40.         sys.stdout.write("\r%s: Done\n" % self.op)
  41.  
  42.  
  43.  
  44. class FetchProgress(object):
  45.     """ Report the download/fetching progress
  46.         Subclass this class to implement fetch progress reporting
  47.     """
  48.  
  49.     # download status constants
  50.     dlDone = 0
  51.     dlQueued = 1
  52.     dlFailed = 2
  53.     dlHit = 3
  54.     dlIgnored = 4
  55.     dlStatusStr = {dlDone : "Done",
  56.                    dlQueued : "Queued",
  57.                    dlFailed : "Failed",
  58.                    dlHit : "Hit",
  59.                    dlIgnored : "Ignored"}
  60.     
  61.     def __init__(self):
  62.         self.eta = 0.0
  63.         self.percent = 0.0
  64.         pass
  65.     
  66.     def start(self):
  67.         pass
  68.     
  69.     def stop(self):
  70.         pass
  71.     
  72.     def updateStatus(self, uri, descr, shortDescr, status):
  73.         pass
  74.  
  75.     def pulse(self):
  76.         """ called periodically (to update the gui), importend to
  77.             return True to continue or False to cancel
  78.         """
  79.         self.percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems)
  80.         if self.currentCPS > 0:
  81.             self.eta = (self.totalBytes-self.currentBytes)/float(self.currentCPS)
  82.         return True
  83.     def mediaChange(self, medium, drive):
  84.         pass
  85.  
  86. class TextFetchProgress(FetchProgress):
  87.     """ Ready to use progress object for terminal windows """
  88.     def __init__(self):
  89.         self.items = {}
  90.     def updateStatus(self, uri, descr, shortDescr, status):
  91.         if status != self.dlQueued:
  92.             print "\r%s %s" % (self.dlStatusStr[status], descr)
  93.         self.items[uri] = status
  94.     def pulse(self):
  95.         FetchProgress.pulse(self)
  96.         if self.currentCPS > 0:
  97.             s = "[%2.f%%] %sB/s %s" % (self.percent,
  98.                                        apt_pkg.SizeToStr(int(self.currentCPS)),
  99.                                        apt_pkg.TimeToStr(int(self.eta)))
  100.         else:
  101.             s = "%2.f%% [Working]" % (self.percent)
  102.         print "\r%s" % (s),
  103.         sys.stdout.flush()
  104.         return True
  105.     def stop(self):
  106.         print "\rDone downloading            " 
  107.     def mediaChange(self, medium, drive):
  108.         """ react to media change events """
  109.         res = True;
  110.         print "Media change: please insert the disc labeled \
  111.                '%s' in the drive '%s' and press enter" % (medium,drive)
  112.         s = sys.stdin.readline()
  113.         if(s == 'c' or s == 'C'):
  114.             res = false;
  115.         return res
  116.  
  117. class DumbInstallProgress(object):
  118.     """ Report the install progress
  119.         Subclass this class to implement install progress reporting
  120.     """
  121.     def __init__(self):
  122.         pass
  123.     def startUpdate(self):
  124.         pass
  125.     def run(self, pm):
  126.         return pm.DoInstall()
  127.     def finishUpdate(self):
  128.         pass
  129.     def updateInterface(self):
  130.         pass
  131.  
  132. class InstallProgress(DumbInstallProgress):
  133.     """ A InstallProgress that is pretty useful.
  134.         It supports the attributes 'percent' 'status' and callbacks
  135.         for the dpkg errors and conffiles and status changes 
  136.      """
  137.     def __init__(self):
  138.         DumbInstallProgress.__init__(self)
  139.         (read, write) = os.pipe()
  140.         self.writefd=write
  141.         self.statusfd = os.fdopen(read, "r")
  142.         fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL,os.O_NONBLOCK)
  143.         self.read = ""
  144.         self.percent = 0.0
  145.         self.status = ""
  146.     def error(self, pkg, errormsg):
  147.         " called when a error is detected during the install "
  148.         pass
  149.     def conffile(self,current,new):
  150.         " called when a conffile question from dpkg is detected "
  151.         pass
  152.     def statusChange(self, pkg, percent, status):
  153.     " called when the status changed "
  154.     pass
  155.     def updateInterface(self):
  156.         if self.statusfd != None:
  157.                 try:
  158.             while not self.read.endswith("\n"):
  159.                         self.read += os.read(self.statusfd.fileno(),1)
  160.                 except OSError, (errno,errstr):
  161.                     # resource temporarly unavailable is ignored
  162.                     if errno != 11:
  163.                         print errstr
  164.                 if self.read.endswith("\n"):
  165.                     s = self.read
  166.                     #print s
  167.                     (status, pkg, percent, status_str) = string.split(s, ":")
  168.                     #print "percent: %s %s" % (pkg, float(percent)/100.0)
  169.                     if status == "pmerror":
  170.                         self.error(pkg,status_str)
  171.                     elif status == "pmconffile":
  172.                         # we get a string like this:
  173.                         # 'current-conffile' 'new-conffile' useredited distedited
  174.                         match = re.compile("\s*\'(.*)\'\s*\'(.*)\'.*").match(status_str)
  175.                         if match:
  176.                             self.conffile(match.group(1), match.group(2))
  177.                     elif status == "pmstatus":
  178.                         if float(percent) != self.percent or \
  179.                            status_str != self.status:
  180.                             self.statusChange(pkg, float(percent), status_str.strip())
  181.                         self.percent = float(percent)
  182.                         self.status = string.strip(status_str)
  183.                     self.read = ""
  184.                     
  185.     def fork(self):
  186.         return os.fork()
  187.     def waitChild(self):
  188.         while True:
  189.             (pid, res) = os.waitpid(self.child_pid,os.WNOHANG)
  190.             if pid == self.child_pid:
  191.                 break
  192.             self.updateInterface()
  193.         return os.WEXITSTATUS(res)
  194.     def run(self, pm):
  195.         pid = self.fork()
  196.         if pid == 0:
  197.             # child
  198.             res = pm.DoInstall(self.writefd)
  199.             sys.exit(res)
  200.         self.child_pid = pid
  201.         res = self.waitChild()
  202.         return res
  203.  
  204. class CdromProgress:
  205.     """ Report the cdrom add progress
  206.         Subclass this class to implement cdrom add progress reporting
  207.     """
  208.     def __init__(self):
  209.         pass
  210.     def update(self, text, step):
  211.         """ update is called regularly so that the gui can be redrawn """
  212.         pass
  213.     def askCdromName(self):
  214.         pass
  215.     def changeCdrom(self):
  216.         pass
  217.  
  218. # module test code
  219. if __name__ == "__main__":
  220.     import apt_pkg
  221.     apt_pkg.init()
  222.     progress = OpTextProgress()
  223.     cache = apt_pkg.GetCache(progress)
  224.     depcache = apt_pkg.GetDepCache(cache)
  225.     depcache.Init(progress)
  226.  
  227.     fprogress = TextFetchProgress()
  228.     cache.Update(fprogress)
  229.