cmds.projects.lib.templates: Don't replace escaped markers
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m43s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m42s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m13s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m21s
CI / Packaging test (push) Successful in 0s
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m43s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m42s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m13s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m21s
CI / Packaging test (push) Successful in 0s
format_list_dict() substitutes {key} markers with str.replace(), which also
matches the marker inside ${key} and {{key}}, mangling text meant to
survive verbatim, e.g. the ${prefix} variable reference of a pkg-config
file. The built-in pkg-config template works around that with doubled
braces, which produces {/usr}-style output instead.
Replace the markers with a regular expression that skips markers preceded
by '$' or '{', and let the pkg-config template use the ${prefix} and
${exec_prefix} references pkg-config expects.
Extend the unit tests with marker escaping, value escaping, quoting,
indentation, and the rendering of the built-in templates.
Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
955fb8101b
commit
61280e4695
2 changed files with 100 additions and 10 deletions
|
|
@ -1,9 +1,14 @@
|
|||
import os
|
||||
import tempfile
|
||||
|
||||
from jw.pkg.cmds.projects.lib.templates import (
|
||||
format_list_dict,
|
||||
is_list_dict,
|
||||
is_str_dict,
|
||||
is_tuple_list,
|
||||
merge_values,
|
||||
render_values_to_list_dict,
|
||||
tmpl_render,
|
||||
)
|
||||
|
||||
# -- Type guards --
|
||||
|
|
@ -47,6 +52,85 @@ try:
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# -- format_list_dict --
|
||||
|
||||
# A plain {key} marker is substituted
|
||||
assert format_list_dict('a {key} b', {'key': ['x', 'y']}, False, ', ') == \
|
||||
'a x, y b'
|
||||
|
||||
# ${key} is a literal, e.g. a pkg-config variable reference
|
||||
assert format_list_dict(
|
||||
'exec_prefix = ${prefix}', {'prefix': ['/usr']}, False, '\n'
|
||||
) == 'exec_prefix = ${prefix}'
|
||||
|
||||
# {{key}} is a literal, too
|
||||
assert format_list_dict('{{prefix}}', {'prefix': ['/usr']}, False, '\n') == \
|
||||
'{{prefix}}'
|
||||
|
||||
# A ${key} next to a real marker: only the marker is substituted
|
||||
assert format_list_dict('x = {p} ${p}', {'p': ['v']}, False, '\n') == \
|
||||
'x = v ${p}'
|
||||
|
||||
# Backslashes in the value are not treated as regex replacements
|
||||
assert format_list_dict('{p}', {'p': ['a\\b', 'c$1']}, False, '\n') == \
|
||||
'a\\b\nc$1'
|
||||
|
||||
# li_quote wraps each list element in double quotes
|
||||
assert format_list_dict('{p}', {'p': ['a', 'b']}, True, ',\n') == \
|
||||
'"a",\n"b"'
|
||||
|
||||
# Multi-line values are re-indented to the marker position
|
||||
assert format_list_dict(' {p}', {'p': ['x\ny']}, False, '\n') == ' x\n y'
|
||||
|
||||
# String values pass through unsplit
|
||||
assert format_list_dict('{p}', {'p': 'xyz'}, False, '\n') == 'xyz'
|
||||
|
||||
# -- tmpl_render --
|
||||
|
||||
# The built-in pkg-config template renders a valid .pc file
|
||||
expected_pc = (
|
||||
'prefix = /usr\n'
|
||||
'exec_prefix = ${prefix}\n'
|
||||
'includedir = ${prefix}/include\n'
|
||||
'libdir = ${exec_prefix}/lib\n'
|
||||
'\n'
|
||||
'Name: jw-pkg\n'
|
||||
'Description: desc\n'
|
||||
'Version: 1.0\n'
|
||||
)
|
||||
assert tmpl_render(
|
||||
'pkg-config',
|
||||
[{
|
||||
'prefix': '/usr', 'name': 'jw-pkg', 'description': 'desc', 'version': '1.0'
|
||||
}]
|
||||
) == expected_pc
|
||||
|
||||
# A template file from the search path wins over the built-ins
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
path = os.path.join(tmp, 'my-tmpl')
|
||||
with open(path, 'w') as f:
|
||||
f.write('hello {who}\n')
|
||||
assert tmpl_render(
|
||||
'my-tmpl', [{
|
||||
'who': 'world'
|
||||
}], search_path = [tmp]
|
||||
) == 'hello world\n'
|
||||
|
||||
# A missing template falls back to the built-ins
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
assert tmpl_render(
|
||||
'pkg-config', [{
|
||||
'prefix': '/usr'
|
||||
}], search_path = [tmp]
|
||||
).startswith('prefix = /usr\n')
|
||||
|
||||
# An unknown template without search path raises
|
||||
try:
|
||||
tmpl_render('no-such-template', [])
|
||||
assert False, 'Should have raised'
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# -- merge_values --
|
||||
|
||||
# String values are merged as whole strings, not character by character
|
||||
|
|
@ -70,4 +154,4 @@ assert merge_values(
|
|||
'a': ['x', 'y', 'z'], 'b': ['w']
|
||||
}
|
||||
|
||||
print('All templates merge tests passed')
|
||||
print('All templates tests passed')
|
||||
|
|
|
|||
Loading…
Reference in a new issue