From 7bb51acabd9abfc192e6dfe4c9253f1f183492fc Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Thu, 5 Apr 2007 15:38:52 +0000 Subject: [PATCH] Merged from trunk 6327:6332 +------------------------------------------------------------------------+ | 6328 | After talking to marienz, decide that 1 class is better | | WarnerBro | than 4, also realize that UserDict has most of the dict | | | methods exposed, so drop them. Also add a LoaderError | | | Exception. Still to do? add a validation callable into the | | | loader to validate data. | |-----------+------------------------------------------------------------| | 6329 | drop line_count in favor of izip and count(), itertools | | WarnerBro | FOR THE WIN baby. | |-----------+------------------------------------------------------------| | 6330 | I consulted the python oracle and it told me enumerate was | | WarnerBro | better, so go team enumerate | |-----------+------------------------------------------------------------| | 6332 | For bug #173184, handle the CommandNotFound that is | | zmedico | produced during uninstallation of prelink. | +------------------------------------------------------------------------+ svn path=/main/branches/prefix/; revision=6334 --- pym/portage/checksum.py | 13 ++-- pym/portage/env/config.py | 135 +++++++------------------------------ pym/portage/env/loaders.py | 78 +++++++++++++++------ 3 files changed, 92 insertions(+), 134 deletions(-) diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py index 2ae873ca5..de4be208c 100644 --- a/pym/portage/checksum.py +++ b/pym/portage/checksum.py @@ -181,6 +181,7 @@ def perform_checksum(filename, hashname="MD5", calc_prelink=0): @rtype: Tuple @return: The hash and size of the data """ + global prelink_capable myfilename = filename[:] prelink_tmpfile = os.path.join("/", PRIVATE_PATH, "prelink-checksum.tmp." + str(os.getpid())) mylock = None @@ -189,10 +190,14 @@ def perform_checksum(filename, hashname="MD5", calc_prelink=0): mylock = portage.locks.lockfile(prelink_tmpfile, wantnewlockfile=1) # Create non-prelinked temporary file to checksum. # Files rejected by prelink are summed in place. - retval = portage.process.spawn([PRELINK_BINARY, "--undo", "-o", - prelink_tmpfile, filename], fd_pipes={}) - if retval == os.EX_OK: - myfilename = prelink_tmpfile + try: + retval = portage.process.spawn([PRELINK_BINARY, "--undo", "-o", + prelink_tmpfile, filename], fd_pipes={}) + if retval == os.EX_OK: + myfilename = prelink_tmpfile + except portage.exception.CommandNotFound: + # This happens during uninstallation of prelink. + prelink_capable = False try: if hashname not in hashfunc_map: raise portage.exception.DigestException(hashname + \ diff --git a/pym/portage/env/config.py b/pym/portage/env/config.py index 3bac9a3a5..62d3d8177 100644 --- a/pym/portage/env/config.py +++ b/pym/portage/env/config.py @@ -4,111 +4,52 @@ # $Id$ from UserDict import UserDict -from portage.env.loaders import KeyListFileLoader, KeyValuePairFileLoader, AtomFileLoader +from portage.env.loaders import KeyListFileLoader, KeyValuePairFileLoader, ItemFileLoader -class PackageKeywords(UserDict): +class UserConfigKlass(UserDict,object): """ - A base class stub for things to inherit from; some people may want a database based package.keywords or something - - Internally dict has pairs of the form - {'cpv':['keyword1','keyword2','keyword3'...] + 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. + """ self._loader = loader def load(self): + """ + Load the data from the loader. + + @throws LoaderError: + """ + self.data, self.errors = self._loader.load() - def iteritems(self): - return self.data.iteritems() - - def keys(self): - return self.data.keys() - - def __contains__(self, other): - return other in self.data - - def __hash__( self ): - return self.data.__hash__() - -class PackageKeywordsFile(PackageKeywords): +class PackageKeywordsFile(UserConfigKlass): """ - Inherits from PackageKeywords; implements a file-based backend. Doesn't handle recursion yet. + Inherits from UserConfigKlass; implements a file-based backend. """ default_loader = KeyListFileLoader def __init__(self, filename): - PackageKeywords.__init__(self, self.default_loader(filename)) - -class PackageUse(UserDict): - """ - A base class stub for things to inherit from; some people may want a database based package.keywords or something - - Internally dict has pairs of the form - {'cpv':['flag1','flag22','flag3'...] - """ - - data = {} + super(PackageKeywordsFile,self).__init__(self.default_loader(filename)) - def __init__(self, loader): - self._loader = loader - - def load( self): - self.data, self.errors = self._loader.load() - - def iteritems(self): - return self.data.iteritems() - - def __hash__(self): - return hash(self.data) - - def __contains__(self, other): - return other in self.data - - def keys(self): - return self.data.keys() - -class PackageUseFile(PackageUse): +class PackageUseFile(UserConfigKlass): """ Inherits from PackageUse; implements a file-based backend. Doesn't handle recursion yet. """ default_loader = KeyListFileLoader def __init__(self, filename): - PackageUse.__init__(self, self.default_loader(filename)) - -class PackageMask(UserDict): - """ - A base class for Package.mask functionality - """ - data = {} + super(PackageUseFile,self).__init__(self.default_loader(filename)) - def __init__(self, loader): - self._loader = loader - - def load(self): - self.data, self.errors = self._loader.load() - - def iteritems(self): - return self.data.iteritems() - - def __hash__(self): - return hash(self.data) - - def __contains__(self, other): - return other in self.data - - def keys(self): - return self.data.keys() - - def iterkeys(self): - return self.data.iterkeys() - -class PackageMaskFile(PackageMask): +class PackageMaskFile(UserConfigKlass): """ A class that implements a file-based package.mask @@ -120,40 +61,12 @@ class PackageMaskFile(PackageMask): to revert a previous mask; this only works when masking files are stacked """ - default_loader = AtomFileLoader + default_loader = ItemFileLoader def __init__(self, filename): - PackageMask.__init__(self, self.default_loader(filename)) - -class PortageModules(UserDict): - """ - Base Class for user level module over-rides - """ - - data = {} - - def __init__(self, loader): - self._loader = loader - - def load(self): - self.data, self.errors = self._loader.load() - - def iteritems(self): - return self.data.iteritems() - - def __hash__(self): - return self.data.__hash__() - - def __contains__(self, key): - return key in self.data - - def keys(self): - return self.data.keys() - - def iterkeys(self): - return self.data.iterkeys() + super(PackageMaskFile,self).__init__(self.default_loader(filename)) -class PortageModulesFile(PortageModules): +class PortageModulesFile(UserConfigKlass): """ File Class for /etc/portage/modules """ @@ -161,4 +74,4 @@ class PortageModulesFile(PortageModules): default_loader = KeyValuePairFileLoader def __init__(self, filename): - PortageModules.__init__(self, self.default_loader(filename)) + super(PortageModulesFile,self).__init__(self.default_loader(filename)) diff --git a/pym/portage/env/loaders.py b/pym/portage/env/loaders.py index 33a8c3d4f..6bfcce77b 100644 --- a/pym/portage/env/loaders.py +++ b/pym/portage/env/loaders.py @@ -5,6 +5,22 @@ import os +class LoaderError(Exception): + + def __init__(self, resource, error_msg): + """ + @param resource: Resource that failed to load (file/sql/etc) + @type resource: String + @param error_msg: Error from underlying Loader system + @type error_msg: String + """ + + self.resource + + def __str__(self): + return "Failed while loading resource: %s, error was: %s" % ( + resource, error_msg) + def RecursiveFileLoader(filename): """ If filename is of type file, return [filename] @@ -32,21 +48,35 @@ def RecursiveFileLoader(filename): class DataLoader(object): + def __init__(self, validator=None): + f = validator + if f is None: + # if they pass in no validator, just make a fake one + # that always returns true + class AlwaysTrue(): + def validate(self, key): + return True + f = AlwaysTrue() + self._validator = f + def load(self): """ Function to do the actual work of a Loader """ pass -class AtomFileLoader(DataLoader): +class ItemFileLoader(DataLoader): """ - Class to load data from a file full of atoms one per line + Class to load data from a file full of items one per line - >>> atom1 - >>> atom2 - >>> atom3 + >>> item1 + >>> item2 + >>> item3 + >>> item1 - becomes ['atom1', 'atom2', 'atom3'] + becomes { 'item1':None, 'item2':None, 'item3':None } + Note that due to the data store being a dict, duplicates + are removed. """ _recursive = False @@ -58,20 +88,23 @@ class AtomFileLoader(DataLoader): def load(self): data = {} errors = {} - line_count = 0 for file in RecursiveFileLoader(self.fname): f = open(file, 'rb') - for line in f: - line_count = line_count + 1 + 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_count, split)) + % (line_num + 1, split)) key = split[0] - data[key] = None + 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): @@ -92,20 +125,24 @@ class KeyListFileLoader(DataLoader): def load(self): data = {} errors = {} - line_count = 0 for file in RecursiveFileLoader(self.fname): f = open(file, 'rb') - for line in f: - line_count = line_count + 1 + 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_count, split)) + % (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: @@ -145,20 +182,23 @@ class KeyValuePairFileLoader(DataLoader): DataLoader.load(self) data = {} errors = {} - line_count = 0 for file in RecursiveFileLoader(self.fname): f = open(file, 'rb') - for line in f: - line_count = line_count + 1 # Increment line count + 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_count, split)) + % (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: -- 2.26.2