From 3cfdb8e184e0178a26c371a20cc0a2f161eea1b7 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Sat, 26 Jun 2021 23:58:37 -0500
Subject: [PATCH] Deprecate FEM transform metadata, move to
 actx.transform_metadata

---
 arraycontext/__init__.py               | 41 ++++++++++++++++--
 arraycontext/impl/pyopencl/__init__.py |  7 ++-
 arraycontext/metadata.py               | 49 +++++++++++----------
 arraycontext/transform_metadata.py     | 59 ++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 27 deletions(-)
 create mode 100644 arraycontext/transform_metadata.py

diff --git a/arraycontext/__init__.py b/arraycontext/__init__.py
index f94fb81..e5ae4a0 100644
--- a/arraycontext/__init__.py
+++ b/arraycontext/__init__.py
@@ -28,9 +28,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 """
 
+import sys
 from .context import ArrayContext
 
-from .metadata import CommonSubexpressionTag, FirstAxisIsElementsTag
+from .transform_metadata import (CommonSubexpressionTag,
+        ElementwiseMapKernelTag)
+
+# deprecated, remove in 2022.
+from .metadata import _FirstAxisIsElementsTag
 
 from .container import (
         ArrayContainer,
@@ -64,7 +69,7 @@ __all__ = (
         "ArrayContext",
 
         "CommonSubexpressionTag",
-        "FirstAxisIsElementsTag",
+        "ElementwiseMapKernelTag",
 
         "ArrayContainer",
         "is_array_container", "is_array_container_type",
@@ -90,7 +95,9 @@ __all__ = (
         )
 
 
-def _acf():
+# {{{ deprecation handling
+
+def _deprecated_acf():
     """A tiny undocumented function to pass to tests that take an ``actx_factory``
     argument when running them from the command line.
     """
@@ -100,4 +107,32 @@ def _acf():
     queue = cl.CommandQueue(context)
     return PyOpenCLArrayContext(queue)
 
+
+_depr_name_to_replacement_and_obj = {
+        "FirstAxisIsElementsTag":
+        ("meshmode.transform_metadata.FirstAxisIsElementsTag",
+            _FirstAxisIsElementsTag),
+        "_acf":
+        ("<no replacement yet>", _deprecated_acf),
+        }
+
+if sys.version_info >= (3, 7):
+    def __getattr__(name):
+        replacement_and_obj = _depr_name_to_replacement_and_obj.get(name, None)
+        if replacement_and_obj is not None:
+            replacement, obj = replacement_and_obj
+            from warnings import warn
+            warn(f"'arraycontext.{name}' is deprecated. "
+                    f"Use '{replacement}' instead. "
+                    f"'arraycontext.{name}' will continue to work until 2022.",
+                    DeprecationWarning, stacklevel=2)
+            return obj
+        else:
+            raise AttributeError(name)
+else:
+    FirstAxisIsElementsTag = _FirstAxisIsElementsTag
+    _acf = _deprecated_acf
+
+# }}}
+
 # vim: foldmethod=marker
diff --git a/arraycontext/impl/pyopencl/__init__.py b/arraycontext/impl/pyopencl/__init__.py
index ca37732..b29fd33 100644
--- a/arraycontext/impl/pyopencl/__init__.py
+++ b/arraycontext/impl/pyopencl/__init__.py
@@ -34,7 +34,6 @@ import numpy as np
 
 from pytools.tag import Tag
 
-from arraycontext.metadata import FirstAxisIsElementsTag
 from arraycontext.context import ArrayContext
 
 
@@ -223,9 +222,13 @@ class PyOpenCLArrayContext(ArrayContext):
         all_inames = default_entrypoint.all_inames()
         # FIXME: This could be much smarter.
         inner_iname = None
+
+        # import with underscore to avoid DeprecationWarning
+        from arraycontext.metadata import _FirstAxisIsElementsTag
+
         if (len(default_entrypoint.instructions) == 1
                 and isinstance(default_entrypoint.instructions[0], lp.Assignment)
-                and any(isinstance(tag, FirstAxisIsElementsTag)
+                and any(isinstance(tag, _FirstAxisIsElementsTag)
                     # FIXME: Firedrake branch lacks kernel tags
                     for tag in getattr(default_entrypoint, "tags", ()))):
             stmt, = default_entrypoint.instructions
diff --git a/arraycontext/metadata.py b/arraycontext/metadata.py
index 1713cd1..6291a86 100644
--- a/arraycontext/metadata.py
+++ b/arraycontext/metadata.py
@@ -1,8 +1,3 @@
-"""
-.. autoclass:: CommonSubexpressionTag
-.. autoclass:: FirstAxisIsElementsTag
-"""
-
 __copyright__ = """
 Copyright (C) 2020-1 University of Illinois Board of Trustees
 """
@@ -27,24 +22,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 """
 
+import sys
 from pytools.tag import Tag
-
-
-# {{{ program metadata
-
-class CommonSubexpressionTag(Tag):
-    """A tag that is applicable to arrays indicating that this same array
-    may be evaluated multiple times, and that the implementation should
-    eliminate those redundant evaluations if possible.
-    """
-
-
-class FirstAxisIsElementsTag(Tag):
-    """A tag that is applicable to array outputs indicating that the
-    first index corresponds to element indices. This suggests that
-    the implementation should set element indices as the outermost
-    loop extent.
-    """
+from warnings import warn
+
+
+# {{{ deprecation handling
+
+try:
+    from meshmode.transform_metadata import FirstAxisIsElementsTag \
+            as _FirstAxisIsElementsTag
+except ImportError:
+    # placeholder in case meshmode is too old to have it.
+    class _FirstAxisIsElementsTag(Tag):  # type: ignore[no-redef]
+        pass
+
+
+if sys.version_info >= (3, 7):
+    def __getattr__(name):
+        if name == "FirstAxisIsElementsTag":
+            warn(f"'arraycontext.{name}' is deprecated. "
+                    f"Use 'meshmode.transform_metadata.{name}' instead. "
+                    f"'arraycontext.{name}' will continue to work until 2022.",
+                    DeprecationWarning, stacklevel=2)
+            return _FirstAxisIsElementsTag
+        else:
+            raise AttributeError(name)
+else:
+    FirstAxisIsElementsTag = _FirstAxisIsElementsTag
 
 # }}}
 
diff --git a/arraycontext/transform_metadata.py b/arraycontext/transform_metadata.py
new file mode 100644
index 0000000..2e0942e
--- /dev/null
+++ b/arraycontext/transform_metadata.py
@@ -0,0 +1,59 @@
+"""
+.. currentmodule:: arraycontext
+
+.. autoclass:: CommonSubexpressionTag
+.. autoclass:: ElementwiseMapKernelTag
+"""
+
+__copyright__ = """
+Copyright (C) 2020-1 University of Illinois Board of Trustees
+"""
+
+__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.
+"""
+
+from pytools.tag import Tag
+
+
+# {{{ program metadata
+
+class CommonSubexpressionTag(Tag):
+    """A tag that is applicable to arrays indicating that this same array
+    may be evaluated multiple times, and that the implementation should
+    eliminate those redundant evaluations if possible.
+    """
+
+
+class ElementwiseMapKernelTag(Tag):
+    """A tag that applies to :class:`loopy.LoopKernel` indicating that the kernel
+    is a "map", i.e. that the output array(s) has/have the same shape as the
+    input array(s), and that each output element only depends on its corresponding
+    element(s) in the input array(s).
+
+    .. note::
+
+        "Element" here refers to a scalar element of an array, not an element
+        in a finite-element discretization.
+    """
+
+# }}}
+
+
+# vim: foldmethod=marker
-- 
GitLab