diff options
Diffstat (limited to 'lib/portage/cache/mappings.py')
-rw-r--r-- | lib/portage/cache/mappings.py | 329 |
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 |