summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bourke <michael@iter8ve.com>2022-01-09 16:38:12 +1100
committerMike Bayer <mike_mp@zzzcomputing.com>2022-01-14 09:57:14 -0500
commit7e52b60b7dac75a3c7177e69244123c0dad9e9d9 (patch)
tree2df96da5716169b2351f442c272a39ed6940332f
parent3c3196754b55b48c044e59a5beacb9a13bc25114 (diff)
downloadmako-7e52b60b7dac75a3c7177e69244123c0dad9e9d9.tar.gz
Refactor test.util into mako.testing
Fixes: #349 Change-Id: I202c252a913fb72cc328a6e7f0f33174802487d3
-rw-r--r--doc/build/unreleased/mako_testing.rst6
-rw-r--r--mako/testing/__init__.py0
-rw-r--r--mako/testing/_config.py128
-rw-r--r--mako/testing/assertions.py (renamed from test/util/assertions.py)15
-rw-r--r--mako/testing/config.py17
-rw-r--r--mako/testing/exclusions.py80
-rw-r--r--mako/testing/fixtures.py (renamed from test/util/fixtures.py)36
-rw-r--r--mako/testing/helpers.py (renamed from test/util/helpers.py)23
-rw-r--r--setup.cfg7
-rw-r--r--test/ext/test_babelplugin.py143
-rw-r--r--test/ext/test_linguaplugin.py37
-rw-r--r--test/templates/foo/modtest.html.py3
-rw-r--r--test/templates/subdir/foo/modtest.html.py3
-rw-r--r--test/test_ast.py9
-rw-r--r--test/test_block.py6
-rw-r--r--test/test_cache.py51
-rw-r--r--test/test_call.py8
-rw-r--r--test/test_cmd.py20
-rw-r--r--test/test_decorators.py6
-rw-r--r--test/test_def.py10
-rw-r--r--test/test_exceptions.py8
-rw-r--r--test/test_filters.py12
-rw-r--r--test/test_inheritance.py6
-rw-r--r--test/test_lexer.py23
-rw-r--r--test/test_lookup.py21
-rw-r--r--test/test_loop.py13
-rw-r--r--test/test_lru.py4
-rw-r--r--test/test_namespace.py13
-rw-r--r--test/test_pygen.py7
-rw-r--r--test/test_runtime.py6
-rw-r--r--test/test_template.py57
-rw-r--r--test/test_tgplugin.py10
-rw-r--r--test/test_util.py21
-rw-r--r--test/testing/dummy.cfg25
-rw-r--r--test/testing/test_config.py176
-rw-r--r--test/util/__init__.py1
-rw-r--r--test/util/exclusions.py47
-rw-r--r--tox.ini2
38 files changed, 712 insertions, 348 deletions
diff --git a/doc/build/unreleased/mako_testing.rst b/doc/build/unreleased/mako_testing.rst
new file mode 100644
index 0000000..13c51c8
--- /dev/null
+++ b/doc/build/unreleased/mako_testing.rst
@@ -0,0 +1,6 @@
+.. change::
+ :tags: changed
+ :tickets: 349
+
+ Refactored test utilities into ``mako.testing`` module. Removed
+ ``unittest.TestCase`` dependency in favor of ``pytest``.
diff --git a/mako/testing/__init__.py b/mako/testing/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mako/testing/__init__.py
diff --git a/mako/testing/_config.py b/mako/testing/_config.py
new file mode 100644
index 0000000..b469709
--- /dev/null
+++ b/mako/testing/_config.py
@@ -0,0 +1,128 @@
+import configparser
+import dataclasses
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Callable
+from typing import ClassVar
+from typing import Optional
+from typing import Union
+
+from .helpers import make_path
+
+
+class ConfigError(BaseException):
+ pass
+
+
+class MissingConfig(ConfigError):
+ pass
+
+
+class MissingConfigSection(ConfigError):
+ pass
+
+
+class MissingConfigItem(ConfigError):
+ pass
+
+
+class ConfigValueTypeError(ConfigError):
+ pass
+
+
+class _GetterDispatch:
+ def __init__(self, initialdata, default_getter: Callable):
+ self.default_getter = default_getter
+ self.data = initialdata
+
+ def get_fn_for_type(self, type_):
+ return self.data.get(type_, self.default_getter)
+
+ def get_typed_value(self, type_, name):
+ get_fn = self.get_fn_for_type(type_)
+ return get_fn(name)
+
+
+def _parse_cfg_file(filespec: Union[Path, str]):
+ cfg = configparser.ConfigParser()
+ try:
+ filepath = make_path(filespec, check_exists=True)
+ except FileNotFoundError as e:
+ raise MissingConfig(f"No config file found at {filespec}") from e
+ else:
+ with open(filepath) as f:
+ cfg.read_file(f)
+ return cfg
+
+
+def _build_getter(cfg_obj, cfg_section, method, converter=None):
+ def caller(option, **kwargs):
+ try:
+ rv = getattr(cfg_obj, method)(cfg_section, option, **kwargs)
+ except configparser.NoSectionError as nse:
+ raise MissingConfigSection(
+ f"No config section named {cfg_section}"
+ ) from nse
+ except configparser.NoOptionError as noe:
+ raise MissingConfigItem(f"No config item for {option}") from noe
+ except ValueError as ve:
+ # ConfigParser.getboolean, .getint, .getfloat raise ValueError
+ # on bad types
+ raise ConfigValueTypeError(
+ f"Wrong value type for {option}"
+ ) from ve
+ else:
+ if converter:
+ try:
+ rv = converter(rv)
+ except Exception as e:
+ raise ConfigValueTypeError(
+ f"Wrong value type for {option}"
+ ) from e
+ return rv
+
+ return caller
+
+
+def _build_getter_dispatch(cfg_obj, cfg_section, converters=None):
+ converters = converters or {}
+
+ default_getter = _build_getter(cfg_obj, cfg_section, "get")
+
+ # support ConfigParser builtins
+ getters = {
+ int: _build_getter(cfg_obj, cfg_section, "getint"),
+ bool: _build_getter(cfg_obj, cfg_section, "getboolean"),
+ float: _build_getter(cfg_obj, cfg_section, "getfloat"),
+ str: default_getter,
+ }
+
+ # use ConfigParser.get and convert value
+ getters.update(
+ {
+ type_: _build_getter(
+ cfg_obj, cfg_section, "get", converter=converter_fn
+ )
+ for type_, converter_fn in converters.items()
+ }
+ )
+
+ return _GetterDispatch(getters, default_getter)
+
+
+@dataclass
+class ReadsCfg:
+ section_header: ClassVar[str]
+ converters: ClassVar[Optional[dict]] = None
+
+ @classmethod
+ def from_cfg_file(cls, filespec: Union[Path, str]):
+ cfg = _parse_cfg_file(filespec)
+ dispatch = _build_getter_dispatch(
+ cfg, cls.section_header, converters=cls.converters
+ )
+ kwargs = {
+ field.name: dispatch.get_typed_value(field.type, field.name)
+ for field in dataclasses.fields(cls)
+ }
+ return cls(**kwargs)
diff --git a/test/util/assertions.py b/mako/testing/assertions.py
index 8be154c..14ea635 100644
--- a/test/util/assertions.py
+++ b/mako/testing/assertions.py
@@ -8,6 +8,21 @@ def eq_(a, b, msg=None):
assert a == b, msg or "%r != %r" % (a, b)
+def ne_(a, b, msg=None):
+ """Assert a != b, with repr messaging on failure."""
+ assert a != b, msg or "%r == %r" % (a, b)
+
+
+def in_(a, b, msg=None):
+ """Assert a in b, with repr messaging on failure."""
+ assert a in b, msg or "%r not in %r" % (a, b)
+
+
+def not_in(a, b, msg=None):
+ """Assert a in not b, with repr messaging on failure."""
+ assert a not in b, msg or "%r is in %r" % (a, b)
+
+
def _assert_proper_exception_context(exception):
"""assert that any exception we're catching does not have a __context__
without a __cause__, and that __suppress_context__ is never set.
diff --git a/mako/testing/config.py b/mako/testing/config.py
new file mode 100644
index 0000000..b77d0c0
--- /dev/null
+++ b/mako/testing/config.py
@@ -0,0 +1,17 @@
+from dataclasses import dataclass
+from pathlib import Path
+
+from ._config import ReadsCfg
+from .helpers import make_path
+
+
+@dataclass
+class Config(ReadsCfg):
+ module_base: Path
+ template_base: Path
+
+ section_header = "mako_testing"
+ converters = {Path: make_path}
+
+
+config = Config.from_cfg_file("./setup.cfg")
diff --git a/mako/testing/exclusions.py b/mako/testing/exclusions.py
new file mode 100644
index 0000000..37b2d14
--- /dev/null
+++ b/mako/testing/exclusions.py
@@ -0,0 +1,80 @@
+import pytest
+
+from mako.ext.beaker_cache import has_beaker
+from mako.util import update_wrapper
+
+
+try:
+ import babel.messages.extract as babel
+except ImportError:
+ babel = None
+
+
+try:
+ import lingua
+except ImportError:
+ lingua = None
+
+
+try:
+ import dogpile.cache # noqa
+except ImportError:
+ has_dogpile_cache = False
+else:
+ has_dogpile_cache = True
+
+
+requires_beaker = pytest.mark.skipif(
+ not has_beaker, reason="Beaker is required for these tests."
+)
+
+
+requires_babel = pytest.mark.skipif(
+ babel is None, reason="babel not installed: skipping babelplugin test"
+)
+
+
+requires_lingua = pytest.mark.skipif(
+ lingua is None, reason="lingua not installed: skipping linguaplugin test"
+)
+
+
+requires_dogpile_cache = pytest.mark.skipif(
+ not has_dogpile_cache,
+ reason="dogpile.cache is required to run these tests",
+)
+
+
+def _pygments_version():
+ try:
+ import pygments
+
+ version = pygments.__version__
+ except:
+ version = "0"
+ return version
+
+
+requires_pygments_14 = pytest.mark.skipif(
+ _pygments_version() < "1.4", reason="Requires pygments 1.4 or greater"
+)
+
+
+# def requires_pygments_14(fn):
+
+# return skip_if(
+# lambda: version < "1.4", "Requires pygments 1.4 or greater"
+# )(fn)
+
+
+def requires_no_pygments_exceptions(fn):
+ def go(*arg, **kw):
+ from mako import exceptions
+
+ exceptions._install_fallback()
+ try:
+ return fn(*arg, **kw)
+ finally:
+ exceptions._install_highlighting()
+
+ return update_wrapper(go, fn)
diff --git a/test/util/fixtures.py b/mako/testing/fixtures.py
index d4b28db..c9379c0 100644
--- a/test/util/fixtures.py
+++ b/mako/testing/fixtures.py
@@ -1,49 +1,29 @@
import os
-import unittest
from mako.cache import CacheImpl
from mako.cache import register_plugin
from mako.template import Template
from .assertions import eq_
+from .config import config
-def _ensure_environment_variable(key, fallback):
- env_var = os.getenv(key)
- if env_var is None:
- return fallback
- return env_var
-
-
-def _get_module_base():
- return _ensure_environment_variable(
- "TEST_MODULE_BASE", os.path.abspath("./test/templates/modules")
- )
-
-
-def _get_template_base():
- return _ensure_environment_variable(
- "TEST_TEMPLATE_BASE", os.path.abspath("./test/templates/")
- )
-
-
-module_base = _get_module_base()
-template_base = _get_template_base()
-
-
-class TemplateTest(unittest.TestCase):
+class TemplateTest:
def _file_template(self, filename, **kw):
filepath = self._file_path(filename)
return Template(
- uri=filename, filename=filepath, module_directory=module_base, **kw
+ uri=filename,
+ filename=filepath,
+ module_directory=config.module_base,
+ **kw,
)
def _file_path(self, filename):
name, ext = os.path.splitext(filename)
- py3k_path = os.path.join(template_base, name + "_py3k" + ext)
+ py3k_path = os.path.join(config.template_base, name + "_py3k" + ext)
if os.path.exists(py3k_path):
return py3k_path
- return os.path.join(template_base, filename)
+ return os.path.join(config.template_base, filename)
def _do_file_test(
self,
diff --git a/test/util/helpers.py b/mako/testing/helpers.py
index 86402c8..77cca36 100644
--- a/test/util/helpers.py
+++ b/mako/testing/helpers.py
@@ -1,11 +1,11 @@
import contextlib
import pathlib
+from pathlib import Path
import re
import time
+from typing import Union
from unittest import mock
-from test.util.fixtures import module_base
-
def flatten_result(result):
return re.sub(r"[\s\r\n]+", " ", result).strip()
@@ -19,6 +19,19 @@ def result_lines(result):
]
+def make_path(
+ filespec: Union[Path, str],
+ make_absolute: bool = True,
+ check_exists: bool = False,
+) -> Path:
+ path = Path(filespec)
+ if make_absolute:
+ path = path.resolve(strict=check_exists)
+ if check_exists and (not path.exists()):
+ raise FileNotFoundError(f"No file or directory at {filespec}")
+ return path
+
+
def _unlink_path(path, missing_ok=False):
# Replicate 3.8+ functionality in 3.7
cm = contextlib.nullcontext()
@@ -52,9 +65,3 @@ def rewind_compile_time(hours=1):
with mock.patch("mako.codegen.time") as codegen_time:
codegen_time.time.return_value = rewound
yield
-
-
-def teardown():
- import shutil
-
- shutil.rmtree(module_base, True)
diff --git a/setup.cfg b/setup.cfg
index ab24fd7..8cbe2db 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -42,6 +42,8 @@ exclude =
examples*
[options.extras_require]
+testing =
+ pytest
babel =
Babel
lingua =
@@ -73,6 +75,7 @@ tag_build = dev
[tool:pytest]
addopts= --tb native -v -r fxX -W error
python_files=test/*test_*.py
+python_classes=*Test
[upload]
sign = 1
@@ -92,3 +95,7 @@ ignore =
exclude = .venv,.git,.tox,dist,docs/*,*egg,build
import-order-style = google
application-import-names = mako,test
+
+[mako_testing]
+module_base = ./test/templates/modules
+template_base = ./test/templates/
diff --git a/test/ext/test_babelplugin.py b/test/ext/test_babelplugin.py
index be3c37a..de3e461 100644
--- a/test/ext/test_babelplugin.py
+++ b/test/ext/test_babelplugin.py
@@ -1,39 +1,25 @@
import io
import os
-import unittest
-from ..util.exclusions import skip_if
-from ..util.fixtures import template_base
-from ..util.fixtures import TemplateTest
+from mako.ext.babelplugin import extract
+from mako.testing.assertions import eq_
+from mako.testing.config import config
+from mako.testing.exclusions import requires_babel
+from mako.testing.fixtures import TemplateTest
-try:
- import babel.messages.extract as babel
- from mako.ext.babelplugin import extract
-except ImportError:
- babel = None
-
-
-def skip():
- return skip_if(
- lambda: not babel, "babel not installed: skipping babelplugin test"
- )
-
-
-class Test_extract(unittest.TestCase):
- @skip()
+@requires_babel
+class PluginExtractTest:
def test_parse_python_expression(self):
input_ = io.BytesIO(b'<p>${_("Message")}</p>')
messages = list(extract(input_, ["_"], [], {}))
- self.assertEqual(messages, [(1, "_", ("Message"), [])])
+ eq_(messages, [(1, "_", ("Message"), [])])
- @skip()
def test_python_gettext_call(self):
input_ = io.BytesIO(b'<p>${_("Message")}</p>')
messages = list(extract(input_, ["_"], [], {}))
- self.assertEqual(messages, [(1, "_", ("Message"), [])])
+ eq_(messages, [(1, "_", ("Message"), [])])
- @skip()
def test_translator_comment(self):
input_ = io.BytesIO(
b"""
@@ -43,7 +29,7 @@ class Test_extract(unittest.TestCase):
</p>"""
)
messages = list(extract(input_, ["_"], ["TRANSLATORS:"], {}))
- self.assertEqual(
+ eq_(
messages,
[
(
@@ -56,65 +42,62 @@ class Test_extract(unittest.TestCase):
)
-class ExtractMakoTestCase(TemplateTest):
- @skip()
+@requires_babel
+class MakoExtractTest(TemplateTest):
def test_extract(self):
- mako_tmpl = open(os.path.join(template_base, "gettext.mako"))
- self.addCleanup(mako_tmpl.close)
- messages = list(
- extract(
- mako_tmpl,
- {"_": None, "gettext": None, "ungettext": (1, 2)},
- ["TRANSLATOR:"],
- {},
+ with open(
+ os.path.join(config.template_base, "gettext.mako")
+ ) as mako_tmpl:
+ messages = list(
+ extract(
+ mako_tmpl,
+ {"_": None, "gettext": None, "ungettext": (1, 2)},
+ ["TRANSLATOR:"],
+ {},
+ )
)
- )
- expected = [
- (1, "_", "Page arg 1", []),
- (1, "_", "Page arg 2", []),
- (10, "gettext", "Begin", []),
- (14, "_", "Hi there!", ["TRANSLATOR: Hi there!"]),
- (19, "_", "Hello", []),
- (22, "_", "Welcome", []),
- (25, "_", "Yo", []),
- (36, "_", "The", ["TRANSLATOR: Ensure so and", "so, thanks"]),
- (36, "ungettext", ("bunny", "bunnies", None), []),
- (41, "_", "Goodbye", ["TRANSLATOR: Good bye"]),
- (44, "_", "Babel", []),
- (45, "ungettext", ("hella", "hellas", None), []),
- (62, "_", "The", ["TRANSLATOR: Ensure so and", "so, thanks"]),
- (62, "ungettext", ("bunny", "bunnies", None), []),
- (68, "_", "Goodbye, really!", ["TRANSLATOR: HTML comment"]),
- (71, "_", "P.S. byebye", []),
- (77, "_", "Top", []),
- (83, "_", "foo", []),
- (83, "_", "hoho", []),
- (85, "_", "bar", []),
- (92, "_", "Inside a p tag", ["TRANSLATOR: <p> tag is ok?"]),
- (95, "_", "Later in a p tag", ["TRANSLATOR: also this"]),
- (99, "_", "No action at a distance.", []),
- ]
- self.assertEqual(expected, messages)
+ expected = [
+ (1, "_", "Page arg 1", []),
+ (1, "_", "Page arg 2", []),
+ (10, "gettext", "Begin", []),
+ (14, "_", "Hi there!", ["TRANSLATOR: Hi there!"]),
+ (19, "_", "Hello", []),
+ (22, "_", "Welcome", []),
+ (25, "_", "Yo", []),
+ (36, "_", "The", ["TRANSLATOR: Ensure so and", "so, thanks"]),
+ (36, "ungettext", ("bunny", "bunnies", None), []),
+ (41, "_", "Goodbye", ["TRANSLATOR: Good bye"]),
+ (44, "_", "Babel", []),
+ (45, "ungettext", ("hella", "hellas", None), []),
+ (62, "_", "The", ["TRANSLATOR: Ensure so and", "so, thanks"]),
+ (62, "ungettext", ("bunny", "bunnies", None), []),
+ (68, "_", "Goodbye, really!", ["TRANSLATOR: HTML comment"]),
+ (71, "_", "P.S. byebye", []),
+ (77, "_", "Top", []),
+ (83, "_", "foo", []),
+ (83, "_", "hoho", []),
+ (85, "_", "bar", []),
+ (92, "_", "Inside a p tag", ["TRANSLATOR: <p> tag is ok?"]),
+ (95, "_", "Later in a p tag", ["TRANSLATOR: also this"]),
+ (99, "_", "No action at a distance.", []),
+ ]
+ eq_(expected, messages)
- @skip()
def test_extract_utf8(self):
- mako_tmpl = open(
- os.path.join(template_base, "gettext_utf8.mako"), "rb"
- )
- self.addCleanup(mako_tmpl.close)
- message = next(
- extract(mako_tmpl, {"_", None}, [], {"encoding": "utf-8"})
- )
- assert message == (1, "_", "K\xf6ln", [])
+ with open(
+ os.path.join(config.template_base, "gettext_utf8.mako"), "rb"
+ ) as mako_tmpl:
+ message = next(
+ extract(mako_tmpl, {"_", None}, [], {"encoding": "utf-8"})
+ )
+ assert message == (1, "_", "K\xf6ln", [])
- @skip()
def test_extract_cp1251(self):
- mako_tmpl = open(
- os.path.join(template_base, "gettext_cp1251.mako"), "rb"
- )
- self.addCleanup(mako_tmpl.close)
- message = next(
- extract(mako_tmpl, {"_", None}, [], {"encoding": "cp1251"})
- )
- # "test" in Rusian. File encoding is cp1251 (aka "windows-1251")
- assert message == (1, "_", "\u0442\u0435\u0441\u0442", [])
+ with open(
+ os.path.join(config.template_base, "gettext_cp1251.mako"), "rb"
+ ) as mako_tmpl:
+ message = next(
+ extract(mako_tmpl, {"_", None}, [], {"encoding": "cp1251"})
+ )
+ # "test" in Rusian. File encoding is cp1251 (aka "windows-1251")
+ assert message == (1, "_", "\u0442\u0435\u0441\u0442", [])
diff --git a/test/ext/test_linguaplugin.py b/test/ext/test_linguaplugin.py
index fa5f76d..ae24f67 100644
--- a/test/ext/test_linguaplugin.py
+++ b/test/ext/test_linguaplugin.py
@@ -1,17 +1,12 @@
import os
-from ..util.exclusions import skip_if
-from ..util.fixtures import template_base
-from ..util.fixtures import TemplateTest
+import pytest
-try:
- import lingua
-except:
- lingua = None
-
-if lingua is not None:
- from mako.ext.linguaplugin import LinguaMakoExtractor
- from lingua.extractors import register_extractors
+from mako.ext.linguaplugin import LinguaMakoExtractor
+from mako.testing.assertions import eq_
+from mako.testing.config import config
+from mako.testing.exclusions import requires_lingua
+from mako.testing.fixtures import TemplateTest
class MockOptions:
@@ -20,22 +15,24 @@ class MockOptions:
comment_tag = True
-def skip():
- return skip_if(
- lambda: not lingua, "lingua not installed: skipping linguaplugin test"
- )
+@requires_lingua
+class MakoExtractTest(TemplateTest):
+ @pytest.fixture(autouse=True)
+ def register_lingua_extractors(self):
+ from lingua.extractors import register_extractors
+ register_extractors()
-class ExtractMakoTestCase(TemplateTest):
- @skip()
def test_extract(self):
- register_extractors()
plugin = LinguaMakoExtractor({"comment-tags": "TRANSLATOR"})
messages = list(
- plugin(os.path.join(template_base, "gettext.mako"), MockOptions())
+ plugin(
+ os.path.join(config.template_base, "gettext.mako"),
+ MockOptions(),
+ )
)
msgids = [(m.msgid, m.msgid_plural) for m in messages]
- self.assertEqual(
+ eq_(
msgids,
[
("Page arg 1", None),
diff --git a/test/templates/foo/modtest.html.py b/test/templates/foo/modtest.html.py
index 7a73e55..c35420f 100644
--- a/test/templates/foo/modtest.html.py
+++ b/test/templates/foo/modtest.html.py
@@ -1,4 +1,5 @@
-from mako import runtime, filters, cache
+from mako import cache
+from mako import runtime
UNDEFINED = runtime.UNDEFINED
__M_dict_builtin = dict
diff --git a/test/templates/subdir/foo/modtest.html.py b/test/templates/subdir/foo/modtest.html.py
index 8b3a73b..9df72e0 100644
--- a/test/templates/subdir/foo/modtest.html.py
+++ b/test/templates/subdir/foo/modtest.html.py
@@ -1,4 +1,5 @@
-from mako import runtime, filters, cache
+from mako import cache
+from mako import runtime
UNDEFINED = runtime.UNDEFINED
__M_dict_builtin = dict
diff --git a/test/test_ast.py b/test/test_ast.py
index 29a8a36..6b3a3e2 100644
--- a/test/test_ast.py
+++ b/test/test_ast.py
@@ -1,14 +1,13 @@
-import unittest
-
from mako import ast
from mako import exceptions
from mako import pyparser
-from .util.assertions import eq_
+from mako.testing.assertions import assert_raises
+from mako.testing.assertions import eq_
exception_kwargs = {"source": "", "lineno": 0, "pos": 0, "filename": ""}
-class AstParseTest(unittest.TestCase):
+class AstParseTest:
def test_locate_identifiers(self):
"""test the location of identifiers in a python code string"""
code = """
@@ -228,7 +227,7 @@ except (Foo, Bar) as e:
from foo import *
import x as bar
"""
- self.assertRaises(
+ assert_raises(
exceptions.CompileException,
ast.PythonCode,
code,
diff --git a/test/test_block.py b/test/test_block.py
index a55ca89..be2fbf7 100644
--- a/test/test_block.py
+++ b/test/test_block.py
@@ -1,9 +1,9 @@
from mako import exceptions
from mako.lookup import TemplateLookup
from mako.template import Template
-from .util.assertions import assert_raises_message
-from .util.fixtures import TemplateTest
-from .util.helpers import result_lines
+from mako.testing.assertions import assert_raises_message
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import result_lines
class BlockTest(TemplateTest):
diff --git a/test/test_cache.py b/test/test_cache.py
index 60785f2..dd415d4 100644
--- a/test/test_cache.py
+++ b/test/test_cache.py
@@ -1,19 +1,18 @@
import time
-import unittest
from mako import lookup
from mako.cache import CacheImpl
from mako.cache import register_plugin
-from mako.ext import beaker_cache
from mako.lookup import TemplateLookup
from mako.template import Template
-from .util.assertions import eq_
-from .util.fixtures import module_base
-from .util.fixtures import TemplateTest
-from .util.helpers import result_lines
+from mako.testing.assertions import eq_
+from mako.testing.config import config
+from mako.testing.exclusions import requires_beaker
+from mako.testing.exclusions import requires_dogpile_cache
+from mako.testing.helpers import result_lines
-if beaker_cache.has_beaker:
- import beaker
+
+module_base = str(config.module_base)
class SimpleBackend:
@@ -32,9 +31,9 @@ class SimpleBackend:
def get_or_create(self, key, creation_function, **kw):
if key in self.cache:
return self.cache[key]
- else:
- self.cache[key] = value = creation_function()
- return value
+
+ self.cache[key] = value = creation_function()
+ return value
class MockCacheImpl(CacheImpl):
@@ -80,7 +79,7 @@ class MockCacheImpl(CacheImpl):
register_plugin("mock", __name__, "MockCacheImpl")
-class CacheTest(TemplateTest):
+class CacheTest:
real_backend = "simple"
@@ -600,7 +599,7 @@ class CacheTest(TemplateTest):
assert m.kwargs["context"].get("x") == "bar"
-class RealBackendTest:
+class RealBackendMixin:
def test_cache_uses_current_context(self):
t = Template(
"""
@@ -643,19 +642,17 @@ class RealBackendTest:
eq_(r3, ["short term 6", "long term 5", "none 7"])
-class BeakerCacheTest(RealBackendTest, CacheTest):
+@requires_beaker
+class BeakerCacheTest(RealBackendMixin, CacheTest):
real_backend = "beaker"
- def setUp(self):
- if not beaker_cache.has_beaker:
- raise unittest.SkipTest("Beaker is required for these tests.")
-
def _install_mock_cache(self, template, implname=None):
template.cache_args["manager"] = self._regions()
- impl = super()._install_mock_cache(template, implname)
- return impl
+ return super()._install_mock_cache(template, implname)
def _regions(self):
+ import beaker
+
return beaker.cache.CacheManager(
cache_regions={
"short": {"expire": 1, "type": "memory"},
@@ -664,22 +661,14 @@ class BeakerCacheTest(RealBackendTest, CacheTest):
)
-class DogpileCacheTest(RealBackendTest, CacheTest):
+@requires_dogpile_cache
+class DogpileCacheTest(RealBackendMixin, CacheTest):
real_backend = "dogpile.cache"
- def setUp(self):
- try:
- import dogpile.cache # noqa
- except ImportError:
- raise unittest.SkipTest(
- "dogpile.cache is required to run these tests"
- )
-
def _install_mock_cache(self, template, implname=None):
template.cache_args["regions"] = self._regions()
template.cache_args.setdefault("region", "short")
- impl = super()._install_mock_cache(template, implname)
- return impl
+ return super()._install_mock_cache(template, implname)
def _regions(self):
from dogpile.cache import make_region
diff --git a/test/test_call.py b/test/test_call.py
index 82d48da..4dea2b3 100644
--- a/test/test_call.py
+++ b/test/test_call.py
@@ -1,8 +1,8 @@
from mako.template import Template
-from .util.assertions import eq_
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
-from .util.helpers import result_lines
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
class CallTest(TemplateTest):
diff --git a/test/test_cmd.py b/test/test_cmd.py
index 2347452..785c652 100644
--- a/test/test_cmd.py
+++ b/test/test_cmd.py
@@ -3,11 +3,11 @@ import os
from unittest import mock
from mako.cmd import cmdline
-from .util.assertions import eq_
-from .util.assertions import expect_raises
-from .util.assertions import expect_raises_message
-from .util.fixtures import template_base
-from .util.fixtures import TemplateTest
+from mako.testing.assertions import eq_
+from mako.testing.assertions import expect_raises
+from mako.testing.assertions import expect_raises_message
+from mako.testing.config import config
+from mako.testing.fixtures import TemplateTest
class CmdTest(TemplateTest):
@@ -53,7 +53,11 @@ class CmdTest(TemplateTest):
def test_file_success(self):
with self._capture_output_fixture() as stdout:
cmdline(
- ["--var", "x=5", os.path.join(template_base, "cmd_good.mako")]
+ [
+ "--var",
+ "x=5",
+ os.path.join(config.template_base, "cmd_good.mako"),
+ ]
)
eq_(stdout.write.mock_calls[0][1][0], "hello world 5")
@@ -65,7 +69,7 @@ class CmdTest(TemplateTest):
[
"--var",
"x=5",
- os.path.join(template_base, "cmd_syntax.mako"),
+ os.path.join(config.template_base, "cmd_syntax.mako"),
]
)
@@ -79,7 +83,7 @@ class CmdTest(TemplateTest):
[
"--var",
"x=5",
- os.path.join(template_base, "cmd_runtime.mako"),
+ os.path.join(config.template_base, "cmd_runtime.mako"),
]
)
diff --git a/test/test_decorators.py b/test/test_decorators.py
index 6153371..68ea903 100644
--- a/test/test_decorators.py
+++ b/test/test_decorators.py
@@ -1,10 +1,8 @@
-import unittest
-
from mako.template import Template
-from .util.helpers import flatten_result
+from mako.testing.helpers import flatten_result
-class DecoratorTest(unittest.TestCase):
+class DecoratorTest:
def test_toplevel(self):
template = Template(
"""
diff --git a/test/test_def.py b/test/test_def.py
index 5f99192..fd96433 100644
--- a/test/test_def.py
+++ b/test/test_def.py
@@ -1,10 +1,10 @@
from mako import lookup
from mako.template import Template
-from .util.assertions import assert_raises
-from .util.assertions import eq_
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
-from .util.helpers import result_lines
+from mako.testing.assertions import assert_raises
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
class DefTest(TemplateTest):
diff --git a/test/test_exceptions.py b/test/test_exceptions.py
index a2b8cf9..b1930c5 100644
--- a/test/test_exceptions.py
+++ b/test/test_exceptions.py
@@ -3,10 +3,10 @@ import sys
from mako import exceptions
from mako.lookup import TemplateLookup
from mako.template import Template
-from .util.exclusions import requires_no_pygments_exceptions
-from .util.exclusions import requires_pygments_14
-from .util.fixtures import TemplateTest
-from .util.helpers import result_lines
+from mako.testing.exclusions import requires_no_pygments_exceptions
+from mako.testing.exclusions import requires_pygments_14
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import result_lines
class ExceptionsTest(TemplateTest):
diff --git a/test/test_filters.py b/test/test_filters.py
index b3b4753..726f5d7 100644
--- a/test/test_filters.py
+++ b/test/test_filters.py
@@ -1,10 +1,8 @@
-import unittest
-
from mako.template import Template
-from .util.assertions import eq_
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
-from .util.helpers import result_lines
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
class FilterTest(TemplateTest):
@@ -363,7 +361,7 @@ data = {a: ${123}, b: ${"123"}};
)
-class BufferTest(unittest.TestCase):
+class BufferTest:
def test_buffered_def(self):
t = Template(
"""
diff --git a/test/test_inheritance.py b/test/test_inheritance.py
index 7824241..15bd54b 100644
--- a/test/test_inheritance.py
+++ b/test/test_inheritance.py
@@ -1,10 +1,8 @@
-import unittest
-
from mako import lookup
-from .util.helpers import result_lines
+from mako.testing.helpers import result_lines
-class InheritanceTest(unittest.TestCase):
+class InheritanceTest:
def test_basic(self):
collection = lookup.TemplateLookup()
diff --git a/test/test_lexer.py b/test/test_lexer.py
index 43b1e7a..255c128 100644
--- a/test/test_lexer.py
+++ b/test/test_lexer.py
@@ -6,10 +6,11 @@ from mako import parsetree
from mako import util
from mako.lexer import Lexer
from mako.template import Template
-from .util.assertions import assert_raises_message
-from .util.assertions import eq_
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
+from mako.testing.assertions import assert_raises
+from mako.testing.assertions import assert_raises_message
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
# create fake parsetree classes which are constructed
# exactly as the repr() of a real parsetree object.
@@ -137,13 +138,13 @@ class LexerTest(TemplateTest):
hi.
"""
- self.assertRaises(exceptions.SyntaxException, Lexer(template).parse)
+ assert_raises(exceptions.SyntaxException, Lexer(template).parse)
def test_noexpr_allowed(self):
template = """
<%namespace name="${foo}"/>
"""
- self.assertRaises(exceptions.CompileException, Lexer(template).parse)
+ assert_raises(exceptions.CompileException, Lexer(template).parse)
def test_unmatched_tag(self):
template = """
@@ -156,13 +157,13 @@ class LexerTest(TemplateTest):
hi.
"""
- self.assertRaises(exceptions.SyntaxException, Lexer(template).parse)
+ assert_raises(exceptions.SyntaxException, Lexer(template).parse)
def test_nonexistent_tag(self):
template = """
<%lala x="5"/>
"""
- self.assertRaises(exceptions.CompileException, Lexer(template).parse)
+ assert_raises(exceptions.CompileException, Lexer(template).parse)
def test_wrongcase_tag(self):
template = """
@@ -170,7 +171,7 @@ class LexerTest(TemplateTest):
</%def>
"""
- self.assertRaises(exceptions.CompileException, Lexer(template).parse)
+ assert_raises(exceptions.CompileException, Lexer(template).parse)
def test_percent_escape(self):
template = """
@@ -273,7 +274,7 @@ class LexerTest(TemplateTest):
hi
</%def>
"""
- self.assertRaises(exceptions.CompileException, Lexer(template).parse)
+ assert_raises(exceptions.CompileException, Lexer(template).parse)
def test_def_syntax_2(self):
template = """
@@ -281,7 +282,7 @@ class LexerTest(TemplateTest):
hi
</%def>
"""
- self.assertRaises(exceptions.CompileException, Lexer(template).parse)
+ assert_raises(exceptions.CompileException, Lexer(template).parse)
def test_whitespace_equals(self):
template = """
diff --git a/test/test_lookup.py b/test/test_lookup.py
index eebb97b..6a797d7 100644
--- a/test/test_lookup.py
+++ b/test/test_lookup.py
@@ -1,24 +1,23 @@
import os
import tempfile
-import unittest
from mako import exceptions
from mako import lookup
from mako import runtime
from mako.template import Template
+from mako.testing.assertions import assert_raises_message
+from mako.testing.assertions import assert_raises_with_given_cause
+from mako.testing.config import config
+from mako.testing.helpers import file_with_template_code
+from mako.testing.helpers import replace_file_with_dir
+from mako.testing.helpers import result_lines
+from mako.testing.helpers import rewind_compile_time
from mako.util import FastEncodingBuffer
-from .util.assertions import assert_raises_message
-from .util.assertions import assert_raises_with_given_cause
-from .util.fixtures import template_base
-from .util.helpers import file_with_template_code
-from .util.helpers import replace_file_with_dir
-from .util.helpers import result_lines
-from .util.helpers import rewind_compile_time
-tl = lookup.TemplateLookup(directories=[template_base])
+tl = lookup.TemplateLookup(directories=[config.template_base])
-class LookupTest(unittest.TestCase):
+class LookupTest:
def test_basic(self):
t = tl.get_template("index.html")
assert result_lines(t.render()) == ["this is index"]
@@ -98,7 +97,7 @@ class LookupTest(unittest.TestCase):
"""test the mechanics of an include where
the include goes outside of the path"""
tl = lookup.TemplateLookup(
- directories=[os.path.join(template_base, "subdir")]
+ directories=[os.path.join(config.template_base, "subdir")]
)
index = tl.get_template("index.html")
diff --git a/test/test_loop.py b/test/test_loop.py
index be7d440..19d40b5 100644
--- a/test/test_loop.py
+++ b/test/test_loop.py
@@ -1,5 +1,4 @@
import re
-import unittest
from mako import exceptions
from mako.codegen import _FOR_LOOP
@@ -7,12 +6,12 @@ from mako.lookup import TemplateLookup
from mako.runtime import LoopContext
from mako.runtime import LoopStack
from mako.template import Template
-from .util.assertions import assert_raises_message
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
+from mako.testing.assertions import assert_raises_message
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
-class TestLoop(unittest.TestCase):
+class TestLoop:
def test__FOR_LOOP(self):
for statement, target_list, expression_list in (
("for x in y:", "x", "y"),
@@ -137,7 +136,7 @@ ${x} ${loop.index} <- outer loop
)
-class TestLoopStack(unittest.TestCase):
+class TestLoopStack:
def setUp(self):
self.stack = LoopStack()
self.bottom = "spam"
@@ -180,7 +179,7 @@ class TestLoopStack(unittest.TestCase):
assert before == (after + 1), "Exiting a context pops the stack"
-class TestLoopContext(unittest.TestCase):
+class TestLoopContext:
def setUp(self):
self.iterable = [1, 2, 3]
self.ctx = LoopContext(self.iterable)
diff --git a/test/test_lru.py b/test/test_lru.py
index 7281537..f54bd15 100644
--- a/test/test_lru.py
+++ b/test/test_lru.py
@@ -1,5 +1,3 @@
-import unittest
-
from mako.util import LRUCache
@@ -11,7 +9,7 @@ class item:
return "item id %d" % self.id
-class LRUTest(unittest.TestCase):
+class LRUTest:
def testlru(self):
l = LRUCache(10, threshold=0.2)
diff --git a/test/test_namespace.py b/test/test_namespace.py
index bdd1641..b6b0544 100644
--- a/test/test_namespace.py
+++ b/test/test_namespace.py
@@ -1,11 +1,12 @@
from mako import exceptions
from mako import lookup
from mako.template import Template
-from .util.assertions import assert_raises_message_with_given_cause
-from .util.assertions import eq_
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
-from .util.helpers import result_lines
+from mako.testing.assertions import assert_raises
+from mako.testing.assertions import assert_raises_message_with_given_cause
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
class NamespaceTest(TemplateTest):
@@ -586,7 +587,7 @@ class NamespaceTest(TemplateTest):
""",
)
- self.assertRaises(AttributeError, l.get_template("bar.html").render)
+ assert_raises(AttributeError, l.get_template("bar.html").render)
def test_custom_tag_1(self):
template = Template(
diff --git a/test/test_pygen.py b/test/test_pygen.py
index 5200e3e..8adc142 100644
--- a/test/test_pygen.py
+++ b/test/test_pygen.py
@@ -1,12 +1,11 @@
from io import StringIO
-import unittest
from mako.pygen import adjust_whitespace
from mako.pygen import PythonPrinter
-from .util.assertions import eq_
+from mako.testing.assertions import eq_
-class GeneratePythonTest(unittest.TestCase):
+class GeneratePythonTest:
def test_generate_normal(self):
stream = StringIO()
printer = PythonPrinter(stream)
@@ -165,7 +164,7 @@ print "more indent"
)
-class WhitespaceTest(unittest.TestCase):
+class WhitespaceTest:
def test_basic(self):
text = """
for x in range(0,15):
diff --git a/test/test_runtime.py b/test/test_runtime.py
index 07802f9..0d6fce3 100644
--- a/test/test_runtime.py
+++ b/test/test_runtime.py
@@ -1,12 +1,10 @@
"""Assorted runtime unit tests
"""
-import unittest
-
from mako import runtime
-from .util.assertions import eq_
+from mako.testing.assertions import eq_
-class ContextTest(unittest.TestCase):
+class ContextTest:
def test_locals_kwargs(self):
c = runtime.Context(None, foo="bar")
eq_(c.kwargs, {"foo": "bar"})
diff --git a/test/test_template.py b/test/test_template.py
index 238b8c6..fc1aeca 100644
--- a/test/test_template.py
+++ b/test/test_template.py
@@ -1,5 +1,4 @@
import os
-import unittest
from mako import exceptions
from mako import runtime
@@ -9,14 +8,13 @@ from mako.lookup import TemplateLookup
from mako.template import ModuleInfo
from mako.template import ModuleTemplate
from mako.template import Template
-from .util.assertions import assert_raises
-from .util.assertions import assert_raises_message
-from .util.assertions import eq_
-from .util.fixtures import module_base
-from .util.fixtures import template_base
-from .util.fixtures import TemplateTest
-from .util.helpers import flatten_result
-from .util.helpers import result_lines
+from mako.testing.assertions import assert_raises
+from mako.testing.assertions import assert_raises_message
+from mako.testing.assertions import eq_
+from mako.testing.config import config
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
class ctx:
@@ -136,7 +134,7 @@ class EncodingTest(TemplateTest):
def test_unicode_file_lookup(self):
lookup = TemplateLookup(
- directories=[template_base],
+ directories=[config.template_base],
output_encoding="utf-8",
default_filters=["decode.utf8"],
)
@@ -165,11 +163,11 @@ class EncodingTest(TemplateTest):
),
)
- self.assertRaises(
+ assert_raises(
exceptions.CompileException,
Template,
filename=self._file_path("badbom.html"),
- module_directory=module_base,
+ module_directory=config.module_base,
)
def test_unicode_memory(self):
@@ -399,7 +397,7 @@ quand une drôle de petite voix m’a réveillé. Elle disait:
def test_read_unicode(self):
lookup = TemplateLookup(
- directories=[template_base],
+ directories=[config.template_base],
filesystem_checks=True,
output_encoding="utf-8",
)
@@ -1228,40 +1226,47 @@ for utf8 in (True, False):
class ModuleDirTest(TemplateTest):
- def tearDown(self):
+ def teardown_method(self):
import shutil
- shutil.rmtree(module_base, True)
+ shutil.rmtree(config.module_base, True)
def test_basic(self):
t = self._file_template("modtest.html")
t2 = self._file_template("subdir/modtest.html")
- eq_(t.module.__file__, os.path.join(module_base, "modtest.html.py"))
+ eq_(
+ t.module.__file__,
+ os.path.join(config.module_base, "modtest.html.py"),
+ )
eq_(
t2.module.__file__,
- os.path.join(module_base, "subdir", "modtest.html.py"),
+ os.path.join(config.module_base, "subdir", "modtest.html.py"),
)
def test_callable(self):
def get_modname(filename, uri):
return os.path.join(
- module_base,
+ config.module_base,
os.path.dirname(uri)[1:],
"foo",
os.path.basename(filename) + ".py",
)
- lookup = TemplateLookup(template_base, modulename_callable=get_modname)
+ lookup = TemplateLookup(
+ config.template_base, modulename_callable=get_modname
+ )
t = lookup.get_template("/modtest.html")
t2 = lookup.get_template("/subdir/modtest.html")
eq_(
t.module.__file__,
- os.path.join(module_base, "foo", "modtest.html.py"),
+ os.path.join(config.module_base, "foo", "modtest.html.py"),
)
eq_(
t2.module.__file__,
- os.path.join(module_base, "subdir", "foo", "modtest.html.py"),
+ os.path.join(
+ config.module_base, "subdir", "foo", "modtest.html.py"
+ ),
)
def test_custom_writer(self):
@@ -1274,17 +1279,17 @@ class ModuleDirTest(TemplateTest):
f.close()
lookup = TemplateLookup(
- template_base,
+ config.template_base,
module_writer=write_module,
- module_directory=module_base,
+ module_directory=config.module_base,
)
lookup.get_template("/modtest.html")
lookup.get_template("/subdir/modtest.html")
eq_(
canary,
[
- os.path.join(module_base, "modtest.html.py"),
- os.path.join(module_base, "subdir", "modtest.html.py"),
+ os.path.join(config.module_base, "modtest.html.py"),
+ os.path.join(config.module_base, "subdir", "modtest.html.py"),
],
)
@@ -1438,7 +1443,7 @@ class ModuleTemplateTest(TemplateTest):
]
-class TestTemplateAPI(unittest.TestCase):
+class TestTemplateAPI:
def test_metadata(self):
t = Template(
"""
diff --git a/test/test_tgplugin.py b/test/test_tgplugin.py
index 9d5799b..38998c2 100644
--- a/test/test_tgplugin.py
+++ b/test/test_tgplugin.py
@@ -1,9 +1,11 @@
from mako.ext.turbogears import TGPlugin
-from .util.fixtures import template_base
-from .util.fixtures import TemplateTest
-from .util.helpers import result_lines
+from mako.testing.config import config
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import result_lines
-tl = TGPlugin(options=dict(directories=[template_base]), extension="html")
+tl = TGPlugin(
+ options=dict(directories=[config.template_base]), extension="html"
+)
class TestTGPlugin(TemplateTest):
diff --git a/test/test_util.py b/test/test_util.py
index 6aa4c47..95c1cb4 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -1,16 +1,19 @@
import os
import sys
-import unittest
+
+import pytest
from mako import compat
from mako import exceptions
from mako import util
-from .util.assertions import assert_raises_message
-from .util.assertions import eq_
-from .util.exclusions import skip_if
+from mako.testing.assertions import assert_raises_message
+from mako.testing.assertions import eq_
+from mako.testing.assertions import in_
+from mako.testing.assertions import ne_
+from mako.testing.assertions import not_in
-class UtilTest(unittest.TestCase):
+class UtilTest:
def test_fast_buffer_write(self):
buf = util.FastEncodingBuffer()
buf.write("string a ")
@@ -38,16 +41,16 @@ class UtilTest(unittest.TestCase):
data = util.read_file(fn, "rb")
assert b"test_util" in data
- @skip_if(lambda: compat.pypy, "Pypy does this differently")
+ @pytest.mark.skipif(compat.pypy, reason="Pypy does this differently")
def test_load_module(self):
path = os.path.join(os.path.dirname(__file__), "module_to_import.py")
some_module = compat.load_module("test.module_to_import", path)
- self.assertNotIn("test.module_to_import", sys.modules)
- self.assertIn("some_function", dir(some_module))
+ not_in("test.module_to_import", sys.modules)
+ in_("some_function", dir(some_module))
import test.module_to_import
- self.assertNotEqual(some_module, test.module_to_import)
+ ne_(some_module, test.module_to_import)
def test_load_plugin_failure(self):
loader = util.PluginLoader("fakegroup")
diff --git a/test/testing/dummy.cfg b/test/testing/dummy.cfg
new file mode 100644
index 0000000..39644a3
--- /dev/null
+++ b/test/testing/dummy.cfg
@@ -0,0 +1,25 @@
+[boolean_values]
+yes = yes
+one = 1
+true = true
+on = on
+no = no
+zero = 0
+false = false
+off = off
+
+[additional_types]
+decimal_value = 100001.01
+datetime_value = 2021-12-04 00:05:23.283
+
+[type_mismatch]
+int_value = foo
+
+[missing_item]
+present_item = HERE
+
+[basic_values]
+int_value = 15421
+bool_value = true
+float_value = 14.01
+str_value = Ceci n'est pas une chaîne
diff --git a/test/testing/test_config.py b/test/testing/test_config.py
new file mode 100644
index 0000000..680d7a4
--- /dev/null
+++ b/test/testing/test_config.py
@@ -0,0 +1,176 @@
+import configparser
+from dataclasses import dataclass
+from datetime import datetime
+from decimal import Decimal
+from pathlib import Path
+
+import pytest
+
+from mako.testing._config import ConfigValueTypeError
+from mako.testing._config import MissingConfig
+from mako.testing._config import MissingConfigItem
+from mako.testing._config import MissingConfigSection
+from mako.testing._config import ReadsCfg
+from mako.testing.assertions import assert_raises_message_with_given_cause
+from mako.testing.assertions import assert_raises_with_given_cause
+
+PATH_TO_TEST_CONFIG = Path(__file__).parent / "dummy.cfg"
+
+
+@dataclass
+class BasicConfig(ReadsCfg):
+ int_value: int
+ bool_value: bool
+ float_value: float
+ str_value: str
+
+ section_header = "basic_values"
+
+
+@dataclass
+class BooleanConfig(ReadsCfg):
+ yes: bool
+ one: bool
+ true: bool
+ on: bool
+ no: bool
+ zero: bool
+ false: bool
+ off: bool
+
+ section_header = "boolean_values"
+
+
+@dataclass
+class UnsupportedTypesConfig(ReadsCfg):
+ decimal_value: Decimal
+ datetime_value: datetime
+
+ section_header = "additional_types"
+
+
+@dataclass
+class SupportedTypesConfig(ReadsCfg):
+ decimal_value: Decimal
+ datetime_value: datetime
+
+ section_header = "additional_types"
+ converters = {
+ Decimal: lambda v: Decimal(str(v)),
+ datetime: lambda v: datetime.fromisoformat(v),
+ }
+
+
+@dataclass
+class NonexistentSectionConfig(ReadsCfg):
+ some_value: str
+ another_value: str
+
+ section_header = "i_dont_exist"
+
+
+@dataclass
+class TypeMismatchConfig(ReadsCfg):
+ int_value: int
+
+ section_header = "type_mismatch"
+
+
+@dataclass
+class MissingItemConfig(ReadsCfg):
+ present_item: str
+ missing_item: str
+
+ section_header = "missing_item"
+
+
+class BasicConfigTest:
+ @pytest.fixture(scope="class")
+ def config(self):
+ return BasicConfig.from_cfg_file(PATH_TO_TEST_CONFIG)
+
+ def test_coercions(self, config):
+ assert isinstance(config.int_value, int)
+ assert isinstance(config.bool_value, bool)
+ assert isinstance(config.float_value, float)
+ assert isinstance(config.str_value, str)
+
+ def test_values(self, config):
+ assert config.int_value == 15421
+ assert config.bool_value == True
+ assert config.float_value == 14.01
+ assert config.str_value == "Ceci n'est pas une chaîne"
+
+ def test_error_on_loading_from_nonexistent_file(self):
+ assert_raises_with_given_cause(
+ MissingConfig,
+ FileNotFoundError,
+ BasicConfig.from_cfg_file,
+ "./n/o/f/i/l/e/h.ere",
+ )
+
+ def test_error_on_loading_from_nonexistent_section(self):
+ assert_raises_with_given_cause(
+ MissingConfigSection,
+ configparser.NoSectionError,
+ NonexistentSectionConfig.from_cfg_file,
+ PATH_TO_TEST_CONFIG,
+ )
+
+
+class BooleanConfigTest:
+ @pytest.fixture(scope="class")
+ def config(self):
+ return BooleanConfig.from_cfg_file(PATH_TO_TEST_CONFIG)
+
+ def test_values(self, config):
+ assert config.yes is True
+ assert config.one is True
+ assert config.true is True
+ assert config.on is True
+ assert config.no is False
+ assert config.zero is False
+ assert config.false is False
+ assert config.off is False
+
+
+class UnsupportedTypesConfigTest:
+ @pytest.fixture(scope="class")
+ def config(self):
+ return UnsupportedTypesConfig.from_cfg_file(PATH_TO_TEST_CONFIG)
+
+ def test_values(self, config):
+ assert config.decimal_value == "100001.01"
+ assert config.datetime_value == "2021-12-04 00:05:23.283"
+
+
+class SupportedTypesConfigTest:
+ @pytest.fixture(scope="class")
+ def config(self):
+ return SupportedTypesConfig.from_cfg_file(PATH_TO_TEST_CONFIG)
+
+ def test_values(self, config):
+ assert config.decimal_value == Decimal("100001.01")
+ assert config.datetime_value == datetime(2021, 12, 4, 0, 5, 23, 283000)
+
+
+class TypeMismatchConfigTest:
+ def test_error_on_load(self):
+ assert_raises_message_with_given_cause(
+ ConfigValueTypeError,
+ "Wrong value type for int_value",
+ ValueError,
+ TypeMismatchConfig.from_cfg_file,
+ PATH_TO_TEST_CONFIG,
+ )
+
+
+class MissingItemConfigTest:
+ def test_error_on_load(self):
+ assert_raises_message_with_given_cause(
+ MissingConfigItem,
+ "No config item for missing_item",
+ configparser.NoOptionError,
+ MissingItemConfig.from_cfg_file,
+ PATH_TO_TEST_CONFIG,
+ )
diff --git a/test/util/__init__.py b/test/util/__init__.py
deleted file mode 100644
index f8cb359..0000000
--- a/test/util/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from unittest import mock # noqa
diff --git a/test/util/exclusions.py b/test/util/exclusions.py
deleted file mode 100644
index 8eb596e..0000000
--- a/test/util/exclusions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import unittest
-
-from mako.util import update_wrapper
-
-
-def skip_if(predicate, reason=None):
- """Skip a test if predicate is true."""
- reason = reason or predicate.__name__
-
- def decorate(fn):
- fn_name = fn.__name__
-
- def maybe(*args, **kw):
- if predicate():
- msg = "'%s' skipped: %s" % (fn_name, reason)
- raise unittest.SkipTest(msg)
- else:
- return fn(*args, **kw)
-
- return update_wrapper(maybe, fn)
-
- return decorate
-
-
-def requires_pygments_14(fn):
- try:
- import pygments
-
- version = pygments.__version__
- except:
- version = "0"
- return skip_if(
- lambda: version < "1.4", "Requires pygments 1.4 or greater"
- )(fn)
-
-
-def requires_no_pygments_exceptions(fn):
- def go(*arg, **kw):
- from mako import exceptions
-
- exceptions._install_fallback()
- try:
- return fn(*arg, **kw)
- finally:
- exceptions._install_highlighting()
-
- return update_wrapper(go, fn)
diff --git a/tox.ini b/tox.ini
index 8b2b0d2..d8edd3c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -15,8 +15,6 @@ deps=pytest>=3.1.0
setenv=
cov: COVERAGE={[testenv]cov_args}
- TEST_TEMPLATE_BASE={toxinidir}{/}test{/}templates
- TEST_MODULE_BASE={env:TEST_TEMPLATE_BASE}{/}modules
commands=pytest {env:COVERAGE:} {posargs}