cmds.projects.CmdCreateFile: Add --field-separator option
List values in a rendered template are joined with a fixed separator of ",\n" (comma plus newline), and there is no way to change that. Templates sometimes want a different separator, e.g. a plain newline or a single-line comma-separated list. Add a --field-separator option that controls how list values are joined in the rendered output. %n expands to a newline, and the default remains ",\n" for both formats. render_tmpl() applies the separator to the rendered template, while render_pyright() rejects any other value: the built-in pyrightconfig.json template is a fixed JSON document, and no alternative separator is supported for it. Update the help output test expectation accordingly. Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.85.1 Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
7f9f65153f
commit
1349665c39
4 changed files with 76 additions and 8 deletions
|
|
@ -55,32 +55,56 @@ class CmdCreateFile(Cmd): # export
|
||||||
p = 'render_'
|
p = 'render_'
|
||||||
return [name.removeprefix(p) for name in dir(self) if name.startswith(p)]
|
return [name.removeprefix(p) for name in dir(self) if name.startswith(p)]
|
||||||
|
|
||||||
|
def __format_separator(self, separator: str | None, default: str) -> str:
|
||||||
|
if separator is None:
|
||||||
|
return default
|
||||||
|
format_chars = {
|
||||||
|
'%n': '\n',
|
||||||
|
}
|
||||||
|
for src, dst in format_chars.items():
|
||||||
|
separator = separator.replace(src, dst)
|
||||||
|
return separator
|
||||||
|
|
||||||
def __render(
|
def __render(
|
||||||
self,
|
self,
|
||||||
template_name: str,
|
template_name: str,
|
||||||
values: list[RenderValues],
|
values: list[RenderValues],
|
||||||
li_quote: bool = False,
|
li_quote: bool = False,
|
||||||
li_delimiter: str = '\n',
|
li_separator: str = '\n',
|
||||||
) -> str:
|
) -> str:
|
||||||
return tmpl_render(
|
return tmpl_render(
|
||||||
template_name,
|
template_name,
|
||||||
values,
|
values,
|
||||||
li_quote = li_quote,
|
li_quote = li_quote,
|
||||||
li_delimiter = li_delimiter,
|
li_delimiter = li_separator,
|
||||||
search_path = self.app.args.search_path.split(':'),
|
search_path = self.app.args.search_path.split(':'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_tmpl(self, module: str, extra_fields: RenderValues) -> str:
|
def render_tmpl(
|
||||||
|
self,
|
||||||
|
module: str,
|
||||||
|
extra_fields: RenderValues,
|
||||||
|
separator: str | None,
|
||||||
|
) -> str:
|
||||||
template_name = self.app.args.template_name
|
template_name = self.app.args.template_name
|
||||||
if template_name is None:
|
if template_name is None:
|
||||||
raise Exception('Can\'t render template without name')
|
raise Exception('Can\'t render template without name')
|
||||||
return self.__render(
|
return self.__render(
|
||||||
template_name, [extra_fields],
|
template_name,
|
||||||
|
[extra_fields],
|
||||||
li_quote = self.app.args.quote,
|
li_quote = self.app.args.quote,
|
||||||
li_delimiter = ',\n'
|
li_separator = self.__format_separator(separator, ',\n'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_pyright(self, module: str, extra_fields: RenderValues) -> str:
|
def render_pyright(
|
||||||
|
self,
|
||||||
|
module: str,
|
||||||
|
extra_fields: RenderValues,
|
||||||
|
separator: str | None,
|
||||||
|
) -> str:
|
||||||
|
separator = self.__format_separator(separator, ',\n')
|
||||||
|
if separator != ',\n':
|
||||||
|
raise Exception(f'Unsupported separator for pyright config: "{separator}"')
|
||||||
extra_paths = []
|
extra_paths = []
|
||||||
for m in self.__jw_required(include_self = True):
|
for m in self.__jw_required(include_self = True):
|
||||||
path = self.app.find_dir(m, search_subdirs = ['src/python', 'tools/python'])
|
path = self.app.find_dir(m, search_subdirs = ['src/python', 'tools/python'])
|
||||||
|
|
@ -94,7 +118,7 @@ class CmdCreateFile(Cmd): # export
|
||||||
return self.__render(
|
return self.__render(
|
||||||
'pyrightconfig.json', [values, extra_fields],
|
'pyrightconfig.json', [values, extra_fields],
|
||||||
li_quote = True,
|
li_quote = True,
|
||||||
li_delimiter = ',\n'
|
li_separator = ',\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, parent: Parent) -> None:
|
def __init__(self, parent: Parent) -> None:
|
||||||
|
|
@ -142,6 +166,13 @@ class CmdCreateFile(Cmd): # export
|
||||||
'rendering output'
|
'rendering output'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--field-separator',
|
||||||
|
help = (
|
||||||
|
'Field separator. %%n expands to newline. Default value depends on '
|
||||||
|
'--format'
|
||||||
|
)
|
||||||
|
)
|
||||||
parser.add_argument('module', help = 'The module to generate the file for')
|
parser.add_argument('module', help = 'The module to generate the file for')
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -166,4 +197,4 @@ class CmdCreateFile(Cmd): # export
|
||||||
raise Exception(f'Unsupported output format {args.format}')
|
raise Exception(f'Unsupported output format {args.format}')
|
||||||
|
|
||||||
# -- Render
|
# -- Render
|
||||||
sys.stdout.write(method(args.module, fields))
|
sys.stdout.write(method(args.module, fields, args.field_separator))
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,7 @@ usage: jw-pkg.py projects create-file [-h] --format {pyright,tmpl}
|
||||||
[--template-name TEMPLATE_NAME]
|
[--template-name TEMPLATE_NAME]
|
||||||
[--quote] [-f KEY=VALUE]
|
[--quote] [-f KEY=VALUE]
|
||||||
[--field-keys FIELD_KEYS]
|
[--field-keys FIELD_KEYS]
|
||||||
|
[--field-separator FIELD_SEPARATOR]
|
||||||
module
|
module
|
||||||
|
|
||||||
Generate a file from project metadata
|
Generate a file from project metadata
|
||||||
|
|
@ -365,6 +366,9 @@ options:
|
||||||
not specified here is an error, and not passing one
|
not specified here is an error, and not passing one
|
||||||
makes the respective field go away from the rendering
|
makes the respective field go away from the rendering
|
||||||
output (default: None)
|
output (default: None)
|
||||||
|
--field-separator FIELD_SEPARATOR
|
||||||
|
Field separator. %n expands to newline. Default value
|
||||||
|
depends on --format (default: None)
|
||||||
============= Running: jw-pkg.py -t ../../../.. --log-level info projects create-pkg-config --help
|
============= Running: jw-pkg.py -t ../../../.. --log-level info projects create-pkg-config --help
|
||||||
usage: jw-pkg.py projects create-pkg-config [-h] [-F PROJECT_DESCR_FILE]
|
usage: jw-pkg.py projects create-pkg-config [-h] [-F PROJECT_DESCR_FILE]
|
||||||
[-d DESCRIPTION] [-n NAME]
|
[-d DESCRIPTION] [-n NAME]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
TOPDIR = ../../../../../../../..
|
||||||
|
|
||||||
|
include $(TOPDIR)/make/proj.mk
|
||||||
|
include $(JWBDIR)/make/py-run.mk
|
||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
test: run
|
||||||
25
test/unit/python/jw/pkg/cmds/projects/CmdCreateFile/test.py
Normal file
25
test/unit/python/jw/pkg/cmds/projects/CmdCreateFile/test.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
from jw.pkg.cmds.projects.CmdCreateFile import CmdCreateFile
|
||||||
|
|
||||||
|
# __format_separator() is a private method that does not use self, so an
|
||||||
|
# uninitialised instance is a sufficient receiver for the bound method
|
||||||
|
inst = CmdCreateFile.__new__(CmdCreateFile)
|
||||||
|
fmt = getattr(inst, '_CmdCreateFile__format_separator')
|
||||||
|
|
||||||
|
# -- __format_separator --
|
||||||
|
|
||||||
|
# A None separator falls back to the format's default
|
||||||
|
assert fmt(None, ',\n') == ',\n'
|
||||||
|
|
||||||
|
# %n expands to a newline, wherever it appears in the separator
|
||||||
|
assert fmt('%n', ',\n') == '\n'
|
||||||
|
assert fmt(',%n', '\n') == ',\n'
|
||||||
|
assert fmt('a%n b', '') == 'a\n b'
|
||||||
|
|
||||||
|
# Several %n expand independently
|
||||||
|
assert fmt('%n%n', '') == '\n\n'
|
||||||
|
|
||||||
|
# Anything that is not %n passes through untouched
|
||||||
|
assert fmt('%', '') == '%'
|
||||||
|
assert fmt('%x', '') == '%x'
|
||||||
|
|
||||||
|
print('All CmdCreateFile tests passed')
|
||||||
Loading…
Reference in a new issue