lang.py: make HashableMap generic, and use in Spec (#50229)

This commit is contained in:
Harmen Stoppels 2025-05-05 10:45:11 +02:00 committed by GitHub
parent 7cd039d022
commit 02501bc4af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 19 additions and 21 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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:

View File

@ -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."""