2024-09-11 11:14:03 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
|
|
import enum, pathlib
|
|
|
|
|
import itertools
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import sys
|
|
|
|
|
from dataclasses import KW_ONLY, dataclass, field
|
|
|
|
|
from functools import partial, partialmethod
|
|
|
|
|
from operator import itemgetter
|
|
|
|
|
from time import sleep
|
|
|
|
|
|
|
|
|
|
import defl
|
|
|
|
|
from defl import CLIError, Null, Path, Undefined, cl, log, Assert, ArgTypeHint
|
2025-03-09 09:17:53 -04:00
|
|
|
from defl._argsFromObject_ import _DefaultParserNotSpecified, _MalformedArguments
|
2024-09-11 11:14:03 -04:00
|
|
|
from defl._typing_ import *
|
2025-03-09 09:17:53 -04:00
|
|
|
from defl._pydantic_ import *
|
2024-09-11 11:14:03 -04:00
|
|
|
from defl.testing_ import Test, Tester, TestState
|
|
|
|
|
from defl._argsFromObject2_ import *
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
defl.log.setLevel('i')
|
2024-09-11 11:14:03 -04:00
|
|
|
tester = Tester(name=__file__)
|
|
|
|
|
# TODO test choices
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
|
2024-09-11 11:14:03 -04:00
|
|
|
@dataclass(slots=True, kw_only=True, frozen=False)
|
|
|
|
|
class Cli:
|
|
|
|
|
a: int
|
|
|
|
|
b: int = 1
|
|
|
|
|
d: list = N
|
|
|
|
|
c: list = field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
_mapSubParsers: ClassVar[dict] = {'t': 'trueFalse1'}
|
|
|
|
|
|
|
|
|
|
def main(_, bb: str = 'cat'):
|
|
|
|
|
return {'a': _.a, 'b': _.b, 'd': _.d, 'c': _.c, 'bb': bb, 'me': 'Cli.main'}
|
|
|
|
|
|
|
|
|
|
def cli1(_, *extra):
|
|
|
|
|
return {'d': _.d, 'extra': extra}
|
|
|
|
|
|
|
|
|
|
def cli2(
|
2025-03-09 09:17:53 -04:00
|
|
|
_, aa: bool, bb: str = 'cat', /, cc: bool = True, notTyped=1, dd: list[str] | None = None, *extra, ee: str
|
2024-09-11 11:14:03 -04:00
|
|
|
):
|
|
|
|
|
return locals()
|
|
|
|
|
|
|
|
|
|
def cast(_, *extra: float) -> str:
|
|
|
|
|
return extra
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
def excludeMe(_): ...
|
2024-09-11 11:14:03 -04:00
|
|
|
|
|
|
|
|
def trueFalse(_, a: bool, b: bool = F, c: bool = T, d: bool = T):
|
|
|
|
|
return {'a': a, 'b': b, 'c': c, 'd': d}
|
|
|
|
|
|
|
|
|
|
def trueFalse1(_, b: bool = F):
|
|
|
|
|
return {'b': b}
|
|
|
|
|
|
|
|
|
|
def trueFalse2(_, false: bool = F, true: bool = T):
|
|
|
|
|
return {'false': false, 'true': true}
|
|
|
|
|
|
|
|
|
|
def listInput(_, aa: list[str], bb: str, cc: str, *extra):
|
|
|
|
|
return locals()
|
|
|
|
|
|
|
|
|
|
@dataclass(slots=True, kw_only=True, frozen=False)
|
|
|
|
|
class Cli2:
|
|
|
|
|
e: list = field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
def main2(_, ff: str = 'cat'):
|
|
|
|
|
parent = Cli.Cli2.main2._cliParent
|
|
|
|
|
return dict(
|
2025-03-09 09:17:53 -04:00
|
|
|
parent=parent.__class__.__name__,
|
|
|
|
|
ff=ff,
|
|
|
|
|
e=_.e,
|
|
|
|
|
a=parent.a,
|
|
|
|
|
b=parent.b,
|
|
|
|
|
d=parent.d,
|
|
|
|
|
c=parent.c,
|
|
|
|
|
me='Cli.Cli2.main2',
|
2024-09-11 11:14:03 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def cli12(_, *extra):
|
|
|
|
|
parent = Cli.Cli2.main2._cliParent
|
|
|
|
|
return dict(
|
2025-03-09 09:17:53 -04:00
|
|
|
parent=parent.__class__.__name__, a=parent.a, b=parent.b, d=parent.d, extra=extra, me='Cli.Cli2.cli12'
|
2024-09-11 11:14:03 -04:00
|
|
|
)
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
def cli22(_, aa: bool, bb: str = 'cat', /, cc: bool = True, notTyped=1, dd: list[str] | None = None, *extra):
|
2024-09-11 11:14:03 -04:00
|
|
|
return locals()
|
|
|
|
|
|
|
|
|
|
def cli32(_, aa: str, *bb, cc: str = 'default', dd: bool = False) -> str:
|
|
|
|
|
return locals()
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
def excludeMe2(_): ...
|
2024-09-11 11:14:03 -04:00
|
|
|
|
|
|
|
|
def listInput2(_, aa: list[str], bb: str, cc: str, *extra):
|
|
|
|
|
return locals()
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
|
2024-09-11 11:14:03 -04:00
|
|
|
@tester.add()
|
|
|
|
|
def parse():
|
|
|
|
|
# print(cli.toJson())
|
|
|
|
|
# afds
|
|
|
|
|
# Assert(cli.toJson()) ==
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-d', 1, '-d', 2, '-a', '1', 'cli1'])
|
|
|
|
|
Assert(res) == {'d': ['1', '2'], 'extra': ()}
|
|
|
|
|
res = ParseObj(Cli).parse(['-d', 1, '-d', 2, '-a', '1', 'cli1'])
|
|
|
|
|
Assert(res) == {'d': ['1', '2'], 'extra': ()}
|
|
|
|
|
res = ParseObj(Cli).parse(['-d', 1, '-d', 2, '-a', '1', 'cli1'])
|
|
|
|
|
Assert(res) == {'d': ['1', '2'], 'extra': ()}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', 2, '-b', 3, '-d', 1, '-d', 3, '-d', 4, 'main', '--bb', 'dog'])
|
|
|
|
|
Assert(res) == {
|
|
|
|
|
'a': 2,
|
|
|
|
|
'b': 3,
|
|
|
|
|
'd': ['1', '3', '4'],
|
|
|
|
|
'c': [],
|
|
|
|
|
'bb': 'dog',
|
|
|
|
|
'me': 'Cli.main',
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
res = ParseObj(Cli).parse(['-a', 2, '-b', 3, '-d', 1, '-d', 3, '-d', 4, 'Cli2', '-e', 9, '-e', 8, 'main2', '-f', 7])
|
2024-09-11 11:14:03 -04:00
|
|
|
Assert(res) == {
|
|
|
|
|
'parent': 'Cli',
|
|
|
|
|
'ff': '7',
|
|
|
|
|
'e': ['9', '8'],
|
|
|
|
|
'a': 2,
|
|
|
|
|
'b': 3,
|
|
|
|
|
'd': ['1', '3', '4'],
|
|
|
|
|
'c': [],
|
2025-03-09 09:17:53 -04:00
|
|
|
'me': 'Cli.Cli2.main2',
|
2024-09-11 11:14:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
2025-03-09 09:17:53 -04:00
|
|
|
res = ParseObj(Cli).parse(
|
|
|
|
|
['-a', 2, '-b', 3, '-d', 1, '-d', 3, '-d', 4, 'Cli2', 'main2', r'\-e', 9, r'\-e', 8, 'main2', r'\-f', 7]
|
|
|
|
|
)
|
2024-09-11 11:14:03 -04:00
|
|
|
raise ValueError('')
|
|
|
|
|
except UnusableExtraArgError:
|
|
|
|
|
...
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
res = ParseObj(Cli).parse(
|
|
|
|
|
['-a', 2, '-b', 3, '-d', 1, '-d', 3, '-d', 4, 'Cli2', 'cli12', r'\-e', 9, r'\-e', 8, 'main2', r'\-f', 7]
|
|
|
|
|
)
|
2024-09-11 11:14:03 -04:00
|
|
|
Assert(res) == {
|
|
|
|
|
'parent': 'Cli',
|
|
|
|
|
'a': 2,
|
|
|
|
|
'b': 3,
|
|
|
|
|
'd': ['1', '3', '4'],
|
|
|
|
|
'extra': ('-e', '9', '-e', '8', 'main2', '-f', '7'),
|
2025-03-09 09:17:53 -04:00
|
|
|
'me': 'Cli.Cli2.cli12',
|
2024-09-11 11:14:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'cast', '1', '2'])
|
|
|
|
|
Assert(res) == (1.0, 2.0)
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'trueFalse1'])
|
|
|
|
|
Assert(res) == {'b': F}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 't'])
|
|
|
|
|
Assert(res) == {'b': F}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'trueFalse2'])
|
|
|
|
|
Assert(res) == {'false': F, 'true': T}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'trueFalse2', '-t'])
|
|
|
|
|
Assert(res) == {'false': F, 'true': F}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'trueFalse'])
|
|
|
|
|
Assert(res) == {'a': F, 'b': F, 'c': T, 'd': T}
|
|
|
|
|
|
|
|
|
|
res = ParseObj(Cli).parse(['-a', '1', '-d', 1, 'trueFalse', '-a', '-b', '-c', '-d'])
|
|
|
|
|
Assert(res) == {'a': not F, 'b': not F, 'c': not T, 'd': not T}
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
|
2024-09-11 11:14:03 -04:00
|
|
|
@tester.add()
|
|
|
|
|
def parse():
|
|
|
|
|
try:
|
|
|
|
|
res = ParseObj(Cli).parse(['-h'])
|
|
|
|
|
raise ValueError()
|
|
|
|
|
except HelpMessage:
|
|
|
|
|
...
|
|
|
|
|
|
2025-03-09 09:17:53 -04:00
|
|
|
|
|
|
|
|
@dataclass(slots=T, kw_only=T, frozen=F)
|
|
|
|
|
class C1:
|
|
|
|
|
l1: list[dict[str, int]]
|
|
|
|
|
|
|
|
|
|
def ii(_, l2: list[dict[str, int]]):
|
|
|
|
|
return (_.l1, l2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@tester.add()
|
|
|
|
|
def parse():
|
|
|
|
|
res = ParseObj(C1).parse(
|
|
|
|
|
['--l1', '{"1":1,"2":2}', '--l1', '{"3":3,"4":4}', 'ii', '--l2', '{"5":5,"6":6}', '--l2', '{"7":7,"8":8}']
|
|
|
|
|
)
|
|
|
|
|
Assert(res) == ([{'1': 1, '2': 2}, {'3': 3, '4': 4}], [{'5': 5, '6': 6}, {'7': 7, '8': 8}])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(slots=T, kw_only=T, frozen=F)
|
|
|
|
|
class C2:
|
|
|
|
|
l1: list[dict[str, int]] | N
|
|
|
|
|
|
|
|
|
|
def ii(_, l2: list[dict[str, int]] | N):
|
|
|
|
|
return (_.l1, l2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@tester.add()
|
|
|
|
|
def parse():
|
|
|
|
|
res = ParseObj(C2).parse(
|
|
|
|
|
['--l1', '{"1":1,"2":2}', '--l1', '{"3":3,"4":4}', 'ii', '--l2', '{"5":5,"6":6}', '--l2', '{"7":7,"8":8}']
|
|
|
|
|
)
|
|
|
|
|
Assert(res) == ([{'1': 1, '2': 2}, {'3': 3, '4': 4}], [{'5': 5, '6': 6}, {'7': 7, '8': 8}])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dantClass()
|
|
|
|
|
class DantCli:
|
|
|
|
|
b: int
|
|
|
|
|
|
|
|
|
|
@dantCall
|
|
|
|
|
def a(_, a: int) -> tuple[int, int]:
|
|
|
|
|
return (_.b, a)
|
|
|
|
|
|
|
|
|
|
|
2024-09-11 11:14:03 -04:00
|
|
|
log.info(tester.run())
|
|
|
|
|
tester.exitWithStatus()
|