lang.py: make HashableMap generic, and use in Spec (#50229)
This commit is contained in:
parent
7cd039d022
commit
02501bc4af
@ -225,10 +225,14 @@ def setup(sphinx):
|
|||||||
("py:class", "llnl.util.lang.T"),
|
("py:class", "llnl.util.lang.T"),
|
||||||
("py:class", "llnl.util.lang.KT"),
|
("py:class", "llnl.util.lang.KT"),
|
||||||
("py:class", "llnl.util.lang.VT"),
|
("py:class", "llnl.util.lang.VT"),
|
||||||
|
("py:class", "llnl.util.lang.K"),
|
||||||
|
("py:class", "llnl.util.lang.V"),
|
||||||
("py:class", "llnl.util.lang.ClassPropertyType"),
|
("py:class", "llnl.util.lang.ClassPropertyType"),
|
||||||
("py:obj", "llnl.util.lang.KT"),
|
("py:obj", "llnl.util.lang.KT"),
|
||||||
("py:obj", "llnl.util.lang.VT"),
|
("py:obj", "llnl.util.lang.VT"),
|
||||||
("py:obj", "llnl.util.lang.ClassPropertyType"),
|
("py:obj", "llnl.util.lang.ClassPropertyType"),
|
||||||
|
("py:obj", "llnl.util.lang.K"),
|
||||||
|
("py:obj", "llnl.util.lang.V"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
Dict,
|
Dict,
|
||||||
Generic,
|
Generic,
|
||||||
Iterable,
|
Iterable,
|
||||||
|
Iterator,
|
||||||
List,
|
List,
|
||||||
Mapping,
|
Mapping,
|
||||||
Optional,
|
Optional,
|
||||||
@ -436,46 +437,39 @@ def add_func_to_class(name, func):
|
|||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
|
||||||
|
K = TypeVar("K")
|
||||||
|
V = TypeVar("V")
|
||||||
|
|
||||||
|
|
||||||
@lazy_lexicographic_ordering
|
@lazy_lexicographic_ordering
|
||||||
class HashableMap(collections.abc.MutableMapping):
|
class HashableMap(typing.MutableMapping[K, V]):
|
||||||
"""This is a hashable, comparable dictionary. Hash is performed on
|
"""This is a hashable, comparable dictionary. Hash is performed on
|
||||||
a tuple of the values in the dictionary."""
|
a tuple of the values in the dictionary."""
|
||||||
|
|
||||||
__slots__ = ("dict",)
|
__slots__ = ("dict",)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.dict = {}
|
self.dict: Dict[K, V] = {}
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key: K) -> V:
|
||||||
return self.dict[key]
|
return self.dict[key]
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key: K, value: V) -> None:
|
||||||
self.dict[key] = value
|
self.dict[key] = value
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self) -> Iterator[K]:
|
||||||
return iter(self.dict)
|
return iter(self.dict)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self) -> int:
|
||||||
return len(self.dict)
|
return len(self.dict)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key: K) -> None:
|
||||||
del self.dict[key]
|
del self.dict[key]
|
||||||
|
|
||||||
def _cmp_iter(self):
|
def _cmp_iter(self):
|
||||||
for _, v in sorted(self.items()):
|
for _, v in sorted(self.items()):
|
||||||
yield v
|
yield v
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
"""Type-agnostic clone method. Preserves subclass type."""
|
|
||||||
# Construct a new dict of my type
|
|
||||||
self_type = type(self)
|
|
||||||
clone = self_type()
|
|
||||||
|
|
||||||
# Copy everything from this dict into it.
|
|
||||||
for key in self:
|
|
||||||
clone[key] = self[key].copy()
|
|
||||||
return clone
|
|
||||||
|
|
||||||
|
|
||||||
def match_predicate(*args):
|
def match_predicate(*args):
|
||||||
"""Utility function for making string matching predicates.
|
"""Utility function for making string matching predicates.
|
||||||
|
@ -2492,7 +2492,7 @@ def _spec_clauses(
|
|||||||
# TODO: variant="*" means 'variant is defined to something', which used to
|
# TODO: variant="*" means 'variant is defined to something', which used to
|
||||||
# be meaningless in concretization, as all variants had to be defined. But
|
# be meaningless in concretization, as all variants had to be defined. But
|
||||||
# now that variants can be conditional, it should force a variant to exist.
|
# now that variants can be conditional, it should force a variant to exist.
|
||||||
if variant.value == ("*",):
|
if not variant.values:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for value in variant.values:
|
for value in variant.values:
|
||||||
|
@ -837,7 +837,7 @@ def _shared_subset_pair_iterate(container1, container2):
|
|||||||
b_idx += 1
|
b_idx += 1
|
||||||
|
|
||||||
|
|
||||||
class FlagMap(lang.HashableMap):
|
class FlagMap(lang.HashableMap[str, List[CompilerFlag]]):
|
||||||
__slots__ = ("spec",)
|
__slots__ = ("spec",)
|
||||||
|
|
||||||
def __init__(self, spec):
|
def __init__(self, spec):
|
||||||
@ -4490,7 +4490,7 @@ def has_virtual_dependency(self, virtual: str) -> bool:
|
|||||||
return bool(self.dependencies(virtuals=(virtual,)))
|
return bool(self.dependencies(virtuals=(virtual,)))
|
||||||
|
|
||||||
|
|
||||||
class VariantMap(lang.HashableMap):
|
class VariantMap(lang.HashableMap[str, vt.VariantValue]):
|
||||||
"""Map containing variant instances. New values can be added only
|
"""Map containing variant instances. New values can be added only
|
||||||
if the key is not already present."""
|
if the key is not already present."""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user