diff --git a/doc/conf.py b/doc/conf.py index dea64997c5c73f553104c1f7d214f6181d209f87..89834add8f44768b812d513af75f5a6dbebc2a24 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -180,4 +180,5 @@ intersphinx_mapping = { "https://docs.python.org/3": None, "https://numpy.org/doc/stable": None, "https://documen.tician.de/pymbolic/": None, + "https://documen.tician.de/loopy/": None, } diff --git a/doc/index.rst b/doc/index.rst index 24e1d66373b8112d03b8ae9bc8ff343e50622ce8..1088516f820e07ea09eef446ea53e00e883ab0fb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,6 +9,7 @@ Welcome to pytools's documentation! obj_array persistent_dict graph + tag codegen misc diff --git a/doc/tag.rst b/doc/tag.rst new file mode 100644 index 0000000000000000000000000000000000000000..fddab855ee1c70b74fb2c440b0059d34a7f95445 --- /dev/null +++ b/doc/tag.rst @@ -0,0 +1 @@ +.. automodule:: pytools.tag diff --git a/pytools/tag.py b/pytools/tag.py new file mode 100644 index 0000000000000000000000000000000000000000..e9a4cc69f766d0379bdc01334f2f5d40c30c7cc0 --- /dev/null +++ b/pytools/tag.py @@ -0,0 +1,133 @@ +from dataclasses import dataclass +from typing import Tuple, Any, FrozenSet + +__copyright__ = """ +Copyright (C) 2020 Andreas Kloeckner +Copyright (C) 2020 Matt Wala +Copyright (C) 2020 Xiaoyu Wei +""" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +# {{{ docs + +__doc__ = """ + +Tag Interface +--------------- + +.. autoclass:: Tag +.. autoclass:: UniqueTag + +Supporting Functionality +------------------------ + +.. autoclass:: DottedName + +""" + +# }}} + + +# {{{ 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, + pytato Arrays. + + .. 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__ + """ + + @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] + +# }}} + +# vim: foldmethod=marker diff --git a/pytools/version.py b/pytools/version.py index 2eb5614b1d13233f1a7ec3916f74603ab1b42b0a..77929bc6e5749dadb2aa46036e6b47b379abe0f2 100644 --- a/pytools/version.py +++ b/pytools/version.py @@ -1,3 +1,3 @@ -VERSION = (2020, 4, 1) +VERSION = (2020, 4, 2) VERSION_STATUS = "" VERSION_TEXT = ".".join(str(x) for x in VERSION) + VERSION_STATUS diff --git a/setup.py b/setup.py index 48356c77060bbfa14a4228c75b5baa875729c765..21f2204bf7657940df987d139e57ed568320c66f 100644 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ setup(name="pytools", "appdirs>=1.4.0", "six>=1.8.0", "numpy>=1.6.0", + "dataclasses>=0.7;python_version<='3.6'" ], package_data={"pytools": ["py.typed"]},