Skip to content

Commit 08564c0

Browse files
committed
mypy: templite.py test_templite.py
1 parent 65aad08 commit 08564c0

File tree

3 files changed

+87
-72
lines changed

3 files changed

+87
-72
lines changed

Diff for: coverage/templite.py

+32-20
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,14 @@
1010

1111
# Coincidentally named the same as http://code.activestate.com/recipes/496702/
1212

13+
from __future__ import annotations
14+
1315
import re
1416

17+
from typing import (
18+
Any, Callable, Dict, List, NoReturn, Optional, Set, Union, cast,
19+
)
20+
1521

1622
class TempliteSyntaxError(ValueError):
1723
"""Raised when a template has a syntax error."""
@@ -26,45 +32,45 @@ class TempliteValueError(ValueError):
2632
class CodeBuilder:
2733
"""Build source code conveniently."""
2834

29-
def __init__(self, indent=0):
30-
self.code = []
35+
def __init__(self, indent: int = 0) -> None:
36+
self.code: List[Union[str, CodeBuilder]] = []
3137
self.indent_level = indent
3238

33-
def __str__(self):
39+
def __str__(self) -> str:
3440
return "".join(str(c) for c in self.code)
3541

36-
def add_line(self, line):
42+
def add_line(self, line: str) -> None:
3743
"""Add a line of source to the code.
3844
3945
Indentation and newline will be added for you, don't provide them.
4046
4147
"""
4248
self.code.extend([" " * self.indent_level, line, "\n"])
4349

44-
def add_section(self):
50+
def add_section(self) -> CodeBuilder:
4551
"""Add a section, a sub-CodeBuilder."""
4652
section = CodeBuilder(self.indent_level)
4753
self.code.append(section)
4854
return section
4955

5056
INDENT_STEP = 4 # PEP8 says so!
5157

52-
def indent(self):
58+
def indent(self) -> None:
5359
"""Increase the current indent for following lines."""
5460
self.indent_level += self.INDENT_STEP
5561

56-
def dedent(self):
62+
def dedent(self) -> None:
5763
"""Decrease the current indent for following lines."""
5864
self.indent_level -= self.INDENT_STEP
5965

60-
def get_globals(self):
66+
def get_globals(self) -> Dict[str, Any]:
6167
"""Execute the code, and return a dict of globals it defines."""
6268
# A check that the caller really finished all the blocks they started.
6369
assert self.indent_level == 0
6470
# Get the Python source as a single string.
6571
python_source = str(self)
6672
# Execute the source, defining globals, and return them.
67-
global_namespace = {}
73+
global_namespace: Dict[str, Any] = {}
6874
exec(python_source, global_namespace)
6975
return global_namespace
7076

@@ -111,7 +117,7 @@ class Templite:
111117
})
112118
113119
"""
114-
def __init__(self, text, *contexts):
120+
def __init__(self, text: str, *contexts: Dict[str, Any]) -> None:
115121
"""Construct a Templite with the given `text`.
116122
117123
`contexts` are dictionaries of values to use for future renderings.
@@ -122,8 +128,8 @@ def __init__(self, text, *contexts):
122128
for context in contexts:
123129
self.context.update(context)
124130

125-
self.all_vars = set()
126-
self.loop_vars = set()
131+
self.all_vars: Set[str] = set()
132+
self.loop_vars: Set[str] = set()
127133

128134
# We construct a function in source form, then compile it and hold onto
129135
# it, and execute it to render the template.
@@ -137,9 +143,9 @@ def __init__(self, text, *contexts):
137143
code.add_line("extend_result = result.extend")
138144
code.add_line("to_str = str")
139145

140-
buffered = []
146+
buffered: List[str] = []
141147

142-
def flush_output():
148+
def flush_output() -> None:
143149
"""Force `buffered` to the code builder."""
144150
if len(buffered) == 1:
145151
code.add_line("append_result(%s)" % buffered[0])
@@ -232,9 +238,15 @@ def flush_output():
232238

233239
code.add_line('return "".join(result)')
234240
code.dedent()
235-
self._render_function = code.get_globals()['render_function']
241+
self._render_function = cast(
242+
Callable[
243+
[Dict[str, Any], Callable[..., Any]],
244+
str
245+
],
246+
code.get_globals()['render_function'],
247+
)
236248

237-
def _expr_code(self, expr):
249+
def _expr_code(self, expr: str) -> str:
238250
"""Generate a Python expression for `expr`."""
239251
if "|" in expr:
240252
pipes = expr.split("|")
@@ -252,11 +264,11 @@ def _expr_code(self, expr):
252264
code = "c_%s" % expr
253265
return code
254266

255-
def _syntax_error(self, msg, thing):
267+
def _syntax_error(self, msg: str, thing: Any) -> NoReturn:
256268
"""Raise a syntax error using `msg`, and showing `thing`."""
257269
raise TempliteSyntaxError(f"{msg}: {thing!r}")
258270

259-
def _variable(self, name, vars_set):
271+
def _variable(self, name: str, vars_set: Set[str]) -> None:
260272
"""Track that `name` is used as a variable.
261273
262274
Adds the name to `vars_set`, a set of variable names.
@@ -268,7 +280,7 @@ def _variable(self, name, vars_set):
268280
self._syntax_error("Not a valid name", name)
269281
vars_set.add(name)
270282

271-
def render(self, context=None):
283+
def render(self, context: Optional[Dict[str, Any]] = None) -> str:
272284
"""Render this template by applying it to `context`.
273285
274286
`context` is a dictionary of values to use in this rendering.
@@ -280,7 +292,7 @@ def render(self, context=None):
280292
render_context.update(context)
281293
return self._render_function(render_context, self._do_dots)
282294

283-
def _do_dots(self, value, *dots):
295+
def _do_dots(self, value: Any, *dots: str) -> Any:
284296
"""Evaluate dotted expressions at run-time."""
285297
for dot in dots:
286298
try:

0 commit comments

Comments
 (0)