1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2025-2026 Benjamin Abendroth <braph93@gmx.de>
'''This module contains code for validating completing definitions.'''
# Unlike the `scheme_validator`, this validator operates directly on Python
# objects and therefore does not have access to line and column information.
# To save code and maintain consistency, we reuse the validation logic
# from `scheme_validator` by wrapping the objects in `ValueWithoutTrace`.
# This provides the same structure as used in `scheme_validator`, except that
# we use `ValueWithoutTrace` instead of `ValueWithTrace`.
from types import NoneType
from . import scheme_validator
from .value_with_trace import ValueWithOutTrace
def _mk_value_without_trace(value):
if isinstance(value, ValueWithOutTrace):
return value
if isinstance(value, (NoneType, str, int, float, bool)):
return ValueWithOutTrace(value)
mk = _mk_value_without_trace
if isinstance(value, (list, tuple)):
return ValueWithOutTrace(list(map(mk, value)))
if isinstance(value, dict):
return ValueWithOutTrace({mk(k): mk(v) for k, v in value.items()})
raise AssertionError(f"Not reached: {value!r}")
def _option_to_definition(option):
return {
'option_strings': option.option_strings,
'metavar': option.metavar,
'help': option.help,
'complete': option.complete,
'nosort': option.nosort,
'groups': option.groups,
'optional_arg': option.optional_arg,
'repeatable': option.repeatable,
'final': option.final,
'hidden': option.hidden,
'when': option.when,
'capture': option.capture,
}
def _positional_to_definition(positional):
return {
'number': positional.number,
'metavar': positional.metavar,
'help': positional.help,
'repeatable': positional.repeatable,
'complete': positional.complete,
'nosort': positional.nosort,
'when': positional.when,
'capture': positional.capture,
}
def _commandline_to_definition(cmdline):
options = list(map(_option_to_definition, cmdline.options))
positionals = list(map(_positional_to_definition, cmdline.positionals))
definition = {
'prog': cmdline.get_command_path(),
'help': cmdline.help,
'aliases': cmdline.aliases,
'wraps': cmdline.wraps,
'abbreviate_commands': cmdline.abbreviate_commands,
'abbreviate_options': cmdline.abbreviate_options,
'inherit_options': cmdline.inherit_options,
'options': options,
'positionals': positionals,
}
return _mk_value_without_trace(definition)
def _commandlines_to_definition_list(commandline):
result = []
def callback(cmdline):
result.append(_commandline_to_definition(cmdline))
commandline.visit_commandlines(callback)
return result
def validate_commandlines(cmdline):
'''Validate commandlines.'''
definitions = _commandlines_to_definition_list(cmdline)
scheme_validator.validate(definitions)
|