Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic tests for jinja2cli #123

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ nosetests.xml

.pytest_cache
dist/

.python-version
*.txt
.venv
.vscode
*.code-workspace
.idea
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
test:
pytest -v
tox

publish: clean
python setup.py sdist bdist_wheel
twine upload -s dist/*

clean:
rm -rf *.egg-info *.egg dist build .pytest_cache
rm -rf .tox/py* .tox/dist/*

.PHONY: test publish clean
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Jinja2
9 changes: 9 additions & 0 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-e git+https://github.com/mattrobenolt/jinja2-cli.git#egg=jinja2_cli
pytest
pytest-xdist
schema
toml
pyyaml
xmltodict
json5
hjson; python_version > '2.7'
111 changes: 111 additions & 0 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Common helper classes and functions used by test cases
"""

import subprocess
import sys

from jinja2 import nodes
from jinja2.ext import Extension

from jinja2cli import cli


class UpperCaseExtension(Extension):
"""A custom jinja2 extension that adds a new tag `upperrcase`,
an upper case block capitalizes all text an variables within
the block.

example:
```template.j2
..
{% uppercase %}{{foo}}{% enduppercase %}
..
```

```
>>> import jinja2
>>> from common import UpperCaseExtension

>>> env = jinja2.Environment(extensions=[UpperCaseExtension])
>>> loader = jinja2.FileSystemLoader("path/to/templates/dir")
>>> template = loader.load(env, "template.j2")
>>> render = template.render(foo="bar")
>>> print(render)
BAR
```
"""

tags = {"uppercase"}

def parse(self, parser):
lineno = next(parser.stream).lineno
args = [] # the uppercase tag doesn't require any arguments
body = parser.parse_statements(["name:enduppercase"], drop_needle=True)
ret = nodes.CallBlock(
self.call_method("_uppercase", args), [], [], body
).set_lineno(lineno)
return ret

def _uppercase(self, caller=None):
if caller is not None:
return caller().upper()
return ""


class CliOpts(object):
"""A helper class to mimic jinja2cli.cli options (passed from optparse)"""

def __init__(self, **opts):
self.format = opts.get("format", None)
self.D = opts.get("D", None)
self.extensions = opts.get("extensions", [])
self.section = opts.get("section", None)
self.outfile = opts.get("outfile", None)
self.strict = opts.get("strict", False)


def is_python_version(major, minor=None):
if minor is None:
return sys.version_info.major == major
return sys.version_info[:2] == (major, minor)


def to_unicode(string):
if is_python_version(3):
return bytes(string, "utf-8")
else:
return unicode(string)


def run_jinja2(template, datafile="", args=None, input_data=""):
"""Run jinja2 with the given template, path to data file, input_data and other options, capture the error and output streams and return them"""

cmd_args = [template]

if datafile:
cmd_args.append(datafile)

if args:
cmd_args.extend(list(args))

proc = subprocess.Popen(
["jinja2"] + cmd_args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)

if input_data:
out, err = proc.communicate(input=to_unicode(input_data))
else:
out, err = proc.communicate()

try:
proc.terminate()
except OSError:
pass

return cli.force_text(out), cli.force_text(err)
26 changes: 26 additions & 0 deletions tests/test_data_input_stdin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os

import pytest

from jinja2cli import cli

from .common import run_jinja2

TEMPLATE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "files/template.j2"
)


def test_stdin_implicit_subprocess():
out, err = run_jinja2(TEMPLATE, input_data="title: foo")
assert "" == err
assert "foo" == out


def test_stdin_explicit_subprocess():
out, err = run_jinja2(TEMPLATE, "-", input_data="title: foo")
assert "" == err
assert "foo" == out
26 changes: 26 additions & 0 deletions tests/test_format_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest

from jinja2cli import cli

EnvParserFn, EnvExpectException, EnvRaiseException = cli.get_format("env")


@pytest.mark.parametrize(
("env", "env_data"),
[
("", {}),
("foo=bar", {"foo": "bar"}),
("foo=", {"foo": ""}),
("foo=bar\nham=spam", {"foo": "bar", "ham": "spam"}),
],
)
def test_env(env, env_data):
assert EnvParserFn(env) == env_data


def test_env_multiline_value():
with pytest.raises(EnvExpectException):
EnvParserFn("foo=bar\nham\nspam")
67 changes: 67 additions & 0 deletions tests/test_format_hjson.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest

from jinja2cli import cli
from .common import is_python_version

try:
HJsonParserFn, HJsonExpectException, HJsonRaiseException = cli.get_format(
"hjson"
)
except cli.InvalidDataFormat:
HJsonParserFn = lambda x: x
HJsonExpectException = BaseException
HJsonRaiseException = BaseException


HJSON_STR = """{
// use #, // or /**/ comments,
// omit quotes for keys
key: 1
// omit quotes for strings
contains: everything on this line
// omit commas at the end of a line
cool: {
foo: 1
bar: 2
}
// allow trailing commas
list: [
1,
2,
]
// and use multiline strings
realist:
'''
My half empty glass,
I will fill your empty half.
Now you are half full.
'''
}
"""

EXPECTED_DATA = {
"key": 1,
"contains": "everything on this line",
"cool": {"foo": 1, "bar": 2},
"list": [1, 2],
"realist": "My half empty glass,\nI will fill your empty half.\nNow you are half full.",
}


@pytest.mark.skipif(
is_python_version(2, 7),
reason="there's no hjson package compatible with Python2.7",
)
@pytest.mark.parametrize(
("hjson", "expected"),
[
("", {}),
("{}", {}),
(HJSON_STR, EXPECTED_DATA),
],
)
def test_hjson(hjson, expected):
assert HJsonParserFn(hjson) == expected
57 changes: 57 additions & 0 deletions tests/test_format_ini.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest

from jinja2cli import cli
from .common import is_python_version

IIinParserFn, IniExpectException, IniRaiseException = cli.get_format("ini")


@pytest.mark.xfail(
is_python_version(3, 12),
strict=True,
raises=AttributeError,
reason="Jinja2cli uses `configparser.ConfigParser.readfp` that is deprecated in Python3.12",
)
@pytest.mark.parametrize(
("ini", "ini_data"),
[
("", {}),
("[data]\nfoo=bar", {"data": {"foo": "bar"}}),
("[data]\nfoo=bar\nham=spam", {"data": {"foo": "bar", "ham": "spam"}}),
(
"[data1]\nfoo=bar\n[data2]\nham=spam",
{"data1": {"foo": "bar"}, "data2": {"ham": "spam"}},
),
pytest.param(
"[data]\nfoo=bar\n[data]\nham=spam",
{"data": {"foo": "bar", "ham": "spam"}},
marks=pytest.mark.skipif(
not is_python_version(2, 7),
reason="Duplicate data section names are not supported by configparser in python versions > 2.7",
),
),
],
)
def test_ini(ini, ini_data):
assert IIinParserFn(ini) == ini_data


@pytest.mark.xfail(
is_python_version(3, 12),
strict=True,
raises=AttributeError,
reason="Jinja2cli uses `configparser.ConfigParser.readfp` that is deprecated in Python3.12",
)
@pytest.mark.parametrize(
("data"),
[
("foo=bar\nham=spam"),
("[data]foo=\nbar"),
],
)
def test_ini_errors(data):
with pytest.raises(IniExpectException):
IIinParserFn(data)
35 changes: 35 additions & 0 deletions tests/test_format_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


import pytest

from jinja2cli import cli

JsonParserFn, JsonExpectException, JsonRaiseException = cli.get_format("json")


@pytest.mark.parametrize(
("json", "json_data"),
[
("{}", {}),
('{"foo": "bar"}', {"foo": "bar"}),
('{"": "bar"}', {"": "bar"}),
('{"foo": "bar", "ham": "spam"}', {"foo": "bar", "ham": "spam"}),
],
)
def test_json(json, json_data):
assert JsonParserFn(json) == json_data


@pytest.mark.parametrize(
("data"),
[
(""),
('{foo: "bar"}'),
('{"foo": bar}'),
],
)
def test_json_errors(data):
with pytest.raises(JsonExpectException):
JsonParserFn(data)
Loading