diff options
-rw-r--r-- | pym/portage/sets/__init__.py | 157 | ||||
-rw-r--r-- | pym/portage/sets/dbapi.py | 157 | ||||
-rw-r--r-- | pym/portage/sets/files.py | 28 | ||||
-rw-r--r-- | pym/portage/sets/profiles.py | 2 | ||||
-rw-r--r-- | pym/portage/sets/security.py | 2 | ||||
-rw-r--r-- | pym/portage/sets/shell.py | 2 |
6 files changed, 172 insertions, 176 deletions
diff --git a/pym/portage/sets/__init__.py b/pym/portage/sets/__init__.py index 96c4be8a5..7c288c264 100644 --- a/pym/portage/sets/__init__.py +++ b/pym/portage/sets/__init__.py @@ -3,12 +3,169 @@ # $Id$ import os +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 OPERATIONS = ["merge", "unmerge"] DEFAULT_SETS = ["world", "system", "everything", "security"] \ +["package_"+x for x in ["mask", "unmask", "use", "keywords"]] del x +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 + + + def make_default_sets(configroot, root, profile_paths, settings=None, vdbapi=None, portdbapi=None): from portage.sets.files import StaticFileSet, ConfigFileSet diff --git a/pym/portage/sets/dbapi.py b/pym/portage/sets/dbapi.py index 13c0fd530..709bbbdec 100644 --- a/pym/portage/sets/dbapi.py +++ b/pym/portage/sets/dbapi.py @@ -3,162 +3,7 @@ # $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 - -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 +from portage.sets import PackageSet class EverythingSet(PackageSet): _operations = ["merge", "unmerge"] diff --git a/pym/portage/sets/files.py b/pym/portage/sets/files.py index 05a44e7bd..b3f85d553 100644 --- a/pym/portage/sets/files.py +++ b/pym/portage/sets/files.py @@ -9,23 +9,20 @@ 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 -from portage.sets.dbapi import PackageSet, EditablePackageSet -from portage.env.config import ConfigLoaderKlass, GenericFile +from portage.sets import PackageSet, EditablePackageSet from portage.env.loaders import ItemFileLoader, KeyListFileLoader -from portage.env.validators import PackagesFileValidator, ValidAtomValidator +from portage.env.validators import ValidAtomValidator class StaticFileSet(EditablePackageSet): _operations = ["merge", "unmerge"] - def __init__(self, name, filename, data = None): + def __init__(self, name, filename): super(StaticFileSet, self).__init__(name) self._filename = filename self._mtime = None self.description = "Package set loaded from file %s" % self._filename - self.data = data - if data is None: - self.data = ConfigLoaderKlass(ItemFileLoader(filename=self._filename, - validator=PackagesFileValidator)) + self.loader = ItemFileLoader(self._filename, ValidAtomValidator) + metadata = grabfile(self._filename + ".metadata") key = None value = [] @@ -55,27 +52,24 @@ class StaticFileSet(EditablePackageSet): mtime = None if (not self._loaded or self._mtime != mtime): try: - self.data.load() + data, errors = self.loader.load() except EnvironmentError, e: if e.errno != errno.ENOENT: raise del e - self._setAtoms(self.data.keys()) + self._setAtoms(data.keys()) self._mtime = mtime class ConfigFileSet(PackageSet): - def __init__(self, name, filename, loader=None, validator=None): + def __init__(self, name, filename): 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) + self.loader = KeyListFileLoader(self._filename, ValidAtomValidator) def load(self): - self.loader.load() - self._setAtoms(self.loader.keys()) + data, errors = self.loader.load() + self._setAtoms(data.keys()) class WorldSet(StaticFileSet): description = "Set of packages that were directly installed by the user" diff --git a/pym/portage/sets/profiles.py b/pym/portage/sets/profiles.py index 4e369e5e2..a1be8e47f 100644 --- a/pym/portage/sets/profiles.py +++ b/pym/portage/sets/profiles.py @@ -4,7 +4,7 @@ import os from portage.util import grabfile_package, stack_lists -from portage.sets.dbapi import PackageSet +from portage.sets import PackageSet class PackagesSystemSet(PackageSet): _operations = ["merge"] diff --git a/pym/portage/sets/security.py b/pym/portage/sets/security.py index d1efa4df7..c2c6048e1 100644 --- a/pym/portage/sets/security.py +++ b/pym/portage/sets/security.py @@ -6,7 +6,7 @@ import os import portage.glsa as glsa from portage.util import grabfile, write_atomic from portage.const import CACHE_PATH -from portage.sets.dbapi import PackageSet +from portage.sets import PackageSet class SecuritySet(PackageSet): _operations = ["merge"] diff --git a/pym/portage/sets/shell.py b/pym/portage/sets/shell.py index 5c316c1e4..6a84918a7 100644 --- a/pym/portage/sets/shell.py +++ b/pym/portage/sets/shell.py @@ -5,7 +5,7 @@ import subprocess import os -from portage.sets.dbapi import PackageSet +from portage.sets import PackageSet class CommandOutputSet(PackageSet): """This class creates a PackageSet from the output of a shell command. |