diff options
author | Michael Bourke <michael@iter8ve.com> | 2022-01-09 16:38:12 +1100 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-14 09:57:14 -0500 |
commit | 7e52b60b7dac75a3c7177e69244123c0dad9e9d9 (patch) | |
tree | 2df96da5716169b2351f442c272a39ed6940332f | |
parent | 3c3196754b55b48c044e59a5beacb9a13bc25114 (diff) | |
download | mako-7e52b60b7dac75a3c7177e69244123c0dad9e9d9.tar.gz |
Refactor test.util into mako.testing
Fixes: #349
Change-Id: I202c252a913fb72cc328a6e7f0f33174802487d3
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) @@ -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) @@ -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} |