← Back to team overview

keryx team mailing list archive

[Merge] lp:~mac9416/keryx/devel into lp:keryx/devel

 

mac9416 has proposed merging lp:~mac9416/keryx/devel into lp:keryx/devel.

    Requested reviews:
    Keryx Admins (keryx-admins)

-- 
https://code.launchpad.net/~mac9416/keryx/devel/+merge/12835
Your team Keryx Development Team is subscribed to branch lp:keryx/devel.
=== modified file 'keryx.py'
--- keryx.py	2009-09-24 01:57:35 +0000
+++ keryx.py	2009-10-04 02:20:22 +0000
@@ -1,151 +1,244 @@
-#!/usr/bin/env python
-
-""" Keryx executable """
-
-__appname__   = 'keryx'
-__version__   = '1.0.0'
-__supports__  = '0'
-__author__    = 'Buran Ayuthia'
-
-import logging
-import os
-from sys import argv, exit
-from optparse import OptionParser, OptionGroup
-import libkeryx
-
-"""
-    * 1 apt-get commands     (For 1.0)
-          o 1.1 keryx update
-          o 1.3 keryx download some-package
-          o 1.5 keryx remove some-package
-          o 1.6 keryx apt-clean
-          o 1.7 keryx clean
-    * 2 apt-cache commands   (For 1.0)
-          o 2.3 keryx showpkg
-          o 2.4 keryx stats
-          o 2.5 keryx dump
-          o 2.7 keryx unmet
-          o 2.9 keryx search
-          o 2.10 keryx show
-          o 2.11 keryx depends
-          o 2.12 keryx pkgnames
-
-    * 1 apt-get commands     (For future)
-          o 1.2 keryx install some-package
-          o 1.4 keryx dist-upgrade
-          o 1.6 keryx apt-clean
-          o 1.7 keryx clean
-    * 2 apt-cache commands   (For future)
-          o 2.1 keryx add
-          o 2.2 keryx gencaches
-          o 2.6 keryx dumpavail
-          o 2.8 keryx check
-          o 2.13 keryx dotty
-"""
-
-FORMAT = '%(asctime)s %(levelname)-8s %(message)s'
-DATE = '%a, %d %b %Y %H:%M:%S'
-db_filename = os.path.join(os.path.dirname(__file__), 'keryx.db')
-
-class Keryx:
-    def __init__(self):
-        self.command = ''
-        self.project = ''
-        self.wx_gui = False
-
-    def __parse_command(self, command):
-        pass
-
-    def parse_options(self, args):
-        command_list = ['create', 'update', 'download', 'remove', \
-                        'clean', 'showpkg', 'dump', 'unmet', 'search', \
-                        'show', 'depends', 'pkgnames']
-        usage = 'usage: %prog project command [options]\n\n' \
-                'Actions (if none is specified, Keryx will enter ' \
-                'GUI mode):'
-        version = __version__
-        description = 'create   - Create a new project      ' \
-                      '                                     ' \
-                      'update   - Get updated package list from the ' \
-                      'Internet                                     ' \
-                      'download - Download selected packages for ' \
-                      'the project                               ' \
-                      'remove   - Removes a package from the download ' \
-                      'list                                           ' \
-                      'clean    - Removes all the packages from the ' \
-                      'download list                                ' \
-                      'showpkg  - Display general information for a ' \
-                      'package                                      ' \
-                      'search   - Display packages that match the ' \
-                      'search string                              ' \
-                      'show     - Display information about a ' \
-                      'particular package                     ' \
-                      'depends  - Display the dependencies for a ' \
-                      'particular package                        ' \
-                      'pkgnames - List the names of all the packages'
-        parser = OptionParser(usage, description=description, version=version)
-
-        download_group = OptionGroup(parser, 'Download')
-        download_group.add_option('-D', '--download', action='store_true', \
-            dest='download', \
-            help='Download only - do NOT install or unpack archives')
-        download_group.add_option('-s', '--simulate', action='store_true', 
-            dest='simulate', help='No-act. Perform ordering simulation')
-        download_group.add_option('-y', '--yes', action='store_true', \
-            dest='auto_yes', \
-            help='Assume Yes to all queries and do not prompt')
-        download_group.add_option('-u', '--show-upgrades', \
-            action='store_true', dest='upgrades', \
-            help='Show a list of upgraded packages as well')
-
-        parser.add_option_group(download_group)
-#       Not an option for 1.0
-#        parser.add_option('-f', '--force', action='store_true', \
-#            dest='force', \
-#            help='Attempt to continue if the integrity check fails')
-
-
-
-        (options, arguments) = parser.parse_args(args)
-
-        # Configure verbosity
-        #TODO: Fix it so basicConfig works
-        logging.basicConfig()
-
-        if len(arguments) == 1:
-            self.wx_gui = True
-
-        if len(arguments) < 3:
-            parser.error('Missing the project name or command')
-
-        if argv[2] not in command_list:
-            print('Unknown command \'%s\'' % args[2])
-            # The following is used to remove the None at the end
-            # of the parser.print_help data
-            help_msg = str(parser.print_help())
-            help_msg = help_msg.split('\n')
-            for index in range(len(help_msg) - 2):
-                print help_msg[index]
-            exit(1)
-
-        self.command = args[2]
-        self.project = args[1]
-
-    def execute(self):
-        if self.wx_gui:
-            print 'call GUI version'
-        else:
-            if self.command == 'create':
-                definition = libkeryx.get_definition(self.project, db_filename)
-                definition.Create()
-            if self.command == 'update':
-                definition = libkeryx.get_definition(self.project, db_filename)
-                definition.UpdateInternet()
-
-# keryx <project-name> <command(s)> <option(s)>
-if __name__ == '__main__':
-    keryx = Keryx()
-
-    no_errors = keryx.parse_options(argv)
-
-    keryx.execute()
+#!/usr/bin/env python
+
+""" Keryx executable """
+
+__appname__   = 'keryx'
+__version__   = '1.0.0'
+__supports__  = '0'
+__author__    = 'Buran Ayuthia'
+
+
+import logging
+import os
+from sys import argv, exit
+from optparse import OptionParser, OptionGroup
+import libkeryx
+
+
+"""
+    * 1 apt-get commands     (For 1.0)
+          o 1.1 keryx update
+          o 1.3 keryx download some-package
+          o 1.5 keryx remove some-package
+          o 1.6 keryx apt-clean
+          o 1.7 keryx clean
+    * 2 apt-cache commands   (For 1.0)
+          o 2.3 keryx showpkg
+          o 2.4 keryx stats
+          o 2.5 keryx dump
+          o 2.7 keryx unmet
+          o 2.9 keryx search
+          o 2.10 keryx show
+          o 2.11 keryx depends
+          o 2.12 keryx pkgnames
+
+    * 1 apt-get commands     (For future)
+          o 1.2 keryx install some-package
+          o 1.4 keryx dist-upgrade
+          o 1.6 keryx apt-clean
+          o 1.7 keryx clean
+    * 2 apt-cache commands   (For future)
+          o 2.1 keryx add
+          o 2.2 keryx gencaches
+          o 2.6 keryx dumpavail
+          o 2.8 keryx check
+          o 2.13 keryx dotty
+"""
+
+
+FORMAT = '%(asctime)s %(levelname)-8s %(message)s'
+DATE = '%a, %d %b %Y %H:%M:%S'
+db_filename = os.path.join(os.path.dirname(__file__), 'keryx.db')
+
+
+class Keryx:
+    def __init__(self):
+        self.command = ''
+        self.project = ''
+        self.wx_gui = False
+
+
+    def __parse_command(self, command):
+        pass
+
+
+    def parse_options(self, args):
+        command_list = ['create', 'update', 'download', 'remove', \
+                        'clean', 'showpkg', 'dump', 'unmet', 'search', \
+                        'show', 'depends', 'pkgnames']
+        usage = 'usage: %prog project command [options]\n\n' \
+                'Actions (if none is specified, Keryx will enter ' \
+                'GUI mode):'
+        version = __version__
+        description = 'create   - Create a new project      ' \
+                      '                                     ' \
+                      'update   - Get updated package list from the ' \
+                      'Internet                                     ' \
+                      'download - Download selected packages for ' \
+                      'the project                               ' \
+                      'remove   - Removes a package from the download ' \
+                      'list                                           ' \
+                      'clean    - Removes all the packages from the ' \
+                      'download list                                ' \
+                      'showpkg  - Display general information for a ' \
+                      'package                                      ' \
+                      'search   - Display packages that match the ' \
+                      'search string                              ' \
+                      'show     - Display information about a ' \
+                      'particular package                     ' \
+                      'depends  - Display the dependencies for a ' \
+                      'particular package                        ' \
+                      'pkgnames - List the names of all the packages'
+        parser = OptionParser(usage, description=description, version=version)  
+
+        download_group = OptionGroup(parser, 'Download')
+        download_group.add_option('-D', '--download', action='store_true', \
+            dest='download', \
+            help='Download only - do NOT install or unpack archives')
+        download_group.add_option('-s', '--simulate', action='store_true', 
+            dest='simulate', help='No-act. Perform ordering simulation')
+        download_group.add_option('-y', '--yes', action='store_true', \
+            dest='auto_yes', \
+            help='Assume Yes to all queries and do not prompt')
+        download_group.add_option('-u', '--show-upgrades', \
+            action='store_true', dest='upgrades', \
+            help='Show a list of upgraded packages as well')
+
+        parser.add_option_group(download_group)
+#       Not an option for 1.0
+#        parser.add_option('-f', '--force', action='store_true', \
+#            dest='force', \
+#            help='Attempt to continue if the integrity check fails')
+
+
+
+        (options, arguments) = parser.parse_args(args)
+
+        # Configure verbosity
+        #TODO: Fix it so basicConfig works
+        logging.basicConfig()
+        logging.root.setLevel(logging.DEBUG)
+
+        if len(arguments) == 1:
+            self.wx_gui = True
+            
+        if len(arguments) < 2:
+            parser.error('Missing the project name')
+        
+        if len(arguments) > 2:
+            self.command = None
+            if argv[2] not in command_list:
+                print('Unknown command \'%s\'' % args[2])
+                # The following is used to remove the None at the end
+                # of the parser.print_help data
+                help_msg = str(parser.print_help())
+                help_msg = help_msg.split('\n')
+                for index in range(len(help_msg) - 2):
+                    print help_msg[index]
+                exit(1)
+            else:
+                self.command = args[2]
+        
+        self.project = args[1]
+
+
+    def execute(self):
+        if self.wx_gui:
+            print 'call GUI version'
+            # If GUI fails, launch KeryxCLI
+            cli = KeryxCLI(self.project)
+            cli.main()
+        else:
+            if not self.command:
+                cli = KeryxCLI(self.project)
+                cli.main()
+            if self.command == 'create':
+                definition = libkeryx.get_definition(self.project, db_filename)
+                definition.Create()
+            if self.command == 'update':
+                definition = libkeryx.get_definition(self.project, db_filename)
+                definition.Update()
+
+
+class KeryxCLI():
+    """Keryx Interactive CLI"""
+    help = """
+Commands:
+open <project name>
+create - Creates the current project into database
+update - Updates the current project
+"""
+    
+    def __init__(self, name):
+        """Set project for CLI usage"""
+        self.set_project(name)
+        
+        
+    def set_project(self, name):
+        """Sets project to name"""
+        self.name = name
+        self.project = libkeryx.get_definition(name, db_filename)
+        # Check self.project.Verify() and notify user if project is not created
+
+
+    def main(self):
+        """Main loop for Keryx interactive CLI"""
+        #Dictionary of commands and there function call second parameter
+        #       boolean is true if the command takes arguments
+        commands = {"create" : ["Create", False],
+                    "update" : ["Update", False],
+                    "update-local" : ["UpdateLocal", False], 
+                    "upgrade" : ["Upgrade", False], 
+                    #"download" : ["Download", True],
+                    #"remove" : ["Remove",  True], 
+                    #"apt-clean" : ["AptClean", False],
+                    #"clean" : ["Clean", False], 
+                    #"showpkg" : ["ShowPkg", False], 
+                    #"stats" : ["Stats", False], 
+                    #"dump" : ["Dump", False], 
+                    #"unmet" : ["Unmet", True], 
+                    #"search" : ["Search", True], 
+                    #"show" : ["Show", True], 
+                    #"depends" : ["Depends", True], 
+                    #"pkgnames" : ["PkgNames", False]
+                    }
+        
+        if os.system("clear") != 0:
+            os.system("cls")
+        print "\nKeryx %s Interactive Command Line Interface\n" % __version__
+        
+        input = [""]
+        while input[0] != "exit":
+            prompt = "%s:%s>" % (__appname__, self.name)
+            input = raw_input(prompt).strip().split()
+            if input:
+                input = [x.lower() for x in input]
+                if commands.has_key(input[0]):
+                    x = getattr(self.project, commands[input[0]][0])
+                    if commands[input[0]][1]:
+                        x(input[1:])
+                    else:
+                        x()
+                else:
+                    if input[0] == "help":
+                        print self.help
+                    elif input[0] == "exit":
+                        pass
+#                if command[0] == "open":
+#                    if len(command) > 1:
+#                        name = command[1].strip()
+#                        self.set_project(name)
+#                    else:
+#                        print self.help
+                    else:
+                        print "Command not found. Type 'help' for details."
+            else:
+                # No command input
+                command = [""]
+                        
+
+# keryx <project-name> <command(s)> <option(s)>
+if __name__ == '__main__':
+    keryx = Keryx()
+    no_errors = keryx.parse_options(argv)
+    keryx.execute()

=== modified file 'libkeryx/__init__.py'
--- libkeryx/__init__.py	2009-09-24 01:57:35 +0000
+++ libkeryx/__init__.py	2009-10-04 02:20:22 +0000
@@ -88,20 +88,19 @@
         pass
 
 
+    def Exists(self):
+        """Checks project has been created"""
+        found = self.session.query(Project).filter(Project.name==self.project).all()
+        return found
+
+
     def Create(self):
         """Create a new Keryx database"""
-        # Query to see if project exists already
-        found = self.session.query(Project).filter(Project.name==self.project).all()
+        if self.Exists():
+            raise AttributeError, "Project already exists"
         
-        if found:
-            logging.error("Project already exists")
-            return False
-
         logging.info("Creating project...")
-        #try:
         self.OnCreate()
-        #except Exception, e:
-        #    logging.error(e)
 
 
     def OnCreate(self):
@@ -109,9 +108,68 @@
         pass
 
 
-    def UpdateInternet(self):
-        """Should be overridden in definition"""
-        pass
+    def Update(self):
+        """Update project from the latest repositories"""
+        if not self.Exists():
+            raise AttributeError, "Project does not exist"
+        self.OnUpdate()
+        
+        
+    def OnUpdate(self):
+        """Should be overridden in definition"""
+        pass
+
+
+    def UpdateLocal(self):
+        """Update project from the local cache"""
+        if not self.Exists():
+            raise AttributeError, "Project does not exist"
+        self.OnUpdateLocal()
+        
+        
+    def OnUpdateLocal(self):
+        """Should be overridden in definition"""
+        pass
+
+
+    def Upgrade(self):
+        """Download out-of-date packages"""
+        if not self.Exists():
+            raise AttributeError, "Project does not exist"
+        self.OnUpgrade()
+        
+        
+    def OnUpgrade(self):
+        """Should be overridden in definition"""
+        pass
+        
+        
+    def Download(self, packages):
+        """Download a list of packages"""
+        if not self.Exists():
+            raise AttributeError, "Project does not exist"
+        self.OnDownload(packages)
+        
+        
+    def OnDownload(self, packages):
+        """Should be overridden in definition"""
+        pass
+
+
+#    * 1 apt-get commands     (For 1.0)
+#          o 1.3 keryx download some-package
+#          o 1.5 keryx remove some-package
+#          o 1.6 keryx apt-clean
+#          o 1.7 keryx clean
+#    * 2 apt-cache commands   (For 1.0)
+#          o 2.3 keryx showpkg
+#          o 2.4 keryx stats
+#          o 2.5 keryx dump
+#          o 2.7 keryx unmet
+#          o 2.9 keryx search
+#          o 2.10 keryx show
+#          o 2.11 keryx depends
+#          o 2.12 keryx pkgnames
 
 
 # These are the mapper classes to help access the database easier.
@@ -122,12 +180,12 @@
     __tablename__ = "projects"
     
     id = Column(Integer, primary_key=True)
-    name = Column(String)
+    name = Column(String, unique=True)
     architecture = Column(String)
     hostname = Column(String)
     definition = Column(String)
     version = Column(String)
-  
+
   
     def __init__(self, name, architecture, hostname, definition, version):
         self.name = name

=== modified file 'libkeryx/definitions/dpkg/__init__.py'
--- libkeryx/definitions/dpkg/__init__.py	2009-09-24 01:57:35 +0000
+++ libkeryx/definitions/dpkg/__init__.py	2009-10-04 02:20:22 +0000
@@ -61,6 +61,8 @@
         except:
             self.project_entry = None
 
+        self.apt_client = AptRepoClient.AptRepoClient()
+        # TODO: Load from database by default
 
     def SetDBEntry(self):
         """Set the Project entry"""
@@ -97,7 +99,7 @@
             raise OSError, "Aptitude is not installed on this machine."
 
 
-    def UpdateInternet(self):
+    def OnUpdate(self):
         """Update package list from the internet"""
         # Get project's repo relationships
         rels = self.session.query(Relation). \
@@ -109,12 +111,106 @@
                  filter(Repo.id==i.target_id).one().items()) for i in rels]
 
         # Feed repos to hungry little minideblib
-        r = AptRepoClient.AptRepoClient(repos, [self.project_entry.architecture])
-        r.update()
-
-        # TODO: Store packages in to database
-        
-        
+        ########################################
+        # Set architecture
+        self.apt_client._arch = [self.project_entry.architecture]
+        self.apt_client.load_repos(repos)
+        
+        print "%i available packages" % len(self.apt_client.get_available_binaries())
+        
+        # TODO: Clear packages table
+        
+        # Add packages to database
+#        for val in self.apt_client.get_available_binaries():
+#            versions = self.apt_client.get_available_binary_versions(val)
+            
+#            for ver in versions:
+#                pkg = self.apt_client.get_binary_name_version(val, ver[1])
+                
+#                # List of available versions for this package
+#                for p in pkg:
+                    
+                    # IS THIS NECESSARY IF WE CLEAR THE DB??
+                    # Check to see if it exists in the database already
+                    # Use a try in case there are no packages
+                    #try:
+                    #    exists = self.session.query(Package). \
+                    #             filter(Package.name==val). \
+                    #             filter(Package.version==ver).all()
+                    #except:
+                    #    exists = []
+                    #print len(exists)
+                    
+                    # Store packages in to database if it does not already exist
+#                    {'origin': 'Ubuntu', 
+#                     'sha1': '40450d7bf6e924c26adeea8ac751442aaf43a3f1', 
+#                     'maintainer': 'Ubuntu MOTU Developers <ubuntu-motu@xxxxxxxxxxxxxxxx>', 
+#                     'description': ["Identify what's using up virtual memory", 'Lists all the processes, executables, and shared libraries', "that are using up virtual memory. It's helpful to see how the", "shared memory is used and which 'old' libs are loaded."], 
+#                     'package': 'memstat', 
+#                     'section': 'universe/admin', 
+#                     'md5sum': 'a575c7560b8a2195067d578551085077', 
+#                     'depends': 'libc6 (>= 2.4)', 
+#                     'filename': 'pool/universe/m/memstat/memstat_0.5_i386.deb', 
+#                     'priority': 'optional', 
+#                     'sha256': 'cc8f164b907a9554708bfb6f5758eef681532ab177e0b6fdfcc6427b97f9d95f', 
+#                     'installed-size': '76', 
+#                     'version': '0.5', 
+#                     'bugs': 'https://bugs.launchpad.net/ubuntu/+filebug', 
+#                     'architecture': 'i386', 
+#                     'size': '10504', 
+#                     'original-maintainer': 'Michael Meskes <meskes@xxxxxxxxxx>'}
+
+                    # TODO: Test for type being a list, if so, " ".join()
+                    # Use " ".join() when multiple lines might exist
+#                    package = Package(unicode(val), unicode(ver[1]), 
+#                        unicode(p.get("section","")),
+#                        unicode(p.get("installed-size","")), 
+#                        unicode(" ".join(p.get("maintainer","")), errors='ignore'),
+#                        unicode(" ".join(p.get("original-maintainer","")), errors='ignore'), 
+#                        unicode(p.get("architecture",""), errors='ignore'),
+#                        unicode(p.get("replaces",""), errors='ignore'),
+#                        )
+#                    self.session.add(package)
+
+    def OnUpdateLocal(self):
+        """Update package list from the local cache"""
+        # Get project's repo relationships
+        rels = self.session.query(Relation). \
+                filter(Relation.project_id==self.project_entry.id). \
+                filter(Relation.type=="repo").all()
+        
+        # Get items out of each repo
+        repos = [" ".join(self.session.query(Repo). \
+                    filter(Repo.id==i.target_id).one().items()) for i in rels]
+
+        # Feed repos to hungry little minideblib
+        ########################################
+        # Set architecture
+        self.apt_client._arch = [self.project_entry.architecture]
+        self.apt_client.load_local("/var/lib/apt/lists", repos)
+        
+        print "%i available packages" % len(self.apt_client.get_available_binaries())
+
+
+    def OnUpgrade(self):
+        """Upgrade out-of-date packages"""
+        self.apt_client.get_available_binaries()
+        status = self.session.query(Status). \
+                            filter(Project.name==self.project).all()
+        upgrade = []
+        for pkg in status:
+            best_ver = self.apt_client.get_best_binary_version(pkg.name)[1]
+            if not best_ver == pkg.version:
+                upgrade.append(pkg.name)
+        print "%i upgradeable packages" % (len(upgrade))
+        self.Download(upgrade)
+
+                
+    def OnDownload(self, packages):
+        """Download packages and their dependencies"""
+        print "DOWNLOAD DEPENDENCIES FOR: "
+        print packages
+            
         
 ####################
 # Helper Functions #

=== modified file 'libkeryx/definitions/dpkg/database.py'
--- libkeryx/definitions/dpkg/database.py	2009-09-24 02:06:24 +0000
+++ libkeryx/definitions/dpkg/database.py	2009-10-04 02:20:22 +0000
@@ -79,8 +79,8 @@
     __tablename__ = "packages"
     
     id = Column(Integer, primary_key=True)
+    name = Column(Unicode)
     version = Column(Unicode)
-    name = Column(Unicode)
     section = Column(Unicode)
     installed_size = Column(Unicode)
     maintainer = Column(Unicode)
@@ -94,7 +94,8 @@
     conflicts = Column(Unicode)
     filename = Column(Unicode)
     size = Column(Unicode)
-    md5sumsha256 = Column(Unicode)
+    md5sum = Column(Unicode)
+    sha256 = Column(Unicode)
     shortdesc = Column(Unicode)
     longdesc = Column(Unicode)
     homepage = Column(Unicode)
@@ -105,9 +106,9 @@
 
     def __init__(self, name, version, section, \
                  installed_size, maintainer, original_maintainer, \
-                 architecture, replaces, provides, depends, recommends, \
-                 suggests, conflicts, filename, size, md5sum, sha256, \
-                 shortdesc, longdesc, homepage, bugs, origin, task):
+                 architecture, replaces):#, replaces, provides, depends, recommends, \
+                 #suggests, conflicts, filename, size, md5sum, sha256, \
+                 #shortdesc, longdesc, homepage, bugs, origin, task):
         self.name = name
         self.version = version
         self.section = section
@@ -116,30 +117,36 @@
         self.original_maintainer = original_maintainer
         self.architecture = architecture
         self.replaces = replaces
-        self.provides = provides
-        self.depends = depends
-        self.recommends = recommends
-        self.suggests = suggests
-        self.conflicts = conflicts
-        self.filename = filename
-        self.size = size
-        self.md5sum = md5sum
-        self.sha256 = sha256
-        self.shortdesc = shortdesc
-        self.longdesc = longdesc
-        self.homepage = homepage
-        self.bugs = bugs
-        self.origin = origin
-        self.task = task
-
+        #self.provides = provides
+        #self.depends = depends
+        #self.recommends = recommends
+        #self.suggests = suggests
+        #self.conflicts = conflicts
+        #self.filename = filename
+        #self.size = size
+        #self.md5sum = md5sum
+        #self.sha256 = sha256
+        #self.shortdesc = shortdesc
+        #self.longdesc = longdesc
+        #self.homepage = homepage
+        #self.bugs = bugs
+        #self.origin = origin
+        #self.task = task
 
     def __repr__(self):
-        return '<Package(\'%s, %s, %s ,%s, %s, %s, %s, %s, %s, %s, %s, \
-                %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\')>' % \
-                (self.id, self.name, self.version, self.section, \
-                self.installed_size, self.maintainer, \
-                self.original_maintainer, self.architecture, self.replaces, \
-                 self.provides, self.depends, self.recommends, self.suggests, \
-                 self.conflicts, self.filename, self.size, self.md5sum, \
-                 self.sha256, self.shortdesc, self.longdesc, self.homepage, \
-                 self.bugs, self.origin, self.task)
\ No newline at end of file
+        return "<Package('%s','%s','%s','%s','%s','%s','%s','%s','%s')>" % \
+            (self.id, self.name, self.version, self.section,
+             self.installed_size, self.maintainer, self.original_maintainer,
+             self.architecture, self.replaces,
+            )
+#    def __repr__(self):
+#        return "<Package('%s','%s','%s','%s','%s','%s','%s','%s'" \
+#               ",'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s'" \
+#               ",'%s','%s','%s','%s','%s')>" % \
+#                (self.id, self.name, self.version, self.section,
+#                 self.installed_size, self.maintainer, self.original_maintainer,
+#                 self.architecture, self.replaces, self.provides, self.depends,
+#                 self.recommends, self.suggests, self.conflicts, self.filename,
+#                 self.size, self.md5sum, self.sha256, self.shortdesc, 
+#                 self.longdesc, self.homepage, self.bugs, self.origin, 
+#                 self.task)
\ No newline at end of file

=== modified file 'libkeryx/urlgrabber/grabber.py'
--- libkeryx/urlgrabber/grabber.py	2009-09-08 03:34:12 +0000
+++ libkeryx/urlgrabber/grabber.py	2009-10-04 02:20:22 +0000
@@ -1347,7 +1347,7 @@
             self._amount_read = self._amount_read + newsize
             if self.opts.progress_obj:
                 self.opts.progress_obj.update(self._amount_read)
-
+        self.opts.progress_obj.end(self._amount_read)
         self._rbuf = string.join(buf, '')
         return
 


Follow ups