Merged from trunk 7353:7371
authorFabian Groffen <grobian@gentoo.org>
Mon, 23 Jul 2007 17:18:12 +0000 (17:18 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 23 Jul 2007 17:18:12 +0000 (17:18 -0000)
   +------------------------------------------------------------------------+
   | 7354      | Run pychecker over everything, fix obvious thing slike     |
   | WarnerBro | modules not in use, variables not being used, or global    |
   |           | exceptions not being deleted. Also fix imports for style   |
   |           | (1 per line)                                               |
   |-----------+------------------------------------------------------------|
   | 7355      | remove unused vars from xpak, fix bug in compose. Also fix |
   | WarnerBro | tests for portage sets, fix misnamed variable.             |
   |-----------+------------------------------------------------------------|
   | 7356      | Add notes about import statements (clarity) and fix        |
   | WarnerBro | spelling error in release-notes                            |
   |-----------+------------------------------------------------------------|
   | 7357      | Fix spacing issues, imports                                |
   | WarnerBro |                                                            |
   |-----------+------------------------------------------------------------|
   | 7358      | For bug #184774, put lha's -q option last since otherwise  |
   | zmedico   | the option parser now requires level 0, 1, or 2 to be      |
   |           | specified.                                                 |
   |-----------+------------------------------------------------------------|
   | 7360      | add test for CommandOutputSet                              |
   | WarnerBro |                                                            |
   |-----------+------------------------------------------------------------|
   | 7361      | add docstring, fix up imports (style), add keyword         |
   | WarnerBro | expansion                                                  |
   |-----------+------------------------------------------------------------|
   | 7362      | fix missing import, default value for value in case we try |
   | WarnerBro | to .join on a variable that hasn't been assigned to yet    |
   |-----------+------------------------------------------------------------|
   | 7363      | Fix hardcoded /usr/bin/echo to use                         |
   | zmedico   | portage.process.find_binary().                             |
   |-----------+------------------------------------------------------------|
   | 7364      | fix spacing, comments, default args                        |
   | WarnerBro |                                                            |
   |-----------+------------------------------------------------------------|
   | 7365      | Move common file functionality into a FileLoader class and |
   | WarnerBro | delegate parsing to subclasses via a lineParser func, no   |
   |           | idea how this will work performance wise. Fix errors in    |
   |           | parser (blank lines are not errors ;))                     |
   |-----------+------------------------------------------------------------|
   | 7366      | Move classes out of __init__.py, they do not belong there. |
   | WarnerBro | Fix import style, and import statements broken by class    |
   |           | moves.                                                     |
   |-----------+------------------------------------------------------------|
   | 7367      | Fix imports for style, deprecate grab*, what is            |
   | WarnerBro | foo.metadata and what does it contain                      |
   |-----------+------------------------------------------------------------|
   | 7368      | Validator should be a function, not a class, fix           |
   | WarnerBro | spacing/tab issues. Fix parsing errors for                 |
   |           | KeyValuePairLoader. Add a GenericFileLoader class that     |
   |           | uses more than 1 loader in a vain attempt to figure out    |
   |           | what kind of file it is. Fix inheritance by renaming       |
   |           | UserConfigKlass                                            |
   |-----------+------------------------------------------------------------|
   | 7369      | Fix imports for style, slight optimization for grab*       |
   | WarnerBro | function, doc fixups.                                      |
   |-----------+------------------------------------------------------------|
   | 7370      | fix broken import                                          |
   | WarnerBro |                                                            |
   |-----------+------------------------------------------------------------|
   | 7371      | add more tests for keyvaluepairloader (it had a bug        |
   | WarnerBro | previously) and fix up other misc tests                    |
   +------------------------------------------------------------------------+

svn path=/main/branches/prefix/; revision=7372

27 files changed:
DEVELOPING
RELEASE-NOTES
bin/ebuild.sh
pym/emerge/__init__.py
pym/portage/checksum.py
pym/portage/env/config.py
pym/portage/env/loaders.py
pym/portage/env/validators.py [new file with mode: 0644]
pym/portage/getbinpkg.py
pym/portage/glsa.py
pym/portage/news.py
pym/portage/output.py
pym/portage/process.py
pym/portage/sets/__init__.py
pym/portage/sets/dbapi.py
pym/portage/sets/files.py
pym/portage/sets/profiles.py
pym/portage/sets/security.py
pym/portage/sets/shell.py
pym/portage/tests/__init__.py
pym/portage/tests/env/config/test_PackageMaskFile.py
pym/portage/tests/env/config/test_PortageModulesFile.py
pym/portage/tests/sets/__init__.py [new file with mode: 0644]
pym/portage/tests/sets/shell/__init__.py [new file with mode: 0644]
pym/portage/tests/sets/shell/testShell.py [new file with mode: 0644]
pym/portage/util.py
pym/portage/xpak.py

index 01eb9bd42695b28f375c29eeac47991dae2083c4..725f1ae1eabbe5d3e28f8f4268ce77bb1cbc9cd2 100644 (file)
@@ -65,3 +65,40 @@ except KeyError:
        dict[foo] = default_value
 
 The get call is nicer (compact) and faster (try,except are slow).
+
+Imports
+-------
+
+Import things one per line
+
+YES:
+  import os
+  import time
+  import sys
+
+NO:
+  import os,sys,time
+
+When importing from a module, you may import more than 1 thing at a time.
+
+YES:
+  from portage.module import foo, bar, baz
+
+Multiline imports are ok (for now :))
+
+Try to group system and package imports separately.
+
+YES:
+  import os
+  import sys
+  import time
+
+  from portage.locks import lockfile
+  from portage.versions import vercmp
+
+NO:
+  import os
+  import portage
+  import portage.util
+  import time
+  import sys
index f6989a14db878ab86c1c67290b6e1084f2974e63..ff3370ef2408414c6df208075aa0ca678ba37cd3 100644 (file)
@@ -16,7 +16,7 @@ portage-2.2
   used in ACCEPT_KEYWORDS.
   For packages that don't specify any other KEYWORDS you can use the new ** token
   as documented in portage(5) to disable KEYWORDS filtering completely.
-* Portage now warns if a ebild repository does not have a name, as several new
+* Portage now warns if an ebuild repository does not have a name, as several new
   features in 2.2 make use of or require named repositories. The repository name
   is stored in profiles/repo_name in each repository.
 
index ec930e4a648f12f4eb70f6d7afcaebc638c85026..483755aa1528c1a74ad97936206e8a707088b3ee 100755 (executable)
@@ -378,7 +378,7 @@ unpack() {
                                unrar x -idq -o+ "${srcdir}/${x}" || die "$myfail"
                                ;;
                        LHa|LHA|lha|lzh)
-                               lha xqf "${srcdir}/${x}" || die "$myfail"
+                               lha xfq "${srcdir}/${x}" || die "$myfail"
                                ;;
                        deb)
                                # Unpacking .deb archives can not always be done with
index 6ed424f503c4dbb4d51cd5a0fb7f89b9aed2fcfa..e746ce1308e245b3544b5c830bd6264f1cbba093 100644 (file)
@@ -53,7 +53,7 @@ from portage.const import EPREFIX
 from portage.data import secpass
 from portage.util import normalize_path as normpath
 from portage.util import writemsg
-from portage.sets import InternalPackageSet
+from portage.sets.dbapi import InternalPackageSet
 from portage.sets.profiles import PackagesSystemSet as SystemSet
 from portage.sets.files import WorldSet
 
index 4b3e8271254d0f697650177720a0946bb6d048b6..3e9bb8a688cb5c417c95eecc2fdff43ebb2eb8b4 100644 (file)
@@ -30,14 +30,14 @@ def _generate_hash_function(hashtype, hashobject, origin="unknown"):
                blocksize = HASHING_BLOCKSIZE
                data = f.read(blocksize)
                size = 0L
-               sum = hashobject()
+               checksum = hashobject()
                while data:
-                       sum.update(data)
+                       checksum.update(data)
                        size = size + len(data)
                        data = f.read(blocksize)
                f.close()
 
-               return (sum.hexdigest(), size)
+               return (checksum.hexdigest(), size)
        hashfunc_map[hashtype] = pyhash
        hashorigin_map[hashtype] = origin
        return pyhash
index a354dcf7de6b66198db5469c7f7419600b8e360e..c990d9f0effe3b80661ac6ecc7bd909415e48495 100644 (file)
@@ -6,19 +6,18 @@
 from UserDict import UserDict
 from portage.env.loaders import KeyListFileLoader, KeyValuePairFileLoader, ItemFileLoader
 
-class UserConfigKlass(UserDict,object):
+class ConfigLoaderKlass(UserDict, object):
        """
        A base class stub for things to inherit from.
        Users may want a non-file backend.
        """
        
-       data = {}
-       
        def __init__(self, loader):
                """
                @param loader: A class that has a load() that returns two dicts
                        the first being a data dict, the second being a dict of errors.
                """
+               UserDict.__init__(self)
                self._loader = loader
 
        def load(self):
@@ -33,9 +32,32 @@ class UserConfigKlass(UserDict,object):
        def __iter__(self):
                return iter(self.data)
 
-class PackageKeywordsFile(UserConfigKlass):
+class GenericFile(UserDict):
+       """
+       Inherits from ConfigLoaderKlass, attempts to use all known loaders
+       until it gets <something> in data.  This is probably really slow but is
+       helpful when you really have no idea what you are loading (hint hint the file
+       should perhaps declare  what type it is? ;)
+       """
+       
+       loaders = [KeyListFileLoader, KeyValuePairFileLoader, ItemFileLoader]
+       
+       def __init__(self, filename):
+               UserDict.__init__(self)
+               self.filename = filename
+       
+       def load(self):
+               for loader in self.loaders:
+                       l = loader(self.filename, None)
+                       data, errors = l.load()
+                       if len(data) and not len(errors):
+                               (self.data, self.errors) = (data, errors)
+                               return
+
+
+class PackageKeywordsFile(ConfigLoaderKlass):
        """
-       Inherits from UserConfigKlass; implements a file-based backend.
+       Inherits from ConfigLoaderKlass; implements a file-based backend.
        """
 
        default_loader = KeyListFileLoader
@@ -44,7 +66,7 @@ class PackageKeywordsFile(UserConfigKlass):
                super(PackageKeywordsFile, self).__init__(
                        self.default_loader(filename, validator=None))
        
-class PackageUseFile(UserConfigKlass):
+class PackageUseFile(ConfigLoaderKlass):
        """
        Inherits from PackageUse; implements a file-based backend.  Doesn't handle recursion yet.
        """
@@ -54,7 +76,7 @@ class PackageUseFile(UserConfigKlass):
                super(PackageUseFile, self).__init__(
                        self.default_loader(filename, validator=None))
        
-class PackageMaskFile(UserConfigKlass):
+class PackageMaskFile(ConfigLoaderKlass):
        """
        A class that implements a file-based package.mask
        
@@ -72,7 +94,7 @@ class PackageMaskFile(UserConfigKlass):
                super(PackageMaskFile, self).__init__(
                        self.default_loader(filename, validator=None))
 
-class PortageModulesFile(UserConfigKlass):
+class PortageModulesFile(ConfigLoaderKlass):
        """
        File Class for /etc/portage/modules
        """
index 3a2d7c2577d2a93d8d696d5fd7e06974d4063a40..ae9579a86b0d6b4c74694b6bf5e5d3323b68f14a 100644 (file)
@@ -15,17 +15,19 @@ class LoaderError(Exception):
                @type error_msg: String
                """
 
-               self.resource
+               self.resource = resource
+               self.error_msg = error_msg
        
        def __str__(self):
                return "Failed while loading resource: %s, error was: %s" % (
-                       resource, error_msg)
+                       self.resource, self.error_msg)
+
 
 def RecursiveFileLoader(filename):
        """
-       If filename is of type file, return [filename]
-       else if filename is of type directory, return an array
-       full of files in that directory to process.
+       If filename is of type file, return a generate that yields filename
+       else if filename is of type directory, return a generator that fields
+       files in that directory.
        
        Ignore files beginning with . or ending in ~.
        Prune CVS directories.
@@ -36,36 +38,85 @@ def RecursiveFileLoader(filename):
        """
 
        if os.path.isdir(filename):
-               for root, dirs, files in os.walk(self.fname):
+               for root, dirs, files in os.walk(filename):
                        if 'CVS' in dirs:
                                dirs.remove('CVS')
-                       files = filter(files,startswith('.'))
-                       files = filter(files,endswith('~'))
-                       for file in files:
-                               yield file
+                       files = filter(files, str.startswith('.'))
+                       files = filter(files, str.endswith('~'))
+                       for f in files:
+                               yield f
        else:
                yield filename
 
+
 class DataLoader(object):
 
-       def __init__(self, validator=None):
+       def __init__(self, validator):
                f = validator
                if f is None:
                        # if they pass in no validator, just make a fake one
                        # that always returns true
-                       class AlwaysTrue(object):
-                               def validate(self, key):
-                                       return True
-                       f = AlwaysTrue()
-               self._validator = f
+                       def validate(key):
+                               return True
+                       f = validate
+               self._validate = f
 
        def load(self):
                """
                Function to do the actual work of a Loader
                """
-               pass
+               raise NotImplementedError("Please override in a subclass")
+
+
+class FileLoader(DataLoader):
+       """ Class to access data in files """
+
+       def __init__(self, filename, validator):
+               """
+                       Args:
+                               filename : Name of file or directory to open
+                               validator : class with validate() method to validate data.
+               """
+               DataLoader.__init__(self, validator)
+               self.fname = filename
+
+       def load(self):
+               """
+               Return the {source: {key: value}} pairs from a file
+               Return the {source: [list of errors] from a load
+
+               @param recursive: If set and self.fname is a directory; 
+                       load all files in self.fname
+               @type: Boolean
+               @rtype: tuple
+               @returns:
+               Returns (data,errors), both may be empty dicts or populated.
+               """
+               data = {}
+               errors = {}
+               # I tried to save a nasty lookup on lineparser by doing the lookup
+               # once, which may be expensive due to digging in child classes.
+               func = self.lineParser
+               for fn in RecursiveFileLoader(self.fname):
+                       f = open(fn, 'rb')
+                       for line_num, line in enumerate(f):
+                               func(line, line_num, data, errors)
+               return (data, errors)
+
+       def lineParser(self, line, line_num, data, errors):
+               """ This function parses 1 line at a time
+                       Args:
+                               line: a string representing 1 line of a file
+                               line_num: an integer representing what line we are processing
+                               data: a dict that contains the data we have extracted from the file
+                                     already
+                               errors: a dict representing parse errors.
+                       Returns:
+                               Nothing (None).  Writes to data and errors
+               """
+               raise NotImplementedError("Please over-ride this in a child class")
 
-class ItemFileLoader(DataLoader):
+class ItemFileLoader(FileLoader):
        """
        Class to load data from a file full of items one per line
        
@@ -78,36 +129,31 @@ class ItemFileLoader(DataLoader):
        Note that due to the data store being a dict, duplicates
        are removed.
        """
-       
-       _recursive = False
 
        def __init__(self, filename, validator):
-               DataLoader.__init__(self, validator)
-               self.fname = filename
+               FileLoader.__init__(self, filename, validator)
        
-       def load(self):
-               data = {}
-               errors = {}
-               for file in RecursiveFileLoader(self.fname):
-                       f = open(file, 'rb')
-                       for line_num, line in enumerate(f):
-                               if line.startswith('#'):
-                                       continue
-                               split = line.strip().split()
-                               if not len(split):
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Malformed data at line: %s, data: %s"
-                                       % (line_num + 1, split))
-                               key = split[0]
-                               if not self._validator.validate(key):
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Validation failed at line: %s, data %s"
-                                       % (line_num + 1, split))
-                                       continue
-                               data[key] = None
-               return (data, errors)
-
-class KeyListFileLoader(DataLoader):
+       def lineParser(self, line, line_num, data, errors):
+               line = line.strip()
+               if line.startswith('#'): # Skip commented lines
+                       return
+               if not len(line): # skip empty lines
+                       return
+               split = line.split()
+               if not len(split):
+                       errors.setdefault(self.fname, []).append(
+                               "Malformed data at line: %s, data: %s"
+                               % (line_num + 1, line))
+                       return
+               key = split[0]
+               if not self._validate(key):
+                       errors.setdefault(self.fname, []).append(
+                               "Validation failed at line: %s, data %s"
+                               % (line_num + 1, key))
+                       return
+               data[key] = None
+
+class KeyListFileLoader(FileLoader):
        """
        Class to load data from a file full of key [list] tuples
        
@@ -116,40 +162,36 @@ class KeyListFileLoader(DataLoader):
        {'key':['foo1','foo2','foo3']}
        """
 
-       _recursive = False
-
        def __init__(self, filename, validator):
-               DataLoader.__init__(self, validator)
-               self.fname = filename
-
-       def load(self):
-               data = {}
-               errors = {}
-               for file in RecursiveFileLoader(self.fname):
-                       f = open(file, 'rb')
-                       for line_num, line in enumerate(f):
-                               if line.startswith('#'):
-                                       continue
-                               split = line.strip().split()
-                               if len(split) < 2:
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Malformed data at line: %s, data: %s"
-                                       % (line_num + 1, split))
-                                       continue
-                               key = split[0]
-                               value = split[1:]
-                               if not self._validator.validate(key):
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Validation failed at line: %s, data %s"
-                                       % (line_num + 1, split))
-                                       continue
-                               if key in data:
-                                       data[key].append(value)
-                               else:
-                                       data[key] = value
-               return (data, errors)
-
-class KeyValuePairFileLoader(DataLoader):
+               FileLoader.__init__(self, filename, validator)
+
+
+       def lineParser(self, line, line_num, data, errors):
+               line = line.strip()
+               if line.startswith('#'): # Skip commented lines
+                       return
+               if not len(line): # skip empty lines
+                       return
+               split = line.split()
+               if len(split) < 2:
+                       errors.setdefault(self.fname, []).append(
+                               "Malformed data at line: %s, data: %s"
+                               % (line_num + 1, line))
+                       return
+               key = split[0]
+               value = split[1:]
+               if not self._validate(key):
+                       errors.setdefault(self.fname, []).append(
+                               "Validation failed at line: %s, data %s"
+                               % (line_num + 1, key))
+                       return
+               if key in data:
+                       data[key].append(value)
+               else:
+                       data[key] = value
+
+
+class KeyValuePairFileLoader(FileLoader):
        """
        Class to load data from a file full of key=value pairs
        
@@ -160,47 +202,36 @@ class KeyValuePairFileLoader(DataLoader):
         'foo':'bar'}
        """
 
-       _recursive = False
-
        def __init__(self, filename, validator):
-               DataLoader.__init__(self, validator)
-               self.fname = filename
+               FileLoader.__init__(self, filename, validator)
+
+
+       def lineParser(self, line, line_num, data, errors):
+               line = line.strip()
+               if line.startswith('#'): # skip commented lines
+                       return
+               if not len(line): # skip empty lines
+                       return
+               split = line.split('=')
+               if len(split) < 2:
+                       errors.setdefault(self.fname, []).append(
+                               "Malformed data at line: %s, data %s"
+                               % (line_num + 1, line))
+                       return
+               key = split[0]
+               value = split[1:]
+               if not key:
+                       errors.setdefault(self.fname, []).append(
+                               "Malformed key at line: %s, key %s"
+                               % (line_num + 1, key))
+                       return
+               if not self._validate(key):
+                       errors.setdefault(self.fname, []).append(
+                               "Validation failed at line: %s, data %s"
+                               % (line_num + 1, key))
+                       return
+               if key in data:
+                       data[key].append(value)
+               else:
+                       data[key] = value
 
-       def load(self):
-               """
-               Return the {source: {key: value}} pairs from a file
-               Return the {source: [list of errors] from a load
-
-               @param recursive: If set and self.fname is a directory; 
-                       load all files in self.fname
-               @type: Boolean
-               @rtype: tuple
-               @returns:
-               Returns (data,errors), both may be empty dicts or populated.
-               """
-
-               DataLoader.load(self)
-               data = {}
-               errors = {}
-               for file in RecursiveFileLoader(self.fname):
-                       f = open(file, 'rb')
-                       for line_num, line in enumerate(f):
-                               if line.startswith('#'):
-                                       continue
-                               split = line.strip().split('=')
-                               if len(split) < 2:
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Malformed data at line: %s, data %s"
-                                       % (line_num + 1, split))
-                               key = split[0]
-                               value = split[1:]
-                               if not self._validator.validate(key):
-                                       errors.setdefault(self.fname,[]).append(
-                                       "Validation failed at line: %s, data %s"
-                                       % (line_num + 1, split))
-                                       continue
-                               if key in data:
-                                       data[key].append(value)
-                               else:
-                                       data[key] = value
-               return (data, errors)
diff --git a/pym/portage/env/validators.py b/pym/portage/env/validators.py
new file mode 100644 (file)
index 0000000..fb29b8d
--- /dev/null
@@ -0,0 +1,21 @@
+# validators.py Portage File Loader Code
+# Copyright 2007 Gentoo Foundation
+# $Id$
+
+from portage.dep import isvalidatom
+
+ValidAtomValidator = isvalidatom
+
+def PackagesFileValidator(atom):
+       """ This function mutates atoms that begin with - or *
+           It then checks to see if that atom is valid, and if
+           so returns True, else it returns False.
+           
+           Args:
+               atom: a string representing an atom such as sys-apps/portage-2.1
+       """
+       if atom.startswith("*") or atom.startswith("-"):
+               atom = atom[1:]
+       if not isvalidatom(atom):
+               return False
+       return True
index 3e566735deb8d5306e4ecb2c3acd110aeb0bf5cd..1d2e5bcb68fe1bd22396912c2051fea1b8a20d5f 100644 (file)
@@ -4,7 +4,14 @@
 # $Id: getbinpkg.py 3483 2006-06-10 21:40:40Z genone $
 
 from portage.output import red, yellow, green
-import htmllib,HTMLParser,formatter,sys,os,portage.xpak,time,tempfile,base64,urllib2
+import portage.xpak
+import HTMLParser
+import sys
+import os
+import time
+import tempfile
+import base64
+import urllib2
 from portage.const import CACHE_PATH
 
 try:
@@ -14,16 +21,12 @@ except ImportError:
 
 try:
        import ftplib
-except SystemExit, e:
-       raise
-except Exception, e:
+except ImportError, e:
        sys.stderr.write(red("!!! CANNOT IMPORT FTPLIB: ")+str(e)+"\n")
 
 try:
        import httplib
-except SystemExit, e:
-       raise
-except Exception, e:
+except ImportError, e:
        sys.stderr.write(red("!!! CANNOT IMPORT HTTPLIB: ")+str(e)+"\n")
 
 def make_metadata_dict(data):
@@ -267,11 +270,11 @@ def match_in_array(array, prefix="", suffix="", match_both=1, allow_overlap=0):
 
                if not allow_overlap: # Not allow to overlap prefix and suffix
                        if len(x) >= (len(prefix)+len(suffix)):
-                               y = x[len(prefix):]
+                               pass
                        else:
                                continue          # Too short to match.
                else:
-                       y = x               # Do whatever... We're overlapping.
+                       pass                      # Do whatever... We're overlapping.
                
                if suffix and (len(x) >= len(suffix)) and (x[-len(suffix):] == suffix):
                        myarray.append(x)   # It matches
@@ -457,8 +460,6 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
 
        conn,protocol,address,params,headers = create_conn(baseurl, conn)
 
-       filedict = {}
-
        try:
                metadatafile = open(CACHE_PATH+"/remote_metadata.pickle")
                metadata = cPickle.load(metadatafile)
@@ -485,7 +486,6 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
        # Determine if our metadata file is current.
        metalist.sort()
        metalist.reverse() # makes the order new-to-old.
-       havecache=0
        for mfile in metalist:
                if usingcache and \
                   ((metadata[baseurl]["indexname"] != mfile) or \
@@ -651,7 +651,6 @@ class PackageIndex(object):
                cpv_all = self.packages.keys()
                cpv_all.sort()
                if self.modified:
-                       import time
                        self.header["TIMESTAMP"] = str(long(time.time()))
                        self.header["PACKAGES"] = str(len(cpv_all))
                keys = self.header.keys()
index d8053a8204bafc0b796120a1451abd1a162adf6e..5e2d5f08171a3db7b2f1ba658e8692e470721b7c 100644 (file)
@@ -5,8 +5,6 @@
 import os
 import sys
 import urllib
-import time
-import codecs
 import re
 import xml.dom.minidom
 
@@ -535,7 +533,6 @@ class Glsa:
                @rtype:         Boolean
                @returns:       True if the system is affected, False if not
                """
-               vList = []
                rValue = False
                for k in self.packages.keys():
                        pkg = self.packages[k]
index d8df8c294257b5c0c670a3f548bbec84e5c72864..702a377a54687431fb88077dcec6d8c2e6b165d1 100644 (file)
@@ -72,7 +72,6 @@ class NewsManager(object):
 
                path = os.path.join(self.portdb.getRepositoryPath(repoid), self.NEWS_PATH)
 
-               repo_path = self.portdb.getRepositoryPath(repoid)
                # Skip reading news for repoid if the news dir does not exist.  Requested by
                # NightMorph :)
                if not os.path.exists(path):
@@ -83,7 +82,7 @@ class NewsManager(object):
                        try:
                                filename = os.path.join(path, itemid, itemid + "." + self.LANGUAGE_ID + ".txt")
                                item = NewsItem(filename, itemid, timestamp)
-                       except (TypeError, ValueError), e:
+                       except (TypeError, ValueError):
                                continue
                        if item.isRelevant(profile=self._profile_path,
                                config=self.config, vardb=self.vdb):
index 26a5c4f08ae60d6337f48c0162598d47d64be60e..46d4b97e847921c4dddeb73516fab2ad93fb27f8 100644 (file)
@@ -4,7 +4,12 @@
 
 __docformat__ = "epytext"
 
-import commands, errno, os, re, shlex, sys, time
+import commands
+import errno
+import os
+import re
+import shlex
+import sys
 from portage.const import COLOR_MAP_FILE
 from portage.util import writemsg
 from portage.exception import PortageException, ParseError, PermissionDenied, FileNotFound
@@ -170,7 +175,6 @@ def parse_color_map(onerror=None):
        try:
                s = shlex.shlex(open(myfile))
                s.wordchars = s.wordchars + ";" # for ansi codes
-               d = {}
                while True:
                        k, o, v = s.get_token(), s.get_token(), s.get_token()
                        if k is s.eof:
@@ -220,10 +224,11 @@ def parse_color_map(onerror=None):
 
 try:
        parse_color_map(onerror=lambda e: writemsg("%s\n" % str(e), noiselevel=-1))
-except FileNotFound, e:
+except FileNotFound:
        pass
 except PortageException, e:
        writemsg("%s\n" % str(e))
+       del e
 
 def nc_len(mystr):
        tmp = re.sub(esc_seq + "^m]+m", "", mystr);
index c3f5d4df4e959ade9ef06f556a19803f4251fbb1..fad38770e2fd7f8d57920ca3f854c2da526e81ee 100644 (file)
@@ -4,8 +4,10 @@
 # $Id$
 
 
-import os, atexit, signal, sys
-import portage.data
+import os
+import atexit
+import signal
+import sys
 
 from portage.util import dump_traceback
 from portage.const import BASH_BINARY, SANDBOX_BINARY
index 3e1fbdb2e3ed65d78adb1351ff2acd47034f2eb0..96c4be8a53dd8caca0cf1e104a53e9cf4b4ba91d 100644 (file)
 
 import os
 
-from portage.const import PRIVATE_PATH, USER_CONFIG_PATH
-from portage.exception import InvalidAtom
-from portage.dep import isvalidatom, match_from_list, best_match_to_list, dep_getkey, use_reduce, paren_reduce
-from portage import flatten
-
 OPERATIONS = ["merge", "unmerge"]
 DEFAULT_SETS = ["world", "system", "everything", "security"] \
        +["package_"+x for x in ["mask", "unmask", "use", "keywords"]]
-
-class PackageSet(object):
-       # Set this to operations that are supported by your subclass. While 
-       # technically there is no difference between "merge" and "unmerge" regarding
-       # package sets, the latter doesn't make sense for some sets like "system"
-       # or "security" and therefore isn't supported by them.
-       _operations = ["merge"]
-       _atommap = {}
-       description = "generic package set"
-       
-       def __init__(self, name):
-               self.name = name
-               self._atoms = set()
-               self._atommap = {}
-               self._loaded = False
-               self._loading = False
-
-       def __contains__(self, atom):
-               return atom in self.getAtoms()
-       
-       def __iter__(self):
-               for x in self.getAtoms():
-                       yield x
-       
-       def supportsOperation(self, op):
-               if not op in OPERATIONS:
-                       raise ValueError(op)
-               return op in self._operations
-       
-       def getAtoms(self):
-               if not (self._loaded or self._loading):
-                       self._loading = True
-                       self.load()
-                       self._loaded = True
-                       self._loading = False
-               return self._atoms
-
-       def _setAtoms(self, atoms):
-               atoms = map(str.strip, atoms)
-               for a in atoms[:]:
-                       if a == "":
-                               atoms.remove(a)
-                       elif not isvalidatom(a):
-                               raise InvalidAtom(a)
-               self._atoms = set(atoms)
-               self._updateAtomMap()
-
-       def load(self):
-               # This method must be overwritten by subclasses
-               # Editable sets should use the value of self._mtime to determine if they
-               # need to reload themselves
-               raise NotImplementedError()
-
-       def containsCPV(self, cpv):
-               for a in self.getAtoms():
-                       if match_from_list(a, [cpv]):
-                               return True
-               return False
-       
-       def getMetadata(self, key):
-               if hasattr(self, key.lower()):
-                       return getattr(self, key.lower())
-               else:
-                       return ""
-       
-       def _updateAtomMap(self, atoms=None):
-               """Update self._atommap for specific atoms or all atoms."""
-               if not atoms:
-                       self._atommap.clear()
-                       atoms = self._atoms
-               for a in atoms:
-                       cp = dep_getkey(a)
-                       self._atommap.setdefault(cp, set())
-                       self._atommap[cp].add(a)
-       
-       # Not sure if this one should really be in PackageSet
-       def findAtomForPackage(self, cpv, metadata):
-               """Return the best match for a given package from the arguments, or
-               None if there are no matches.  This matches virtual arguments against
-               the PROVIDE metadata.  This can raise an InvalidDependString exception
-               if an error occurs while parsing PROVIDE."""
-               cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
-               cp = dep_getkey(cpv)
-               self.getAtoms() # make sure the atoms are loaded
-               atoms = self._atommap.get(cp)
-               if atoms:
-                       best_match = best_match_to_list(cpv_slot, atoms)
-                       if best_match:
-                               return best_match
-               if not metadata["PROVIDE"]:
-                       return None
-               provides = flatten(use_reduce(paren_reduce(metadata["PROVIDE"]),
-                                                               uselist=metadata["USE"].split()))
-               for provide in provides:
-                       provided_cp = dep_getkey(provide)
-                       atoms = self._atommap.get(provided_cp)
-                       if atoms:
-                               atoms = list(atoms)
-                               transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
-                               best_match = best_match_to_list(cpv_slot, transformed_atoms)
-                               if best_match:
-                                       return atoms[transformed_atoms.index(best_match)]
-               return None
-
-class EditablePackageSet(PackageSet):
-
-       def update(self, atoms):
-               self.getAtoms()
-               self._atoms.update(atoms)
-               self._updateAtomMap(atoms=atoms)
-               self.write()
-       
-       def add(self, atom):
-               self.update([atom])
-
-       def replace(self, atoms):
-               self._setAtoms(atoms)
-               self.write()
-
-       def remove(self, atom):
-               self.getAtoms()
-               self._atoms.discard(atom)
-               self._updateAtomMap()
-               self.write()
-
-       def removePackageAtoms(self, cp):
-               for a in list(self.getAtoms()):
-                       if dep_getkey(a) == cp:
-                               self.remove(a)
-               self.write()
-
-       def write(self):
-               # This method must be overwritten in subclasses that should be editable
-               raise NotImplementedError()
-
-
-class InternalPackageSet(EditablePackageSet):
-       def __init__(self, initial_atoms=None):
-               super(InternalPackageSet, self).__init__("")
-               if initial_atoms != None:
-                       self.update(initial_atoms)
-
-       def clear(self):
-               self._atoms.clear()
-               self._updateAtomMap()
-       
-       def load(self):
-               pass
-
-       def write(self):
-               pass
+del x
 
 def make_default_sets(configroot, root, profile_paths, settings=None, 
                vdbapi=None, portdbapi=None):
@@ -170,6 +15,7 @@ def make_default_sets(configroot, root, profile_paths, settings=None,
        from portage.sets.profiles import PackagesSystemSet
        from portage.sets.security import NewAffectedSet
        from portage.sets.dbapi import EverythingSet
+       from portage.const import PRIVATE_PATH, USER_CONFIG_PATH
        
        rValue = set()
        worldset = StaticFileSet("world", os.path.join(root, PRIVATE_PATH, "world"))
@@ -193,6 +39,7 @@ def make_default_sets(configroot, root, profile_paths, settings=None,
 
 def make_extra_static_sets(configroot):
        from portage.sets.files import StaticFileSet
+       from portage.const import PRIVATE_PATH, USER_CONFIG_PATH
        
        rValue = set()
        mydir = os.path.join(configroot, USER_CONFIG_PATH.lstrip(os.sep), "sets")
@@ -203,7 +50,7 @@ def make_extra_static_sets(configroot):
        for myname in mysets:
                if myname in DEFAULT_SETS:
                        continue
-               rValue.add(StaticFileSet(fname, os.path.join(mydir, myname)))
+               rValue.add(StaticFileSet(myname, os.path.join(mydir, myname)))
        return rValue
 
 def make_category_sets(portdbapi, settings, only_visible=True):
@@ -224,7 +71,7 @@ if __name__ == "__main__":
                for s in sys.argv[1:]:
                        if s.startswith("category_"):
                                c = s[9:]
-                               l.add(CategorySet("category_%s" % c, c, portdbapi, only_visible=only_visible))
+                               l.add(CategorySet("category_%s" % c, c, portage.db['/']['porttree'].dbapi, only_visible=False))
                        elif os.path.exists(s):
                                l.add(StaticFileSet(os.path.basename(s), s))
                        elif s != "*":
index 1b2520ef6049146fa1defbc9f097978c8fa06eae..13c0fd530431d4d9e7f971a5ce99946d2815712a 100644 (file)
@@ -3,8 +3,162 @@
 # $Id$
 
 from portage.versions import catsplit
+from portage import flatten
+from portage.dep import isvalidatom, match_from_list, \
+     best_match_to_list, dep_getkey, use_reduce, paren_reduce
+from portage.exception import InvalidAtom
+from portage.sets import OPERATIONS
 
-from portage.sets import PackageSet
+class PackageSet(object):
+       # Set this to operations that are supported by your subclass. While 
+       # technically there is no difference between "merge" and "unmerge" regarding
+       # package sets, the latter doesn't make sense for some sets like "system"
+       # or "security" and therefore isn't supported by them.
+       _operations = ["merge"]
+       _atommap = {}
+       description = "generic package set"
+       
+       def __init__(self, name):
+               self.name = name
+               self._atoms = set()
+               self._atommap = {}
+               self._loaded = False
+               self._loading = False
+
+       def __contains__(self, atom):
+               return atom in self.getAtoms()
+       
+       def __iter__(self):
+               for x in self.getAtoms():
+                       yield x
+       
+       def supportsOperation(self, op):
+               if not op in OPERATIONS:
+                       raise ValueError(op)
+               return op in self._operations
+       
+       def getAtoms(self):
+               if not (self._loaded or self._loading):
+                       self._loading = True
+                       self.load()
+                       self._loaded = True
+                       self._loading = False
+               return self._atoms
+
+       def _setAtoms(self, atoms):
+               atoms = map(str.strip, atoms)
+               for a in atoms[:]:
+                       if a == "":
+                               atoms.remove(a)
+                       elif not isvalidatom(a):
+                               raise InvalidAtom(a)
+               self._atoms = set(atoms)
+               self._updateAtomMap()
+
+       def load(self):
+               # This method must be overwritten by subclasses
+               # Editable sets should use the value of self._mtime to determine if they
+               # need to reload themselves
+               raise NotImplementedError()
+
+       def containsCPV(self, cpv):
+               for a in self.getAtoms():
+                       if match_from_list(a, [cpv]):
+                               return True
+               return False
+       
+       def getMetadata(self, key):
+               if hasattr(self, key.lower()):
+                       return getattr(self, key.lower())
+               else:
+                       return ""
+       
+       def _updateAtomMap(self, atoms=None):
+               """Update self._atommap for specific atoms or all atoms."""
+               if not atoms:
+                       self._atommap.clear()
+                       atoms = self._atoms
+               for a in atoms:
+                       cp = dep_getkey(a)
+                       self._atommap.setdefault(cp, set())
+                       self._atommap[cp].add(a)
+       
+       # Not sure if this one should really be in PackageSet
+       def findAtomForPackage(self, cpv, metadata):
+               """Return the best match for a given package from the arguments, or
+               None if there are no matches.  This matches virtual arguments against
+               the PROVIDE metadata.  This can raise an InvalidDependString exception
+               if an error occurs while parsing PROVIDE."""
+               cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
+               cp = dep_getkey(cpv)
+               self.getAtoms() # make sure the atoms are loaded
+               atoms = self._atommap.get(cp)
+               if atoms:
+                       best_match = best_match_to_list(cpv_slot, atoms)
+                       if best_match:
+                               return best_match
+               if not metadata["PROVIDE"]:
+                       return None
+               provides = flatten(use_reduce(paren_reduce(metadata["PROVIDE"]),
+                                                               uselist=metadata["USE"].split()))
+               for provide in provides:
+                       provided_cp = dep_getkey(provide)
+                       atoms = self._atommap.get(provided_cp)
+                       if atoms:
+                               atoms = list(atoms)
+                               transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
+                               best_match = best_match_to_list(cpv_slot, transformed_atoms)
+                               if best_match:
+                                       return atoms[transformed_atoms.index(best_match)]
+               return None
+
+class EditablePackageSet(PackageSet):
+
+       def update(self, atoms):
+               self.getAtoms()
+               self._atoms.update(atoms)
+               self._updateAtomMap(atoms=atoms)
+               self.write()
+       
+       def add(self, atom):
+               self.update([atom])
+
+       def replace(self, atoms):
+               self._setAtoms(atoms)
+               self.write()
+
+       def remove(self, atom):
+               self.getAtoms()
+               self._atoms.discard(atom)
+               self._updateAtomMap()
+               self.write()
+
+       def removePackageAtoms(self, cp):
+               for a in list(self.getAtoms()):
+                       if dep_getkey(a) == cp:
+                               self.remove(a)
+               self.write()
+
+       def write(self):
+               # This method must be overwritten in subclasses that should be editable
+               raise NotImplementedError()
+
+
+class InternalPackageSet(EditablePackageSet):
+       def __init__(self, initial_atoms=None):
+               super(InternalPackageSet, self).__init__("")
+               if initial_atoms != None:
+                       self.update(initial_atoms)
+
+       def clear(self):
+               self._atoms.clear()
+               self._updateAtomMap()
+       
+       def load(self):
+               pass
+
+       def write(self):
+               pass
 
 class EverythingSet(PackageSet):
        _operations = ["merge", "unmerge"]
index 99d30d8303b2e99e9e0d081b4c995f2578a23163..f5884eea75ebf799de2b7582d0b1f1749d1c86b6 100644 (file)
@@ -2,24 +2,31 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
-from portage.util import grabfile, grabfile_package, grabdict_package, write_atomic, ensure_dirs
+import os
+
+from portage.util import grabfile, write_atomic, ensure_dirs
 from portage.const import PRIVATE_PATH
 from portage.locks import lockfile, unlockfile
 from portage import portage_gid
-import os
-
-from portage.sets import PackageSet, EditablePackageSet
+from portage.sets.dbapi import PackageSet, EditablePackageSet
+from portage.env.config import ConfigLoaderKlass, GenericFile
+from portage.env.loaders import ItemFileLoader, KeyListFileLoader
+from portage.env.validators import PackagesFileValidator, ValidAtomValidator
 
 class StaticFileSet(EditablePackageSet):
        _operations = ["merge", "unmerge"]
        
-       def __init__(self, name, filename):
+       def __init__(self, name, filename, loader=None):
                super(StaticFileSet, self).__init__(name)
                self._filename = filename
                self._mtime = None
                self.description = "Package set loaded from file %s" % self._filename
+               if loader is None:
+                       self.loader = ConfigLoaderKlass(ItemFileLoader(filename=self._filename,
+                               validator=PackagesFileValidator))
                metadata = grabfile(self._filename + ".metadata")
                key = None
+               value = []
                for line in metadata:
                        line = line.strip()
                        if len(line) == 0 and key != None:
@@ -45,17 +52,23 @@ class StaticFileSet(EditablePackageSet):
                except (OSError, IOError):
                        mtime = None
                if (not self._loaded or self._mtime != mtime):
-                       self._setAtoms(grabfile_package(self._filename, recursive=True))
+                       self.loader.load()
+                       self._setAtoms(self.loader.keys())
                        self._mtime = mtime
        
 class ConfigFileSet(PackageSet):
-       def __init__(self, name, filename):
+       def __init__(self, name, filename, loader=None, validator=None):
                super(ConfigFileSet, self).__init__(name)
                self._filename = filename
                self.description = "Package set generated from %s" % self._filename
+               if loader is None:
+                       self.loader = GenericFile(filename=self._filename)
+               else:
+                       self.loader = loader(filename, validator)
 
        def load(self):
-               self._setAtoms(grabdict_package(self._filename, recursive=True).keys())
+               self.loader.load()
+               self._setAtoms(self.loader.keys())
 
 class WorldSet(StaticFileSet):
        description = "Set of packages that were directly installed by the user"
index 55b7942f594f2a9b747c0be53a4eab8dc6b39af2..4e369e5e2e61adc386b478f25db1a0332be41f92 100644 (file)
@@ -4,8 +4,7 @@
 
 import os
 from portage.util import grabfile_package, stack_lists
-
-from portage.sets import PackageSet
+from portage.sets.dbapi import PackageSet
 
 class PackagesSystemSet(PackageSet):
        _operations = ["merge"]
index 3bc9cbca4862e5a489052a1b639b3f224c0ad2dc..d1efa4df79a10c616af59770e5d171d225d99822 100644 (file)
@@ -2,12 +2,11 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
+import os
 import portage.glsa as glsa
-from portage.util import grabfile
+from portage.util import grabfile, write_atomic
 from portage.const import CACHE_PATH
-import os
-
-from portage.sets import PackageSet
+from portage.sets.dbapi import PackageSet
 
 class SecuritySet(PackageSet):
        _operations = ["merge"]
index 2383dba81cf1463e94698f398f2eb39ea29e1d8b..5c316c1e484242f3b7ac85313f7424d03896b5a3 100644 (file)
@@ -2,11 +2,25 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
-import subprocess, os
+import subprocess
+import os
 
-from portage.sets import PackageSet
+from portage.sets.dbapi import PackageSet
 
 class CommandOutputSet(PackageSet):
+       """This class creates a PackageSet from the output of a shell command.
+          The shell command should produce one atom per line, that is:
+
+          >>> atom1
+              atom2
+              ...
+              atomN
+
+          Args:
+            name: A string that identifies the set.
+            command: A string or sequence identifying the command to run
+            (see the subprocess.Popen documentaion for the format)
+       """
        _operations = ["merge", "unmerge"]
 
        def __init__(self, name, command):
index e3702e08e9e1937bfff4cfdcbb7a873fa9c2f332..2ade6d4022116285395e374708f248c0f5b48789 100644 (file)
@@ -3,17 +3,19 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
-import os, sys, time, unittest
-import portage.tests
+import os
+import sys
+import time
+import unittest
 
 def main():
        testDirs = ["bin", "dep", "ebuild",
-               "env/config", "util", "versions", "xpak"]
+               "env/config", "util", "versions", "xpak", "sets/shell"]
        suite = unittest.TestSuite()
        basedir = os.path.dirname(__file__)
        for mydir in testDirs:
                suite.addTests(getTests(os.path.join(basedir, mydir), basedir) )
-       return portage.tests.TextTestRunner(verbosity=2).run(suite)
+       return TextTestRunner(verbosity=2).run(suite)
 
 def my_import(name):
        mod = __import__(name)
@@ -22,7 +24,7 @@ def my_import(name):
                mod = getattr(mod, comp)
        return mod
 
-def getTests( path, base_path ):
+def getTests(path, base_path):
        """
 
        path is the path to a given subdir ( 'portage/' for example)
@@ -30,18 +32,17 @@ def getTests( path, base_path ):
        to import
 
        """
-       import os
-       files = os.listdir( path )
-       files = [ f[:-3] for f in files if f.startswith("test_") and f.endswith(".py") ]
+       files = os.listdir(path)
+       files = [ f[:-3] for f in files if f.startswith("test") and f.endswith(".py") ]
        parent_path = path[len(base_path)+1:]
-       parent_module = ".".join(("portage","tests", parent_path))
-       parent_module = parent_module.replace('/','.')
+       parent_module = ".".join(("portage", "tests", parent_path))
+       parent_module = parent_module.replace('/', '.')
        result = []
        for mymodule in files:
                # Make the trailing / a . for module importing
                modname = ".".join((parent_module, mymodule))
                mod = my_import(modname)
-               result.append( unittest.TestLoader().loadTestsFromModule(mod) )
+               result.append(unittest.TestLoader().loadTestsFromModule(mod))
        return result
 
 class TextTestResult(unittest._TextTestResult):
@@ -53,18 +54,18 @@ class TextTestResult(unittest._TextTestResult):
        by the test runner.
        """
        
-       def __init__( self, stream, descriptions, verbosity ):
+       def __init__(self, stream, descriptions, verbosity):
                unittest._TextTestResult.__init__( self, stream, descriptions, verbosity )
                self.todoed = []
 
-       def addTodo( self, test, info ):
+       def addTodo(self, test, info):
                self.todoed.append((test,info))
                if self.showAll:
                        self.stream.writeln("TODO")
                elif self.dots:
                        self.stream.write(".")
        
-       def printErrors( self ):
+       def printErrors(self):
                if self.dots or self.showAll:
                        self.stream.writeln()
                        self.printErrorList('ERROR', self.errors)
@@ -90,7 +91,7 @@ class TestCase(unittest.TestCase):
        def defaultTestResult(self):
                return TextTestResult()
 
-       def run( self, result=None ):
+       def run(self, result=None):
                if result is None: result = self.defaultTestResult()
                result.startTest(self)
                testMethod = getattr(self, self._testMethodName)
@@ -134,7 +135,7 @@ class TextTestRunner(unittest.TextTestRunner):
        def _makeResult(self):
                return TextTestResult(self.stream, self.descriptions, self.verbosity)
 
-       def run( self, test ):
+       def run(self, test):
                """
                Run the given test case or test suite.
                """
index e8357f7e61b2754e60df6d33ef59affa27866289..4000f18071b358817facc6b6c873368964561011 100644 (file)
@@ -6,12 +6,10 @@
 import os
 
 from portage.env.config import PackageMaskFile
-from portage.tests import TestCase
+from portage.tests import TestCase, test_cps
 from tempfile import mkstemp
 
 class PackageMaskFileTestCase(TestCase):
-
-       atoms = ['sys-apps/portage','dev-util/diffball','not@va1id@t0m']
        
        def testPackageMaskFile(self):
                self.BuildFile()
@@ -19,14 +17,14 @@ class PackageMaskFileTestCase(TestCase):
                        f = PackageMaskFile(self.fname)
                        f.load()
                        for atom in f:
-                               self.assertTrue(atom in self.atoms)
+                               self.assertTrue(atom in test_cps)
                finally:
                        self.NukeFile()
        
        def BuildFile(self):
                fd, self.fname = mkstemp()
                f = os.fdopen(fd, 'w')
-               f.write("\n".join(self.atoms))
+               f.write("\n".join(test_cps))
                f.close()
        
        def NukeFile(self):
index 03104cff5f182a830fa6df52f435fab7f12165e1..e4f9e4252b40604a961969af496542c3ba8abf7b 100644 (file)
@@ -1,34 +1,38 @@
-import os
 
 from portage.tests import TestCase
 from portage.env.config import PortageModulesFile
 from tempfile import mkstemp
 from itertools import izip
+import os
 
 class PortageModulesFileTestCase(TestCase):
 
        keys = ['foo.bar','baz','bob','extra_key']
-       modules = ['spanky','zmedico','antarus','ricer']
+       invalid_keys = ['',""]
+       modules = ['spanky','zmedico','antarus','ricer','5','6']
 
        def setUp(self):
                self.items = {}
-               for k,v in izip(self.keys, self.modules):
+               for k, v in izip(self.keys + self.invalid_keys, 
+                               self.modules):
                        self.items[k] = v
 
        def testPortageModulesFile(self):
                self.BuildFile()
                f = PortageModulesFile(self.fname)
-               for k in f:
-                       self.assertEqual( f[k], self.items[k] )
+               f.load()
+               for k in self.keys:
+                       self.assertEqual(f[k], [self.items[k]])
+               for ik in self.invalid_keys:
+                       self.assertEqual(False, ik in f)
                self.NukeFile()
 
        def BuildFile(self):
                fd, self.fname = mkstemp()
                f = os.fdopen(fd, 'wb')
-               for k,v in self.items.iteritems():
+               for k, v in self.items.iteritems():
                        f.write('%s=%s\n' % (k,v))
                f.close()
 
        def NukeFile(self):
-               import os
                os.unlink(self.fname)
diff --git a/pym/portage/tests/sets/__init__.py b/pym/portage/tests/sets/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pym/portage/tests/sets/shell/__init__.py b/pym/portage/tests/sets/shell/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pym/portage/tests/sets/shell/testShell.py b/pym/portage/tests/sets/shell/testShell.py
new file mode 100644 (file)
index 0000000..938c265
--- /dev/null
@@ -0,0 +1,28 @@
+# testCommandOututSet.py -- Portage Unit Testing Functionality
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+from portage.process import find_binary
+from portage.tests import TestCase, test_cps
+from portage.sets.shell import CommandOutputSet
+
+class CommandOutputSetTestCase(TestCase):
+       """Simple Test Case for CommandOutputSet"""
+
+       def setUp(self):
+               pass
+
+       def tearDown(self):
+               pass
+
+       def testCommand(self):
+               
+               input = set(test_cps)
+               command = find_binary("echo")
+               command += " -e "
+               for a in input:
+                 command += "\"%s\n\"" % a
+               s = CommandOutputSet('testset', command)
+               atoms = s.getAtoms()
+               self.assertEqual(atoms, input)
index 53b1c86f4cbe36b1316827fd8ca1681e1180da36..ad6f39e822e962960951b1c0ba850d4078c764fe 100644 (file)
@@ -2,13 +2,20 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id: portage_util.py 4603 2006-10-06 03:28:25Z zmedico $
 
+
+import os
+import errno
+import shlex
+import stat
+import string
+import sys
+
 from portage.exception import PortageException, FileNotFound, \
        OperationNotPermitted, PermissionDenied, ReadOnlyFileSystem
 import portage.exception
 from portage.dep import isvalidatom
 from portage.const import EPREFIX
 
-import os, errno, shlex, stat, string, sys
 try:
        import cPickle
 except ImportError:
@@ -223,6 +230,8 @@ def grabdict(myfilename, juststrings=0, empty=0, recursive=0, incremental=1):
        return newdict
 
 def grabdict_package(myfilename, juststrings=0, recursive=0):
+       """ Does the same thing as grabdict except it validates keys
+           with isvalidatom()"""
        pkgs=grabdict(myfilename, juststrings, empty=1, recursive=recursive)
        # We need to call keys() here in order to avoid the possibility of
        # "RuntimeError: dictionary changed size during iteration"
@@ -238,9 +247,7 @@ def grabfile_package(myfilename, compatlevel=0, recursive=0):
        pkgs=grabfile(myfilename, compatlevel, recursive=recursive)
        for x in range(len(pkgs)-1, -1, -1):
                pkg = pkgs[x]
-               if pkg[0] == "-":
-                       pkg = pkg[1:]
-               if pkg[0] == "*": # Kill this so we can deal the "packages" file too
+               if pkg[0] in  ["-","*"]: # -atom *pkg for packages file
                        pkg = pkg[1:]
                if not isvalidatom(pkg):
                        writemsg("--- Invalid atom in %s: %s\n" % (myfilename, pkgs[x]),
index e3588ab728f085ca0ea909f7eeb0091cb8e636c2..c463b8b4cfbd9f8b78bc3edaec3af0581c0e2547 100644 (file)
@@ -126,7 +126,6 @@ def xsplit_mem(mydat):
        if mydat[-8:]!="XPAKSTOP":
                return None
        indexsize=decodeint(mydat[8:12])
-       datasize=decodeint(mydat[12:16])
        return (mydat[16:indexsize+16], mydat[indexsize+16:-8])
 
 def getindex(infile):
@@ -251,7 +250,7 @@ class tbz2(object):
                return self.unpackinfo(datadir)
        def compose(self,datadir,cleanup=0):
                """Alias for recompose()."""
-               return recompose(datadir,cleanup)
+               return self.recompose(datadir,cleanup)
        def recompose(self,datadir,cleanup=0):
                """Creates an xpak segment from the datadir provided, truncates the tbz2
                to the end of regular data if an xpak segment already exists, and adds