diff --git a/pytools/__init__.py b/pytools/__init__.py index 225e2dfadcb2ba69aa8960d7266031eecd1b3d6f..b3ce8a18b206f62cab0e9c2c89c7933a043ca4f3 100644 --- a/pytools/__init__.py +++ b/pytools/__init__.py @@ -2311,8 +2311,14 @@ class UniqueNameGenerator: """ pass - def add_name(self, name: str) -> None: - if self.is_name_conflicting(name): + def add_name(self, name: str, *, conflicting_ok: bool = False) -> None: + """ + :arg conflicting_ok: A flag to dictate the behavior when *name* is + conflicting with the set of existing names. If *True*, a conflict + is silently passed. If *False*, a :class:`ValueError` is raised on + encountering a conflict. + """ + if (not conflicting_ok) and self.is_name_conflicting(name): raise ValueError(f"name '{name}' conflicts with existing names") if not name.startswith(self.forced_prefix): @@ -2323,9 +2329,14 @@ class UniqueNameGenerator: self.existing_names.add(name) self._name_added(name) - def add_names(self, names: Iterable[str]) -> None: + def add_names(self, names: Iterable[str], + *, + conflicting_ok: bool = False) -> None: + """ + :arg conflicting_ok: Plainly passed to :meth:`UniqueNameGenerator.add_name`. + """ for name in names: - self.add_name(name) + self.add_name(name, conflicting_ok=conflicting_ok) def __call__(self, based_on: str = "id") -> str: based_on = self.forced_prefix + based_on diff --git a/test/test_pytools.py b/test/test_pytools.py index 18dd44485f5fb89a521a605dc441c65e9b9842bf..d53394269c12085a19a27e51c61c1d635efddcb1 100644 --- a/test/test_pytools.py +++ b/test/test_pytools.py @@ -652,6 +652,18 @@ def test_sphere_sampling(sampling, visualize=False): # }}} +def test_unique_name_gen_conflicting_ok(): + from pytools import UniqueNameGenerator + + ung = UniqueNameGenerator() + ung.add_names({"a", "b", "c"}) + + with pytest.raises(ValueError): + ung.add_names({"a"}) + + ung.add_names({"a", "b", "c"}, conflicting_ok=True) + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1])