Improvements
* Preserve comments in Jinja2 templates * Handle truthy/falsy statements better * Handle params that have an empty value (php.ini is notorious) * Add indentation to yaml and also starting --- so yamllint passes
This commit is contained in:
parent
2be1e9e895
commit
f992da47ee
5 changed files with 396 additions and 13 deletions
|
|
@ -1,7 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import configparser
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ def test_toml_sample_roundtrip():
|
|||
assert fmt == "toml"
|
||||
|
||||
flat_items = flatten_config(fmt, parsed)
|
||||
assert flat_items, "Expected at least one flattened item from TOML sample"
|
||||
assert flat_items
|
||||
|
||||
defaults_yaml = generate_defaults_yaml("jinjaturtle", flat_items)
|
||||
defaults = yaml.safe_load(defaults_yaml)
|
||||
|
|
@ -84,10 +84,16 @@ def test_toml_sample_roundtrip():
|
|||
assert key == key.lower()
|
||||
assert " " not in key
|
||||
|
||||
# template generation
|
||||
template = generate_template(fmt, parsed, "jinjaturtle")
|
||||
# template generation – **now with original_text**
|
||||
original_text = toml_path.read_text(encoding="utf-8")
|
||||
template = generate_template(
|
||||
fmt, parsed, "jinjaturtle", original_text=original_text
|
||||
)
|
||||
assert isinstance(template, str)
|
||||
assert template.strip(), "Template for TOML sample should not be empty"
|
||||
assert template.strip()
|
||||
|
||||
# comments from the original file should now be preserved
|
||||
assert "# This is a TOML document" in template
|
||||
|
||||
# each default variable name should appear in the template as a Jinja placeholder
|
||||
for var_name in defaults:
|
||||
|
|
@ -120,7 +126,9 @@ def test_ini_php_sample_roundtrip():
|
|||
assert " " not in key
|
||||
|
||||
# template generation
|
||||
template = generate_template(fmt, parsed, "php")
|
||||
original_text = ini_path.read_text(encoding="utf-8")
|
||||
template = generate_template(fmt, parsed, "php", original_text=original_text)
|
||||
assert "; About this file" in template
|
||||
assert isinstance(template, str)
|
||||
assert template.strip(), "Template for php.ini sample should not be empty"
|
||||
|
||||
|
|
@ -189,3 +197,92 @@ def test_generate_template_type_and_format_errors():
|
|||
# unsupported format
|
||||
with pytest.raises(ValueError):
|
||||
generate_template("yaml", parsed=None, role_prefix="role")
|
||||
|
||||
# unsupported format even when original_text is provided
|
||||
with pytest.raises(ValueError):
|
||||
generate_template(
|
||||
"yaml",
|
||||
parsed=None,
|
||||
role_prefix="role",
|
||||
original_text="foo=bar",
|
||||
)
|
||||
|
||||
|
||||
def test_normalize_default_value_true_false_strings():
|
||||
# 'true'/'false' strings should be preserved as strings and double-quoted in YAML.
|
||||
flat_items = [
|
||||
(("section", "foo"), "true"),
|
||||
(("section", "bar"), "FALSE"),
|
||||
]
|
||||
defaults_yaml = generate_defaults_yaml("role", flat_items)
|
||||
data = yaml.safe_load(defaults_yaml)
|
||||
assert data["role_section_foo"] == "true"
|
||||
assert data["role_section_bar"] == "FALSE"
|
||||
|
||||
|
||||
def test_split_inline_comment_handles_quoted_hash():
|
||||
# The '#' inside quotes should not start a comment; the one outside should.
|
||||
text = " 'foo # not comment' # real"
|
||||
value, comment = core._split_inline_comment(text, {"#"})
|
||||
assert "not comment" in value
|
||||
assert comment.strip() == "# real"
|
||||
|
||||
|
||||
def test_generate_template_fallback_toml_and_ini():
|
||||
# When original_text is not provided, generate_template should use the
|
||||
# older fallback generators based on the parsed structures.
|
||||
parsed_toml = {
|
||||
"title": "Example",
|
||||
"server": {"port": 8080, "host": "127.0.0.1"},
|
||||
"logging": {
|
||||
"file": {"path": "/tmp/app.log"}
|
||||
}, # nested table to hit recursive walk
|
||||
}
|
||||
tmpl_toml = generate_template("toml", parsed=parsed_toml, role_prefix="role")
|
||||
assert "[server]" in tmpl_toml
|
||||
assert "role_server_port" in tmpl_toml
|
||||
assert "[logging]" in tmpl_toml or "[logging.file]" in tmpl_toml
|
||||
|
||||
parser = configparser.ConfigParser()
|
||||
# foo is quoted in the INI text to hit the "preserve quotes" branch
|
||||
parser["section"] = {"foo": '"bar"', "num": "42"}
|
||||
tmpl_ini = generate_template("ini", parsed=parser, role_prefix="role")
|
||||
assert "[section]" in tmpl_ini
|
||||
assert "role_section_foo" in tmpl_ini
|
||||
assert '"{{ role_section_foo }}"' in tmpl_ini # came from quoted INI value
|
||||
|
||||
|
||||
def test_generate_ini_template_from_text_edge_cases():
|
||||
# Cover CRLF newlines, lines without '=', and lines with no key before '='.
|
||||
text = "[section]\r\nkey=value\r\nnoequals\r\n = bare\r\n"
|
||||
tmpl = core._generate_ini_template_from_text("role", text)
|
||||
# We don't care about exact formatting here, just that it runs and
|
||||
# produces some reasonable output.
|
||||
assert "[section]" in tmpl
|
||||
assert "role_section_key" in tmpl
|
||||
# The "noequals" line should be preserved as-is.
|
||||
assert "noequals" in tmpl
|
||||
# The " = bare" line has no key and should be left untouched.
|
||||
assert " = bare" in tmpl
|
||||
|
||||
|
||||
def test_generate_toml_template_from_text_edge_cases():
|
||||
# Cover CRLF newlines, lines without '=', empty keys, and inline tables
|
||||
# that both parse successfully and fail parsing.
|
||||
text = (
|
||||
"# comment\r\n"
|
||||
"[table]\r\n"
|
||||
"noequals\r\n"
|
||||
" = 42\r\n"
|
||||
'inline_good = { name = "abc", value = 1 }\r\n'
|
||||
"inline_bad = { invalid = }\r\n"
|
||||
)
|
||||
tmpl = core._generate_toml_template_from_text("role", text)
|
||||
# The good inline table should expand into two separate variables.
|
||||
assert "role_table_inline_good_name" in tmpl
|
||||
assert "role_table_inline_good_value" in tmpl
|
||||
# The bad inline table should fall back to scalar handling.
|
||||
assert "role_table_inline_bad" in tmpl
|
||||
# Ensure the lines without '=' / empty key were handled without exploding.
|
||||
assert "[table]" in tmpl
|
||||
assert "noequals" in tmpl
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue