aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/portage/cache/mappings.py')
-rw-r--r--lib/portage/cache/mappings.py329
1 files changed, 180 insertions, 149 deletions
diff --git a/lib/portage/cache/mappings.py b/lib/portage/cache/mappings.py
index c0f2147a9..469f3dbc4 100644
--- a/lib/portage/cache/mappings.py
+++ b/lib/portage/cache/mappings.py
@@ -1,4 +1,4 @@
-# Copyright: 2005-2020 Gentoo Authors
+# Copyright: 2005-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# Author(s): Brian Harring (ferringb@gentoo.org)
@@ -69,7 +69,7 @@ class Mapping:
class MutableMapping(Mapping):
"""
- A mutable vesion of the Mapping class.
+ A mutable version of the Mapping class.
"""
__slots__ = ()
@@ -146,7 +146,6 @@ class UserDict(MutableMapping):
__slots__ = ("data",)
def __init__(self, *args, **kwargs):
-
self.data = {}
if len(args) > 1:
@@ -250,7 +249,7 @@ class LazyLoad(Mapping):
def __getitem__(self, key):
if key in self.d:
return self.d[key]
- if self.pull != None:
+ if self.pull is not None:
self.d.update(self.pull())
self.pull = None
return self.d[key]
@@ -264,7 +263,7 @@ class LazyLoad(Mapping):
def __contains__(self, key):
if key in self.d:
return True
- if self.pull != None:
+ if self.pull is not None:
self.d.update(self.pull())
self.pull = None
return key in self.d
@@ -272,6 +271,175 @@ class LazyLoad(Mapping):
keys = __iter__
+class _SlotDict:
+ """
+ Base class for classes returned from slot_dict_class.
+ """
+
+ _prefix = ""
+ allowed_keys = frozenset()
+ __slots__ = ("__weakref__",)
+
+ def __init__(self, *args, **kwargs):
+ if len(args) > 1:
+ raise TypeError(
+ "expected at most 1 positional argument, got " + repr(len(args))
+ )
+
+ if args:
+ self.update(args[0])
+
+ if kwargs:
+ self.update(kwargs)
+
+ def __reduce__(self):
+ return _PickledSlotDict, (
+ self._prefix,
+ self.allowed_keys,
+ dict(self),
+ )
+
+ def __eq__(self, other):
+ return dict(self) == dict(other)
+
+ def __iter__(self):
+ for k, v in self.iteritems():
+ yield k
+
+ def __len__(self):
+ l = 0
+ for i in self.iteritems():
+ l += 1
+ return l
+
+ def iteritems(self):
+ prefix = self._prefix
+ for k in self.allowed_keys:
+ try:
+ yield (k, getattr(self, prefix + k))
+ except AttributeError:
+ pass
+
+ def itervalues(self):
+ for k, v in self.iteritems():
+ yield v
+
+ def __delitem__(self, k):
+ try:
+ delattr(self, self._prefix + k)
+ except AttributeError:
+ raise KeyError(k)
+
+ def __setitem__(self, k, v):
+ setattr(self, self._prefix + k, v)
+
+ def setdefault(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return default
+
+ def update(self, *args, **kwargs):
+ if len(args) > 1:
+ raise TypeError(
+ "expected at most 1 positional argument, got " + repr(len(args))
+ )
+ other = None
+ if args:
+ other = args[0]
+ if other is None:
+ pass
+ elif hasattr(other, "iteritems"):
+ # Use getattr to avoid interference from 2to3.
+ for k, v in getattr(other, "iteritems")():
+ self[k] = v
+ elif hasattr(other, "items"):
+ # Use getattr to avoid interference from 2to3.
+ for k, v in getattr(other, "items")():
+ self[k] = v
+ elif hasattr(other, "keys"):
+ for k in other.keys():
+ self[k] = other[k]
+ else:
+ for k, v in other:
+ self[k] = v
+ if kwargs:
+ self.update(kwargs)
+
+ def __getitem__(self, k):
+ try:
+ return getattr(self, self._prefix + k)
+ except AttributeError:
+ raise KeyError(k)
+
+ def get(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def __contains__(self, k):
+ return hasattr(self, self._prefix + k)
+
+ def pop(self, key, *args):
+ if len(args) > 1:
+ raise TypeError(
+ "pop expected at most 2 arguments, got " + repr(1 + len(args))
+ )
+ try:
+ value = self[key]
+ except KeyError:
+ if args:
+ return args[0]
+ raise
+ del self[key]
+ return value
+
+ def popitem(self):
+ try:
+ k, v = self.iteritems().next()
+ except StopIteration:
+ raise KeyError("container is empty")
+ del self[k]
+ return (k, v)
+
+ def copy(self):
+ c = self.__class__()
+ c.update(self)
+ return c
+
+ def clear(self):
+ for k in self.allowed_keys:
+ try:
+ delattr(self, self._prefix + k)
+ except AttributeError:
+ pass
+
+ def __str__(self):
+ return str(dict(self.iteritems()))
+
+ def __repr__(self):
+ return repr(dict(self.iteritems()))
+
+ items = iteritems
+ keys = __iter__
+ values = itervalues
+
+
+class _PickledSlotDict(_SlotDict):
+ """
+ Since LocalSlotDict instances are not directly picklable, this
+ class exists as a way to express pickled LocalSlotDict instances,
+ using a plain __dict__ instead of custom __slots__.
+ """
+
+ def __init__(self, prefix, allowed_keys, *args, **kwargs):
+ self._prefix = prefix
+ self.allowed_keys = allowed_keys
+ super().__init__(*args, **kwargs)
+
+
_slot_dict_classes = weakref.WeakValueDictionary()
@@ -294,152 +462,15 @@ def slot_dict_class(keys, prefix="_val_"):
keys_set = keys
else:
keys_set = frozenset(keys)
- v = _slot_dict_classes.get((keys_set, prefix))
+ cache_key = (keys_set, prefix)
+ v = _slot_dict_classes.get(cache_key)
if v is None:
- class SlotDict:
-
+ class LocalSlotDict(_SlotDict):
allowed_keys = keys_set
_prefix = prefix
- __slots__ = ("__weakref__",) + tuple(prefix + k for k in allowed_keys)
-
- def __init__(self, *args, **kwargs):
-
- if len(args) > 1:
- raise TypeError(
- "expected at most 1 positional argument, got " + repr(len(args))
- )
-
- if args:
- self.update(args[0])
-
- if kwargs:
- self.update(kwargs)
-
- def __iter__(self):
- for k, v in self.iteritems():
- yield k
-
- def __len__(self):
- l = 0
- for i in self.iteritems():
- l += 1
- return l
-
- def iteritems(self):
- prefix = self._prefix
- for k in self.allowed_keys:
- try:
- yield (k, getattr(self, prefix + k))
- except AttributeError:
- pass
-
- def itervalues(self):
- for k, v in self.iteritems():
- yield v
-
- def __delitem__(self, k):
- try:
- delattr(self, self._prefix + k)
- except AttributeError:
- raise KeyError(k)
-
- def __setitem__(self, k, v):
- setattr(self, self._prefix + k, v)
-
- def setdefault(self, key, default=None):
- try:
- return self[key]
- except KeyError:
- self[key] = default
- return default
-
- def update(self, *args, **kwargs):
- if len(args) > 1:
- raise TypeError(
- "expected at most 1 positional argument, got " + repr(len(args))
- )
- other = None
- if args:
- other = args[0]
- if other is None:
- pass
- elif hasattr(other, "iteritems"):
- # Use getattr to avoid interference from 2to3.
- for k, v in getattr(other, "iteritems")():
- self[k] = v
- elif hasattr(other, "items"):
- # Use getattr to avoid interference from 2to3.
- for k, v in getattr(other, "items")():
- self[k] = v
- elif hasattr(other, "keys"):
- for k in other.keys():
- self[k] = other[k]
- else:
- for k, v in other:
- self[k] = v
- if kwargs:
- self.update(kwargs)
-
- def __getitem__(self, k):
- try:
- return getattr(self, self._prefix + k)
- except AttributeError:
- raise KeyError(k)
-
- def get(self, key, default=None):
- try:
- return self[key]
- except KeyError:
- return default
-
- def __contains__(self, k):
- return hasattr(self, self._prefix + k)
-
- def pop(self, key, *args):
- if len(args) > 1:
- raise TypeError(
- "pop expected at most 2 arguments, got " + repr(1 + len(args))
- )
- try:
- value = self[key]
- except KeyError:
- if args:
- return args[0]
- raise
- del self[key]
- return value
-
- def popitem(self):
- try:
- k, v = self.iteritems().next()
- except StopIteration:
- raise KeyError("container is empty")
- del self[k]
- return (k, v)
-
- def copy(self):
- c = self.__class__()
- c.update(self)
- return c
-
- def clear(self):
- for k in self.allowed_keys:
- try:
- delattr(self, self._prefix + k)
- except AttributeError:
- pass
-
- def __str__(self):
- return str(dict(self.iteritems()))
-
- def __repr__(self):
- return repr(dict(self.iteritems()))
-
- items = iteritems
- keys = __iter__
- values = itervalues
-
- v = SlotDict
- _slot_dict_classes[v.allowed_keys] = v
+ __slots__ = tuple(prefix + k for k in allowed_keys)
+
+ v = LocalSlotDict
+ _slot_dict_classes[cache_key] = v
return v