From 4d0c0190f92bc2d0b13e37f9e67028b49e9dd238 Mon Sep 17 00:00:00 2001 From: Christensen <njchris2@illinois.edu> Date: Sun, 4 Oct 2020 19:15:56 -0500 Subject: [PATCH] extract tag class out of pytato --- pytools/tag.py | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 pytools/tag.py diff --git a/pytools/tag.py b/pytools/tag.py new file mode 100644 index 0000000..0155e52 --- /dev/null +++ b/pytools/tag.py @@ -0,0 +1,90 @@ +from __future__ import annotations +from dataclasses import dataclass +from typing import (Tuple, Any, FrozenSet) + + + +# {{{ dotted name + +class DottedName: + """ + .. attribute:: name_parts + + A tuple of strings, each of which is a valid + Python identifier. No name part may start with + a double underscore. + + The name (at least morally) exists in the + name space defined by the Python module system. + It need not necessarily identify an importable + object. + + .. automethod:: from_class + """ + + def __init__(self, name_parts: Tuple[str, ...]): + if len(name_parts) == 0: + raise ValueError("empty name parts") + + for p in name_parts: + if not p.isidentifier(): + raise ValueError(f"{p} is not a Python identifier") + + self.name_parts = name_parts + + @classmethod + def from_class(cls, argcls: Any) -> DottedName: + name_parts = tuple( + [str(part) for part in argcls.__module__.split(".")] + + [str(argcls.__name__)]) + if not all(not npart.startswith("__") for npart in name_parts): + raise ValueError(f"some name parts of {'.'.join(name_parts)} " + "start with double underscores") + return cls(name_parts) + +# }}} + +# {{{ tag + +tag_dataclass = dataclass(init=True, eq=True, frozen=True, repr=True) + +@tag_dataclass +class Tag: + """ + Generic metadata, applied to, among other things, + instances of :class:`Array`. + + .. attribute:: tag_name + + A fully qualified :class:`DottedName` that reflects + the class name of the tag. + + Instances of this type must be immutable, hashable, + picklable, and have a reasonably concise :meth:`__repr__` + of the form ``dotted.name(attr1=value1, attr2=value2)``. + Positional arguments are not allowed. + + .. automethod:: __repr__ + + .. note:: + + This mirrors the tagging scheme that :mod:`loopy` + is headed towards. + """ + + @property + def tag_name(self) -> DottedName: + return DottedName.from_class(type(self)) + + +class UniqueTag(Tag): + """ + Only one instance of this type of tag may be assigned + to a single tagged object. + """ + pass + + +TagsType = FrozenSet[Tag] + +# }}} -- GitLab