summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/portage/sets/__init__.py157
-rw-r--r--pym/portage/sets/dbapi.py157
-rw-r--r--pym/portage/sets/files.py28
-rw-r--r--pym/portage/sets/profiles.py2
-rw-r--r--pym/portage/sets/security.py2
-rw-r--r--pym/portage/sets/shell.py2
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.