Improve Python config file template substitution #8

Merged
Jan Lindemann merged 10 commits from jan/feature/20260609-pyproject-toml-add-mypypath into master 2026-06-09 08:13:09 +02:00 AGit
Showing only changes of commit da877c624f - Show all commits

cmds.projects.CmdCreateFile: Add more options

- Add an additional, more generic value that --format understands: "tmpl". If chosen, the template selected by the new option --template-name is rendered by replacing --field key=value pairs.
- This commit also adds the option --quote, which makes the renderer enclose the rendered variable values in double quotes.
Signed-off-by: Jan Lindemann <jan@janware.com>
Jan Lindemann 2026-06-04 07:29:29 +02:00
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61

View file

@ -1,11 +1,10 @@
from argparse import ArgumentParser, ArgumentTypeError, Namespace
from enum import Enum, auto
from typing import Iterable, TypeAlias
from ...lib.log import WARNING, log
from .Cmd import Cmd, Parent
from .lib.pkg_relations import VersionSyntax, pkg_relations
from .lib.templates import RenderValues, tmpl_render
from .lib.templates import ListDict, RenderValues, tmpl_render
def key_value(s):
try:
@ -18,24 +17,26 @@ def key_value(s):
class Fmt(Enum):
Pyright = auto()
TupleList: TypeAlias = Iterable[tuple[str, str]]
ListDict: TypeAlias = dict[str, list[str]]
class CmdCreateFile(Cmd): # export
def __tuple_list_to_dict(self, src: TupleList) -> ListDict:
ret: ListDict = {}
for key, val in src:
entry = ret.setdefault(key, [])
entry.append(val)
return ret
def __update_dict(self, dst: ListDict, src: TupleList) -> ListDict:
ret = dst
for key, val in src:
entry = ret.setdefault(key, [])
entry.append(val)
return ret
def __jw_required(self, module: str | None = None) -> list[str]:
if module is None:
module = self.app.args.module
if module is None:
raise Exception('Can\'t get required packages without module name')
return pkg_relations(
self.app,
rel_type = 'requires',
flavours = ['run'],
subsections = ['jw'],
seed_pkgs = [module],
syntax = VersionSyntax.names_only,
no_subpackages = True,
recursive = True,
quote = False,
hide_self = False,
hide_jw_pkg = False,
)
def __render(
self,
@ -52,23 +53,19 @@ class CmdCreateFile(Cmd): # export
search_path = self.app.args.search_path.split(':'),
)
def render_pyright(self, module: str, extra_fields: TupleList) -> str:
prereq = pkg_relations(
self.app,
rel_type = 'requires',
flavours = ['run'],
subsections = ['jw'],
seed_pkgs = [module],
syntax = VersionSyntax.names_only,
no_subpackages = True,
recursive = True,
quote = False,
hide_self = False,
hide_jw_pkg = False,
def render_tmpl(self, module: str, extra_fields: RenderValues) -> str:
template_name = self.app.args.template_name
if template_name is None:
raise Exception('Can\'t render template without name')
return self.__render(
template_name, [extra_fields],
li_quote = self.app.args.quote,
li_delimiter = ',\n'
)
def render_pyright(self, module: str, extra_fields: RenderValues) -> str:
extra_paths = []
for m in prereq:
for m in self.__jw_required():
path = self.app.find_dir(m, search_subdirs = ['src/python', 'tools/python'])
if path is None:
log(WARNING, f'No project directory for module "{m}"')
@ -77,10 +74,10 @@ class CmdCreateFile(Cmd): # export
values: ListDict = {
'extra_paths': extra_paths,
}
self.__update_dict(values, extra_fields)
return self.__render(
'pyrightconfig.json', [values], li_quote = True, li_delimiter = ',\n'
'pyrightconfig.json', [values, extra_fields],
li_quote = True,
li_delimiter = ',\n'
)
def __init__(self, parent: Parent) -> None:
@ -92,14 +89,22 @@ class CmdCreateFile(Cmd): # export
super().add_arguments(parser)
parser.add_argument(
'--format',
choices = [fmt.name.lower() for fmt in Fmt],
help = 'Output format'
help = (
'Output format, for example: '
', '.join([fmt.name.lower() for fmt in Fmt])
)
)
parser.add_argument(
'--search-path',
default = '/etc/opt/jw-pkg/templates',
help = 'Template search path, colon separated',
)
parser.add_argument('--template-name', help = 'Template file name')
parser.add_argument(
'--quote',
action = 'store_true',
help = 'Enclose variable values in double quotes before substituting'
)
parser.add_argument(
'-f',
'--field',