From bae7244400682543b8b93dd59bd2e5f6fc893ab5 Mon Sep 17 00:00:00 2001
From: xywei <wxy0516@gmail.com>
Date: Mon, 25 May 2020 10:16:54 -0500
Subject: [PATCH] Add mypy ci job

---
 .gitlab-ci.yml   |  9 +++++++++
 pytato/array.py  | 11 +++++------
 pytato/typing.py | 45 ++++++++++++++++++++++++++++++++++++++++++---
 run-mypy.sh      |  3 +++
 setup.cfg        |  6 ++++++
 5 files changed, 65 insertions(+), 9 deletions(-)
 create mode 100644 run-mypy.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 510eba8..ad24891 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,6 +34,15 @@ Flake8:
   except:
   - tags
 
+Mypy:
+  script:
+  - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-mypy.sh
+  - ". ./prepare-and-run-mypy.sh python3 mypy"
+  tags:
+  - python3
+  except:
+  - tags
+
 Documentation:
   script:
   - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-docs.sh
diff --git a/pytato/array.py b/pytato/array.py
index b2eefd1..1f6f268 100644
--- a/pytato/array.py
+++ b/pytato/array.py
@@ -156,11 +156,11 @@ class Array(ptype.ArrayInterface):
         purposefully so.
     """
 
-    def __init__(self, namespace: Namespace,
+    def __init__(self, namespace: ptype.NamespaceInterface,
                  name: Optional[ptype.NameType],
                  tags: Optional[ptype.TagsType] = None):
-        assert ptype.check_name(name)
-        assert ptype.check_tags(tags)
+        assert (name is None) or ptype.check_name(name)
+        assert (tags is None) or ptype.check_tags(tags)
 
         if tags is None:
             tags = {}
@@ -195,7 +195,7 @@ class Array(ptype.ArrayInterface):
             pass
 
     def without_tag(self, dotted_name: DottedName):
-        pass
+        raise NotImplementedError
 
     def with_name(self, name: ptype.NameType):
         assert ptype.check_name(name)
@@ -235,8 +235,7 @@ class DictOfNamedArrays(collections.abc.Mapping):
     def namespace(self):
         return single_valued(ary.namespace for ary in self._data.values())
 
-    def __contains__(self, name: ptype.NameType):
-        assert ptype.check_name(name)
+    def __contains__(self, name: object):
         return name in self._data
 
     def __getitem__(self, name: ptype.NameType):
diff --git a/pytato/typing.py b/pytato/typing.py
index 27f07f5..fbc94c5 100644
--- a/pytato/typing.py
+++ b/pytato/typing.py
@@ -26,11 +26,12 @@ THE SOFTWARE.
 
 __doc__ = """Interface classes and type specifications.
 Each type is paired with a check_* function that, when used together, achieves
-contracts-like functionality."""
+contracts-like functionality.
+"""
 
 import re
 from pymbolic.primitives import Expression
-from abc import ABC
+from abc import ABC, abstractmethod
 from typing import Optional, Union, Dict, Tuple
 
 # {{{ abstract classes
@@ -39,6 +40,10 @@ from typing import Optional, Union, Dict, Tuple
 class NamespaceInterface():
     __metaclass__ = ABC
 
+    @abstractmethod
+    def assign(self, name, value):
+        pass
+
 
 class TagInterface():
     __metaclass__ = ABC
@@ -49,6 +54,40 @@ class ArrayInterface():
     """
     __metaclass__ = ABC
 
+    @property
+    def namespace(self):
+        return self._namespace
+
+    @namespace.setter
+    def namespace(self, val: NamespaceInterface):
+        self._namespace = val
+
+    @property
+    @abstractmethod
+    def ndim(self):
+        pass
+
+    @property
+    @abstractmethod
+    def shape(self):
+        pass
+
+    @abstractmethod
+    def copy(self, **kwargs):
+        pass
+
+    @abstractmethod
+    def with_tag(self, tag_key, tag_val):
+        pass
+
+    @abstractmethod
+    def without_tag(self, tag_key):
+        pass
+
+    @abstractmethod
+    def with_name(self, name):
+        pass
+
 # }}} End abstract classes
 
 # {{{ name type
@@ -91,7 +130,7 @@ def check_shape(shape: ShapeType,
             assert s > 0, f"size parameter must be positive (got {s})"
         elif isinstance(s, str):
             assert check_name(s)
-        elif isinstance(Expression) and ns is not None:
+        elif isinstance(s, Expression) and ns is not None:
             # TODO: check expression in namespace
             pass
     return True
diff --git a/run-mypy.sh b/run-mypy.sh
new file mode 100644
index 0000000..14730b1
--- /dev/null
+++ b/run-mypy.sh
@@ -0,0 +1,3 @@
+#! /bin/bash
+
+mypy --strict pytato
diff --git a/setup.cfg b/setup.cfg
index 07d5743..a8663c0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,9 @@
 [flake8]
 ignore = E126,E127,E128,E123,E226,E241,E242,E265,N802,W503,E402,N814,N817,W504
 max-line-length=85
+
+[mypy-pymbolic.primitives]
+ignore_missing_imports = True
+
+[mypy-pytools]
+ignore_missing_imports = True
-- 
GitLab