summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/portage/__init__.py24
-rw-r--r--pym/portage/util.py42
2 files changed, 58 insertions, 8 deletions
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index c18d43013..992f257cb 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -958,6 +958,19 @@ def check_config_instance(test):
if not isinstance(test, config):
raise TypeError("Invalid type for config object: %s (should be %s)" % (test.__class__, config))
+def _lazy_iuse_regex(iuse_implicit):
+ """
+ The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow
+ and the value is only used when an ebuild phase needs to be executed
+ (it's used only to generate QA notices).
+ """
+ # Escape anything except ".*" which is supposed to pass through from
+ # _get_implicit_iuse().
+ regex = sorted(re.escape(x) for x in iuse_implicit)
+ regex = "^(%s)$" % "|".join(regex)
+ regex = regex.replace("\\.\\*", ".*")
+ return regex
+
class config(object):
"""
This class encompasses the main portage configuration. Data is pulled from
@@ -1484,7 +1497,7 @@ class config(object):
self.configlist.append(self.mygcfg)
self.configdict["conf"]=self.configlist[-1]
- self.configlist.append({})
+ self.configlist.append(util.LazyItemsDict())
self.configdict["pkg"]=self.configlist[-1]
#auto-use:
@@ -2077,12 +2090,9 @@ class config(object):
iuse_implicit = self._get_implicit_iuse()
iuse_implicit.update(x.lstrip("+-") for x in iuse.split())
- # Escape anything except ".*" which is supposed
- # to pass through from _get_implicit_iuse()
- regex = sorted(re.escape(x) for x in iuse_implicit)
- regex = "^(%s)$" % "|".join(regex)
- regex = regex.replace("\\.\\*", ".*")
- self.configdict["pkg"]["PORTAGE_IUSE"] = regex
+ # PORTAGE_IUSE is not always needed so it's lazily evaluated.
+ self.configdict["pkg"].addLazySingleton(
+ "PORTAGE_IUSE", _lazy_iuse_regex, iuse_implicit)
ebuild_force_test = self.get("EBUILD_FORCE_TEST") == "1"
if ebuild_force_test and \
diff --git a/pym/portage/util.py b/pym/portage/util.py
index 33a61a26b..ce226a4f7 100644
--- a/pym/portage/util.py
+++ b/pym/portage/util.py
@@ -2,7 +2,6 @@
# Distributed under the terms of the GNU General Public License v2
# $Id$
-
import os
import errno
import logging
@@ -1244,6 +1243,47 @@ class LazyItemsDict(dict):
del self.lazy_items[item_key]
dict.__delitem__(self, item_key)
+ def clear(self):
+ self.lazy_items.clear()
+ dict.clear(self)
+
+ def copy(self):
+ return self.__copy__()
+
+ def __copy__(self):
+ return self.__class__(self)
+
+ def __deepcopy__(self, memo=None):
+ """
+ WARNING: If any of the lazy items contains a bound method then it's
+ typical for deepcopy() to raise an exception like this:
+
+ File "/usr/lib/python2.5/copy.py", line 189, in deepcopy
+ y = _reconstruct(x, rv, 1, memo)
+ File "/usr/lib/python2.5/copy.py", line 322, in _reconstruct
+ y = callable(*args)
+ File "/usr/lib/python2.5/copy_reg.py", line 92, in __newobj__
+ return cls.__new__(cls, *args)
+ TypeError: instancemethod expected at least 2 arguments, got 0
+
+ If deepcopy() needs to work, this problem can be avoided by
+ implementing lazy items with normal (non-bound) functions.
+ """
+ if memo is None:
+ memo = {}
+ from copy import deepcopy
+ result = self.__class__()
+ memo[id(self)] = result
+ for k in self:
+ k_copy = deepcopy(k, memo)
+ if k in self.lazy_items:
+ dict.__setitem__(result, k_copy, None)
+ result.lazy_items[k_copy] = \
+ deepcopy(self.lazy_items[k], memo)
+ else:
+ dict.__setitem__(result, k_copy, deepcopy(self[k], memo))
+ return result
+
class _SingletonWrapper(object):
__slots__ = ('_parent', '_key', '_callable', '_pargs', '_kwargs')