Mercurial > hg
diff mercurial/thirdparty/jaraco/collections.py @ 50408:82e5a9b1ef1e
extras: re-use Projection from jaraco.collections
author | Jason R. Coombs <jaraco@jaraco.com> |
---|---|
date | Tue, 21 Mar 2023 20:47:30 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/thirdparty/jaraco/collections.py Tue Mar 21 20:47:30 2023 -0400 @@ -0,0 +1,56 @@ +# adapted from jaraco.collections 3.9 + +import collections + + +class Projection(collections.abc.Mapping): + """ + Project a set of keys over a mapping + + >>> sample = {'a': 1, 'b': 2, 'c': 3} + >>> prj = Projection(['a', 'c', 'd'], sample) + >>> prj == {'a': 1, 'c': 3} + True + + Keys should only appear if they were specified and exist in the space. + + >>> sorted(list(prj.keys())) + ['a', 'c'] + + Attempting to access a key not in the projection + results in a KeyError. + + >>> prj['b'] + Traceback (most recent call last): + ... + KeyError: 'b' + + Use the projection to update another dict. + + >>> target = {'a': 2, 'b': 2} + >>> target.update(prj) + >>> target == {'a': 1, 'b': 2, 'c': 3} + True + + Also note that Projection keeps a reference to the original dict, so + if you modify the original dict, that could modify the Projection. + + >>> del sample['a'] + >>> dict(prj) + {'c': 3} + """ + + def __init__(self, keys, space): + self._keys = tuple(keys) + self._space = space + + def __getitem__(self, key): + if key not in self._keys: + raise KeyError(key) + return self._space[key] + + def __iter__(self): + return iter(set(self._keys).intersection(self._space)) + + def __len__(self): + return len(tuple(iter(self)))