]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Setup mypy 1247/head
authorTeymour Aldridge <teymour.aldridge@icloud.com>
Fri, 26 Jun 2020 14:22:21 +0000 (15:22 +0100)
committerTeymour Aldridge <teymour.aldridge@icloud.com>
Tue, 28 Jul 2020 21:32:34 +0000 (22:32 +0100)
* Add missing type hints (these are intended as an initial set of type hints, to be added upon and improved later)
* Setup MyPy to run as a Github Action

15 files changed:
.github/workflows/tests.yaml
.gitignore
setup.cfg
src/jinja2/compiler.py
src/jinja2/environment.py
src/jinja2/ext.py
src/jinja2/filters.py
src/jinja2/nativetypes.py
src/jinja2/nodes.py
src/jinja2/runtime.py
src/jinja2/sandbox.py
tests/test_api.py
tests/test_asyncfilters.py
tests/test_ext.py
tox.ini

index a826fda6c79b35548011f5952ef5e46ab3d955d0..6fbd29664fc996fccfae029e62d654666d91bf29 100644 (file)
@@ -22,6 +22,7 @@ jobs:
           - {name: 'PyPy', python: pypy3, os: ubuntu-latest, tox: pypy3}
           - {name: Style, python: '3.8', os: ubuntu-latest, tox: style}
           - {name: Docs, python: '3.8', os: ubuntu-latest, tox: docs}
+          - {name: Typing, python: '3.8', os: ubuntu-latest, tox: mypy}
           - {name: Windows, python: '3.8', os: windows-latest, tox: py38}
           - {name: Mac, python: '3.8', os: macos-latest, tox: py38}
     steps:
index 81752e0e9eb797e860ae41074c9a8ff1f1b58881..86b119b6920e28ff6e3d1bf1752e846b6bc7656e 100644 (file)
@@ -18,3 +18,4 @@ venv-*/
 htmlcov
 .pytest_cache/
 /.vscode/
+.mypy_cache
index 5d3d02ee5c95e02c47837b87c790383151cc609e..27f24beb2bd87b0931367d642807fb030e4be892 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -40,3 +40,22 @@ max-line-length = 80
 per-file-ignores =
     # __init__ module exports names
     src/jinja2/__init__.py: F401
+
+[mypy]
+allow_redefinition = True
+disallow_subclassing_any = True
+# disallow_untyped_defs = True
+strict_equality = True
+strict_optional = False
+warn_redundant_casts = True
+warn_unused_configs = True
+warn_unused_ignores = True
+
+[mypy-_pytest.*]
+ignore_missing_imports = True
+
+[mypy-pytest.*]
+ignore_missing_imports = True
+
+[mypy-requests_unixsocket.*]
+ignore_missing_imports = True
index abdbe6da65f92c45457e25b0c2d773db8a7cf770..251aec6e4f216aca314324f2443d27852f1b9382 100644 (file)
@@ -1512,18 +1512,18 @@ class CodeGenerator(NodeVisitor):
 
         return visitor
 
-    visit_Add = binop("+")
-    visit_Sub = binop("-")
-    visit_Mul = binop("*")
-    visit_Div = binop("/")
-    visit_FloorDiv = binop("//")
-    visit_Pow = binop("**")
-    visit_Mod = binop("%")
-    visit_And = binop("and", interceptable=False)
-    visit_Or = binop("or", interceptable=False)
-    visit_Pos = uaop("+")
-    visit_Neg = uaop("-")
-    visit_Not = uaop("not ", interceptable=False)
+    visit_Add = binop("+")  # type:ignore
+    visit_Sub = binop("-")  # type:ignore
+    visit_Mul = binop("*")  # type:ignore
+    visit_Div = binop("/")  # type:ignore
+    visit_FloorDiv = binop("//")  # type:ignore
+    visit_Pow = binop("**")  # type:ignore
+    visit_Mod = binop("%")  # type:ignore
+    visit_And = binop("and", interceptable=False)  # type:ignore
+    visit_Or = binop("or", interceptable=False)  # type:ignore
+    visit_Pos = uaop("+")  # type:ignore
+    visit_Neg = uaop("-")  # type:ignore
+    visit_Not = uaop("not ", interceptable=False)  # type:ignore
     del binop, uaop
 
     @optimizeconst
index 556f7255f051e67dbf7805c0b3c6a4376888531e..5201bbc1fa6da3cbf938fb3a0afe0ca28e8b7873 100644 (file)
@@ -6,6 +6,7 @@ import sys
 import weakref
 from functools import partial
 from functools import reduce
+from typing import Any
 
 from markupsafe import Markup
 
@@ -271,10 +272,12 @@ class Environment:
     #: :class:`~jinja2.compiler.CodeGenerator` for more information.
     code_generator_class = CodeGenerator
 
-    #: the context class thatis used for templates.  See
+    #: the context class that is used for templates.  See
     #: :class:`~jinja2.runtime.Context` for more information.
     context_class = Context
 
+    template_class = Any
+
     def __init__(
         self,
         block_start_string=BLOCK_START_STRING,
index 533ff1795afa74fc14c3612c4b0c95ebc675e76c..4b89cf40a5bfcfab853f2abe82d9694cf3abd55e 100644 (file)
@@ -2,6 +2,7 @@
 import pprint
 import re
 from sys import version_info
+from typing import Set
 
 from markupsafe import Markup
 
@@ -61,7 +62,7 @@ class Extension(metaclass=ExtensionRegistry):
     """
 
     #: if this extension parses this is the list of tags it's listening to.
-    tags = set()
+    tags: Set[str] = set()
 
     #: the priority of that extension.  This is especially useful for
     #: extensions that preprocess values.  A lower value means higher
index c257d4c5fc27db297b84ca907f7115d25f1eab9f..7a554a0e94f234bc99f7b287a220b031ff0bc168 100644 (file)
@@ -922,8 +922,8 @@ def do_round(value, precision=0, method="common"):
 # people start to print this out in comments or something similar for
 # debugging.
 _GroupTuple = namedtuple("_GroupTuple", ["grouper", "list"])
-_GroupTuple.__repr__ = tuple.__repr__
-_GroupTuple.__str__ = tuple.__str__
+_GroupTuple.__repr__ = tuple.__repr__  # type: ignore
+_GroupTuple.__str__ = tuple.__str__  # type: ignore
 
 
 @environmentfilter
index 5ecf72b598ce19f3dd0cf80c331e0c702c71d1b1..c71e033641b6f0523f4c2480396569dc8cddcea0 100644 (file)
@@ -1,6 +1,7 @@
 from ast import literal_eval
 from itertools import chain
 from itertools import islice
+from typing import Any
 
 from . import nodes
 from .compiler import CodeGenerator
@@ -70,6 +71,7 @@ class NativeEnvironment(Environment):
     """An environment that renders templates to native Python types."""
 
     code_generator_class = NativeCodeGenerator
+    template_class: Any
 
 
 class NativeTemplate(Template):
index d5133f759570a54b6937759ff756a154b00f7d98..95e7b73064ee21de02dad87e8fb4dbebbc509637 100644 (file)
@@ -4,6 +4,8 @@ to normalize nodes.
 """
 import operator
 from collections import deque
+from typing import Any
+from typing import Tuple as TupleType
 
 from markupsafe import Markup
 
@@ -105,7 +107,7 @@ class Node(metaclass=NodeType):
     all nodes automatically.
     """
 
-    fields = ()
+    fields: TupleType = ()
     attributes = ("lineno", "environment")
     abstract = True
 
@@ -414,7 +416,7 @@ class BinExpr(Expr):
     """Baseclass for all binary expressions."""
 
     fields = ("left", "right")
-    operator = None
+    operator: Any = None
     abstract = True
 
     def as_const(self, eval_ctx=None):
@@ -436,7 +438,7 @@ class UnaryExpr(Expr):
     """Baseclass for all unary expressions."""
 
     fields = ("node",)
-    operator = None
+    operator: Any = None
     abstract = True
 
     def as_const(self, eval_ctx=None):
@@ -1048,5 +1050,5 @@ def _failing_new(*args, **kwargs):
     raise TypeError("can't create custom node types")
 
 
-NodeType.__new__ = staticmethod(_failing_new)
+NodeType.__new__ = staticmethod(_failing_new)  # type: ignore
 del _failing_new
index 7b5925b16245fc1b5f1a973104f9f08f5ab04b5c..950f620d44249f50737fa1f2591b33f3332a9ab8 100644 (file)
@@ -308,6 +308,7 @@ class Context(metaclass=ContextMeta):
         context.blocks.update((k, list(v)) for k, v in self.blocks.items())
         return context
 
+    # ignore: true
     def _all(meth):  # noqa: B902
         def proxy(self):
             return getattr(self.get_all(), meth)()
@@ -316,9 +317,9 @@ class Context(metaclass=ContextMeta):
         proxy.__name__ = meth
         return proxy
 
-    keys = _all("keys")
-    values = _all("values")
-    items = _all("items")
+    keys = _all("keys")  # type:ignore
+    values = _all("values")  # type:ignore
+    items = _all("items")  # type:ignore
     del _all
 
     def __contains__(self, name):
index 5c6d09461bdc896c0abd80388c02bb2dda02851d..6311a5dd14eccfd038b2d5948f26adab0101cb9b 100644 (file)
@@ -3,10 +3,12 @@ Useful when the template itself comes from an untrusted source.
 """
 import operator
 import types
-from _string import formatter_field_name_split
+from _string import formatter_field_name_split  # type: ignore
 from collections import abc
 from collections import deque
 from string import Formatter
+from typing import FrozenSet
+from typing import Set
 
 from markupsafe import EscapeFormatter
 from markupsafe import Markup
@@ -18,10 +20,10 @@ from .exceptions import SecurityError
 MAX_RANGE = 100000
 
 #: Unsafe function attributes.
-UNSAFE_FUNCTION_ATTRIBUTES = set()
+UNSAFE_FUNCTION_ATTRIBUTES: Set = set()
 
 #: Unsafe method attributes. Function attributes are unsafe for methods too.
-UNSAFE_METHOD_ATTRIBUTES = set()
+UNSAFE_METHOD_ATTRIBUTES: Set = set()
 
 #: unsafe generator attributes.
 UNSAFE_GENERATOR_ATTRIBUTES = {"gi_frame", "gi_code"}
@@ -220,7 +222,7 @@ class SandboxedEnvironment(Environment):
     #: interested in.
     #:
     #: .. versionadded:: 2.6
-    intercepted_binops = frozenset()
+    intercepted_binops: FrozenSet = frozenset()
 
     #: a set of unary operators that should be intercepted.  Each operator
     #: that is added to this set (empty by default) is delegated to the
@@ -235,7 +237,7 @@ class SandboxedEnvironment(Environment):
     #: interested in.
     #:
     #: .. versionadded:: 2.6
-    intercepted_unops = frozenset()
+    intercepted_unops: FrozenSet = frozenset()
 
     def intercept_unop(self, operator):
         """Called during template compilation with the name of a unary
index 2679e8fb5dd1c71b741895fc3b23e384f251f265..4b6e0aed3d7974f0e0567e9bdb704cb3fbc7550a 100644 (file)
@@ -273,7 +273,7 @@ class TestUndefined:
         # function raises an AttributeError, printing the repr of the
         # object in the undefined message would cause a RecursionError.
         class Error:
-            @property
+            @property  # type: ignore
             def __class__(self):
                 raise AttributeError()
 
index 7c737c835e0846c0a57d7abff4a93a5aba49af4a..524a6d9db1c6080acb3b3e25b293fc903de7f759 100644 (file)
@@ -142,7 +142,7 @@ def test_bool_select(env_async, items):
     assert tmpl.render(items=items) == "1|2|3|4|5"
 
 
-def make_users():
+def make_users():  # type: ignore
     User = namedtuple("User", "name,is_active")
     return [
         User("john", True),
index 94d20bee45a719fb8198b6e7501e14caca58b4d4..61abdc5bd1bae7b960d107e59114329f34956699 100644 (file)
@@ -90,7 +90,9 @@ i18n_env_trimmed.globals.update(
 newstyle_i18n_env = Environment(
     loader=DictLoader(newstyle_i18n_templates), extensions=["jinja2.ext.i18n"]
 )
-newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+newstyle_i18n_env.install_gettext_callables(  # type: ignore
+    gettext, ngettext, newstyle=True
+)
 
 
 class ExampleExtension(Extension):
@@ -121,7 +123,7 @@ class ExampleExtension(Extension):
 
 
 class DerivedExampleExtension(ExampleExtension):
-    context_reference_node_cls = nodes.DerivedContextReference
+    context_reference_node_cls = nodes.DerivedContextReference  # type: ignore
 
 
 class PreprocessorExtension(Extension):
diff --git a/tox.ini b/tox.ini
index 9b6d471357ea91bcc42e68ebb04066113eaebffd..ba9cb4d05dbfc0ba039da32836fe78dd7e847f37 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -3,6 +3,7 @@ envlist =
     py{38,37,36,py3}
     style
     docs
+    mypy
 skip_missing_interpreters = true
 
 [testenv]
@@ -17,3 +18,8 @@ commands = pre-commit run --all-files --show-diff-on-failure
 [testenv:docs]
 deps = -r requirements/docs.txt
 commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
+
+[testenv:mypy]
+deps = mypy
+commands =
+    mypy src/jinja2 tests