cmds.projects.CmdCreateFile: Add module
Add CmdCreateFile as a command to generate files from project metadata. It uses the new tmpl_render() engine, might serve as a central location to replace other code generating files, let's see how that evolves.
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
d449472ceb
commit
49016373e1
1 changed files with 102 additions and 0 deletions
102
src/python/jw/pkg/cmds/projects/CmdCreateFile.py
Normal file
102
src/python/jw/pkg/cmds/projects/CmdCreateFile.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
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 tmpl_render
|
||||
|
||||
def key_value(s):
|
||||
try:
|
||||
key, value = s.split('=', 1)
|
||||
except ValueError:
|
||||
raise ArgumentTypeError('Expected KEY=VALUE')
|
||||
return key, value
|
||||
|
||||
# TODO: Put the more elaborate stuff into lib
|
||||
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 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,
|
||||
)
|
||||
|
||||
extra_paths = []
|
||||
for m in prereq:
|
||||
path = self.app.find_dir(m)
|
||||
if path is None:
|
||||
log(WARNING, f'No project directory for module "{m}"')
|
||||
continue
|
||||
extra_paths.append(path)
|
||||
paths = ',\n'.join([f'"{path}"' for path in extra_paths])
|
||||
values: ListDict = {}
|
||||
kwargs = {
|
||||
'extra_paths': paths,
|
||||
}
|
||||
self.__update_dict(values, extra_fields)
|
||||
self.__update_dict(values, kwargs.items())
|
||||
|
||||
kwargs.update(extra_fields)
|
||||
return tmpl_render(
|
||||
'pyrightconfig.json', values, li_quote = True, li_delimiter = ',\n'
|
||||
)
|
||||
|
||||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(
|
||||
parent, 'create-file', help = 'Generate a file from project metadata'
|
||||
)
|
||||
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument(
|
||||
'--format',
|
||||
choices = [fmt.name.lower() for fmt in Fmt],
|
||||
help = 'Output format'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-f',
|
||||
'--field',
|
||||
action = 'append',
|
||||
type = key_value,
|
||||
default = [],
|
||||
metavar = 'KEY=VALUE',
|
||||
help = 'Additional fields to insert into the output file',
|
||||
)
|
||||
parser.add_argument('module', help = 'The module to generate the file for')
|
||||
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
method = getattr(self, 'render_' + args.format, None)
|
||||
if method is None: # Should be prevented by choices=[] but keeps linter happy
|
||||
raise Exception(f'Unsupported output format {args.format}')
|
||||
print(method(args.module, args.field))
|
||||
Loading…
Add table
Add a link
Reference in a new issue