Skip to content

Commit

Permalink
Add more tests of custom formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
jwodder committed Jun 8, 2021
1 parent 8ae7081 commit cd1fe71
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
12 changes: 11 additions & 1 deletion src/tinuous/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ def iterfiles(dirpath: Path) -> Iterator[Path]:


class LazySlicingFormatter(Formatter):
"""
A `string.Formatter` subclass that:
- accepts a second set of format kwargs that can refer to the main kwargs
or each other and are only templated as needed
- supports indexing strings & other sequences with slices
"""

def __init__(self, var_defs: Dict[str, str]):
self.var_defs: Dict[str, str] = var_defs
self.expanded_vars: Dict[str, str] = {}
Expand All @@ -73,7 +81,9 @@ def get_field(
) -> Any:
m = re.match(r"\w+", field_name)
assert m, f"format field name {field_name!r} does not start with arg_name"
key = m.group()
key: Union[int, str] = m.group()
if key.isdigit():
key = int(key)
obj = self.get_value(key, args, kwargs)
s = field_name[m.end() :]
while s:
Expand Down
37 changes: 36 additions & 1 deletion test/test_util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from types import SimpleNamespace
from typing import Any, Dict
import pytest
from tinuous.util import expand_template, parse_slice
from pytest_mock import MockerFixture
from tinuous.util import LazySlicingFormatter, expand_template, parse_slice


def test_expand_template() -> None:
Expand Down Expand Up @@ -58,3 +61,35 @@ def test_expand_template_unused_bad() -> None:
)
def test_parse_slice(s: str, sl: slice) -> None:
assert parse_slice(s) == sl


@pytest.mark.parametrize(
"fmt,args,kwargs,result",
[
("{0}", ["foo"], {}, "foo"),
(
"{foo.bar.baz}",
[],
{"foo": SimpleNamespace(bar=SimpleNamespace(baz="quux"))},
"quux",
),
("{foo[1][2]}", [], {"foo": ["abc", "def", "ghi"]}, "f"),
("{foo[bar][baz]}", [], {"foo": {"bar": {"baz": "quux"}}}, "quux"),
],
)
def test_lazy_slicing_formatter_basics(
fmt: str, args: list, kwargs: Dict[str, Any], result: str
) -> None:
assert LazySlicingFormatter({}).format(fmt, *args, **kwargs) == result


def test_lazy_slicing_formatter_undef_key() -> None:
with pytest.raises(KeyError):
LazySlicingFormatter({}).format("{foo}", bar=42)


def test_lazy_slicing_formatter_var_reuse(mocker: MockerFixture) -> None:
fmter = LazySlicingFormatter({"foo": "bar"})
spy = mocker.spy(fmter, "format")
assert fmter.format("-{foo}-{foo}-") == "-bar-bar-"
assert spy.call_args_list == [mocker.call("-{foo}-{foo}-"), mocker.call("bar")]
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ minversion = 3.3.0
deps =
pytest~=6.0
pytest-cov~=2.0
pytest-mock~=3.0
commands =
# Basic smoketest:
tinuous --help
Expand Down

0 comments on commit cd1fe71

Please sign in to comment.