def test_nargs_questionmark(self): parser = ArgumentParser(error_handler=None) parser.add_argument('p1') parser.add_argument('p2', nargs='?', type=OpenUnitInterval) self.assertIsNone(parser.parse_args(['a']).p2) self.assertEqual(0.5, parser.parse_args(['a', '0.5']).p2) self.assertRaises(ParserError, lambda: parser.parse_args(['a', 'b']))
def test_list_path(self): parser = ArgumentParser() parser.add_argument('--paths', type=List[Path_fc]) cfg = parser.parse_args(['--paths=["file1", "file2"]']) self.assertEqual(['file1', 'file2'], cfg.paths) self.assertIsInstance(cfg.paths[0], Path) self.assertIsInstance(cfg.paths[1], Path)
def test_class_type_subclass_given_by_name_issue_84(self): class LocalCalendar(Calendar): pass parser = ArgumentParser() parser.add_argument('--op', type=Union[Calendar, GzipFile, None]) cfg = parser.parse_args(['--op=TextCalendar']) self.assertEqual(cfg.op.class_path, 'calendar.TextCalendar') out = StringIO() parser.print_help(out) for class_path in [ 'calendar.Calendar', 'calendar.TextCalendar', 'gzip.GzipFile' ]: self.assertIn(class_path, out.getvalue()) self.assertNotIn('LocalCalendar', out.getvalue()) class HTMLCalendar(Calendar): pass with mock_module(HTMLCalendar) as module: err = StringIO() with redirect_stderr(err), self.assertRaises(SystemExit): parser.parse_args(['--op.help=HTMLCalendar']) self.assertIn('Give the full class path to avoid ambiguity', err.getvalue()) self.assertIn(f'{module}.HTMLCalendar', err.getvalue())
def test_class_type_with_default_config_files(self): config = { 'class_path': 'calendar.Calendar', 'init_args': { 'firstweekday': 3 }, } config_path = os.path.join(self.tmpdir, 'config.yaml') with open(config_path, 'w') as f: json.dump({'data': {'cal': config}}, f) class MyClass: def __init__(self, cal: Optional[Calendar] = None, val: int = 2): self.cal = cal parser = ArgumentParser(error_handler=None, default_config_files=[config_path]) parser.add_argument('--op', default='from default') parser.add_class_arguments(MyClass, 'data') cfg = parser.get_defaults() self.assertEqual(config_path, str(cfg['__default_config__'])) self.assertEqual(cfg.data.cal.as_dict(), config) dump = parser.dump(cfg) self.assertIn('class_path: calendar.Calendar\n', dump) self.assertIn('firstweekday: 3\n', dump) cfg = parser.parse_args([]) self.assertEqual(cfg.data.cal.as_dict(), config) cfg = parser.parse_args(['--data.cal.class_path=calendar.Calendar'], defaults=False) self.assertEqual(cfg.data.cal, Namespace(class_path='calendar.Calendar'))
def _test_typehint_non_parameterized_types(self, type): parser = ArgumentParser(error_handler=None) ActionTypeHint.is_supported_typehint(type, full=True) parser.add_argument('--type', type=type) cfg = parser.parse_args(['--type=uuid.UUID']) self.assertEqual(cfg.type, uuid.UUID) self.assertEqual(parser.dump(cfg), 'type: uuid.UUID\n')
def test_dict_union(self): class MyEnum(Enum): ab = 1 parser = ArgumentParser(error_handler=None) parser.add_argument('--dict1', type=Dict[int, Optional[Union[float, MyEnum]]]) parser.add_argument('--dict2', type=Dict[str, Union[bool, Path_fc]]) cfg = parser.parse_args( ['--dict1={"2":4.5, "6":"ab"}', '--dict2={"a":true, "b":"f"}']) self.assertEqual({2: 4.5, 6: MyEnum.ab}, cfg['dict1']) self.assertEqual({'a': True, 'b': 'f'}, cfg['dict2']) self.assertIsInstance(cfg['dict2']['b'], Path) self.assertEqual({5: None}, parser.parse_args(['--dict1={"5":null}'])['dict1']) self.assertRaises(ParserError, lambda: parser.parse_args(['--dict1=["a", "b"]'])) cfg = yaml.safe_load(parser.dump(cfg)) self.assertEqual( { 'dict1': { '2': 4.5, '6': 'ab' }, 'dict2': { 'a': True, 'b': 'f' } }, cfg)
def test_class_path_override_with_default_config_files(self): class MyCalendar(Calendar): def __init__(self, *args, param: str = '0', **kwargs): super().__init__(*args, **kwargs) with mock_module(MyCalendar) as module: config = { 'class_path': f'{module}.MyCalendar', 'init_args': { 'firstweekday': 2, 'param': '1' }, } config_path = os.path.join(self.tmpdir, 'config.yaml') with open(config_path, 'w') as f: json.dump({'cal': config}, f) parser = ArgumentParser(error_handler=None, default_config_files=[config_path]) parser.add_argument('--cal', type=Optional[Calendar]) cfg = parser.instantiate_classes(parser.get_defaults()) self.assertIsInstance(cfg['cal'], MyCalendar) cfg = parser.parse_args([ '--cal={"class_path": "calendar.Calendar", "init_args": {"firstweekday": 3}}' ]) self.assertEqual(type(parser.instantiate_classes(cfg)['cal']), Calendar)
def test_enum(self): class MyEnum(Enum): A = 1 B = 2 C = 3 parser = ArgumentParser(error_handler=None) parser.add_argument('--enum', type=MyEnum, default=MyEnum.C, help='Description') for val in ['A', 'B', 'C']: self.assertEqual(MyEnum[val], parser.parse_args(['--enum=' + val]).enum) for val in ['X', 'b', 2]: self.assertRaises( ParserError, lambda: parser.parse_args(['--enum=' + str(val)])) cfg = parser.parse_args(['--enum=C'], with_meta=False) self.assertEqual('enum: C\n', parser.dump(cfg)) help_str = StringIO() parser.print_help(help_str) self.assertIn('Description (type: MyEnum, default: C)', help_str.getvalue())
def test_ActionParser_required(self): p1 = ArgumentParser() p1.add_argument('--op1', required=True) p2 = ArgumentParser(error_handler=None) p2.add_argument('--op2', action=ActionParser(parser=p1)) p2.parse_args(['--op2.op1=1']) self.assertRaises(ParserError, lambda: p2.parse_args([]))
def test_list(self): for list_type in [Iterable, List, Sequence]: with self.subTest(str(list_type)): parser = ArgumentParser() parser.add_argument('--list', type=list_type[int]) cfg = parser.parse_args(['--list=[1, 2]']) self.assertEqual([1, 2], cfg.list)
def test_subcommand_with_subclass_default_override_lightning_issue_10859( self): class Arch: def __init__(self, a: int = 1): pass class ArchB(Arch): def __init__(self, a: int = 2, b: int = 3): pass class ArchC(Arch): def __init__(self, a: int = 4, c: int = 5): pass parser = ArgumentParser(error_handler=None) parser_subcommands = parser.add_subcommands() subparser = ArgumentParser() subparser.add_argument('--arch', type=Arch) with mock_module(Arch, ArchB, ArchC) as module: default = {'class_path': f'{module}.ArchB'} value = { 'class_path': f'{module}.ArchC', 'init_args': { 'a': 10, 'c': 11 } } subparser.set_defaults(arch=default) parser_subcommands.add_subcommand('fit', subparser) cfg = parser.parse_args(['fit', f'--arch={json.dumps(value)}']) self.assertEqual(cfg.fit.arch.as_dict(), value)
def test_ActionJsonnet(self): parser = ArgumentParser(default_meta=False, error_handler=None) parser.add_argument('--input.ext_vars', action=ActionJsonnetExtVars()) parser.add_argument('--input.jsonnet', action=ActionJsonnet( ext_vars='input.ext_vars', schema=json.dumps(example_schema))) cfg2 = parser.parse_args([ '--input.ext_vars', '{"param": 123}', '--input.jsonnet', example_2_jsonnet ]) self.assertEqual(123, cfg2.input.jsonnet['param']) self.assertEqual(9, len(cfg2.input.jsonnet['records'])) self.assertEqual('#8', cfg2.input.jsonnet['records'][-2]['ref']) self.assertEqual(15.5, cfg2.input.jsonnet['records'][-2]['val']) cfg1 = parser.parse_args(['--input.jsonnet', example_1_jsonnet]) self.assertEqual(cfg1.input.jsonnet['records'], cfg2.input.jsonnet['records']) self.assertRaises( ParserError, lambda: parser.parse_args([ '--input.ext_vars', '{"param": "a"}', '--input.jsonnet', example_2_jsonnet ])) self.assertRaises( ParserError, lambda: parser.parse_args(['--input.jsonnet', example_2_jsonnet])) self.assertRaises(ValueError, lambda: ActionJsonnet(ext_vars=2)) self.assertRaises( ValueError, lambda: ActionJsonnet(schema='.' + json.dumps(example_schema)))
def get_parser_lv2(): parser_lv2 = ArgumentParser(description='parser_lv2 description') parser_lv2.add_argument('--a1', help='lv2_a1 help') group_lv2 = parser_lv2.add_argument_group( description='group_lv2 description') group_lv2.add_argument('--a2', help='lv2_a2 help') return parser_lv2
def test_ActionYesNo_parse_env(self): parser = example_parser() self.assertEqual( True, parser.parse_env({ 'APP_BOOLS__DEF_FALSE': 'true' }).bools.def_false) self.assertEqual( True, parser.parse_env({ 'APP_BOOLS__DEF_FALSE': 'yes' }).bools.def_false) self.assertEqual( False, parser.parse_env({ 'APP_BOOLS__DEF_TRUE': 'false' }).bools.def_true) self.assertEqual( False, parser.parse_env({ 'APP_BOOLS__DEF_TRUE': 'no' }).bools.def_true) parser = ArgumentParser(default_env=True, env_prefix='APP') parser.add_argument('--op', action=ActionYesNo, default=False) self.assertEqual(True, parser.parse_env({'APP_OP': 'true'}).op)
def test_class_type_subclass_nested_help(self): class Class: def __init__(self, cal: Calendar, p1: int = 0): self.cal = cal parser = ArgumentParser() parser.add_argument('--op', type=Class) for pattern in [r'[\s=]', r'\s']: with self.subTest('" "' if '=' in pattern else '"="'), mock_module( Class) as module: out = StringIO() args = re.split( pattern, f'--op.help={module}.Class --op.init_args.cal.help=TextCalendar' ) with redirect_stdout(out), self.assertRaises(SystemExit): parser.parse_args(args) self.assertIn('--op.init_args.cal.init_args.firstweekday', out.getvalue()) with self.subTest('invalid'), mock_module(Class) as module: err = StringIO() with redirect_stderr(err), self.assertRaises(SystemExit): parser.parse_args( [f'--op.help={module}.Class', '--op.init_args.p1=1']) self.assertIn('Expected a nested --*.help option', err.getvalue())
def test_bool(self): parser = ArgumentParser(prog='app', default_env=True, error_handler=None) parser.add_argument('--val', type=bool) self.assertEqual(None, parser.get_defaults().val) self.assertEqual(True, parser.parse_args(['--val', 'true']).val) self.assertEqual(True, parser.parse_args(['--val', 'TRUE']).val) self.assertEqual(False, parser.parse_args(['--val', 'false']).val) self.assertEqual(False, parser.parse_args(['--val', 'FALSE']).val) self.assertRaises(ParserError, lambda: parser.parse_args(['--val', '1'])) os.environ['APP_VAL'] = 'true' self.assertEqual(True, parser.parse_args([]).val) os.environ['APP_VAL'] = 'True' self.assertEqual(True, parser.parse_args([]).val) os.environ['APP_VAL'] = 'false' self.assertEqual(False, parser.parse_args([]).val) os.environ['APP_VAL'] = 'False' self.assertEqual(False, parser.parse_args([]).val) os.environ['APP_VAL'] = '2' self.assertRaises(ParserError, lambda: parser.parse_args(['--val', 'a'])) del os.environ['APP_VAL']
def get_parser(): """Returns the argument parser object for the command line tool.""" ## validate parser ## parser_validate = ModuleArchitecture.get_config_parser() parser_validate.description = 'Command for checking the validity of neural network module architecture files.' parser_validate.set_defaults(propagators='default') parser_validate.add_argument( 'jsonnet_paths', action=ActionPath(mode='fr'), nargs='+', help= 'Path(s) to neural network module architecture file(s) in jsonnet narchi format.' ) ## render parser ## parser_render = ModuleArchitectureRenderer.get_config_parser() parser_render.description = 'Command for rendering a neural network module architecture file.' parser_render.set_defaults(propagators='default') parser_render.add_argument( 'jsonnet_path', action=ActionPath(mode='fr'), help= 'Path to a neural network module architecture file in jsonnet narchi format.' ) parser_render.add_argument( 'out_file', nargs='?', action=ActionPath(mode='fc'), help= 'Path where to write the architecture diagram (with a valid extension for pygraphviz draw). If ' 'unset a pdf is saved to the output directory.') ## schema parser ## parser_schema = ArgumentParser( description='Prints a schema as a pretty json.') parser_schema.add_argument( 'schema', nargs='?', default='narchi', choices=[x for x in schemas.keys() if x is not None], help='Which of the available schemas to print.') ## global parser ## parser = ArgumentParser(description=__doc__, version=__version__) parser.add_argument( '--stack_trace', type=bool, default=False, help='Whether to print stack trace when there are errors.') parser.parser_validate = parser_validate parser.parser_render = parser_render parser.parser_schema = parser_schema subcommands = parser.add_subcommands() subcommands.add_subcommand('validate', parser_validate) subcommands.add_subcommand('render', parser_render) subcommands.add_subcommand('schema', parser_schema) return parser
def get_config_parser(): parser = ArgumentParser() parser.add_argument("--factor", type=int, default=2, help="Factor to multiply") return parser
def test_nested_mapping_without_args(self): parser = ArgumentParser() parser.add_argument('--map', type=Mapping[str, Union[int, Mapping]]) self.assertEqual(parser.parse_args(['--map={"a": 1}']).map, {"a": 1}) self.assertEqual( parser.parse_args(['--map={"b": {"c": 2}}']).map, {"b": { "c": 2 }})
def test_ActionParser_conflict(self): parser_lv2 = ArgumentParser() parser_lv2.add_argument('--op') parser = ArgumentParser(error_handler=None) parser.add_argument('--inner.op') self.assertRaises( ValueError, lambda: parser.add_argument('--inner', action=ActionParser(parser_lv2)))
def test_list_enum(self): class MyEnum(Enum): ab = 0 xy = 1 parser = ArgumentParser(error_handler=None) parser.add_argument('--list', type=List[MyEnum]) self.assertEqual([MyEnum.xy, MyEnum.ab], parser.parse_args(['--list=["xy", "ab"]']).list)
def test_nested_tuples(self): parser = ArgumentParser(error_handler=None) parser.add_argument('--tuple', type=Tuple[Tuple[str, str], Tuple[Tuple[int, float], Tuple[int, float]]]) cfg = parser.parse_args( ['--tuple=[["foo", "bar"], [[1, 2.02], [3, 3.09]]]']) self.assertEqual((('foo', 'bar'), ((1, 2.02), (3, 3.09))), cfg.tuple)
def test_no_str_strip(self): parser = ArgumentParser(error_handler=None) parser.add_argument('--op', type=Optional[str]) parser.add_argument('--cfg', action=ActionConfigFile) self.assertEqual(' ', parser.parse_args(['--op', ' ']).op) self.assertEqual('', parser.parse_args(['--op', '']).op) self.assertEqual(' abc ', parser.parse_args(['--op= abc ']).op) self.assertEqual(' ', parser.parse_args(['--cfg={"op":" "}']).op) self.assertIsNone(parser.parse_args(['--op=null']).op)
def _test_typehint_parameterized_types(self, type): parser = ArgumentParser(error_handler=None) ActionTypeHint.is_supported_typehint(type, full=True) parser.add_argument('--cal', type=type[Calendar]) cfg = parser.parse_args(['--cal=calendar.Calendar']) self.assertEqual(cfg.cal, Calendar) self.assertEqual(parser.dump(cfg), 'cal: calendar.Calendar\n') self.assertRaises(ParserError, lambda: parser.parse_args(['--cal=uuid.UUID']))
def test_ActionPath_skip_check(self): parser = ArgumentParser(error_handler=None) parser.add_argument('--file', action=ActionPath(mode='fr', skip_check=True)) cfg = parser.parse_args(['--file=not-exist']) self.assertIsInstance(cfg.file, Path) self.assertEqual(str(cfg.file), 'not-exist') self.assertEqual(parser.dump(cfg), 'file: not-exist\n') self.assertTrue(repr(cfg.file).startswith('Path_fr_skip_check'))
def get_parser(): parser = ArgumentParser() parser.add_argument('xml', action=ActionPath(mode='fr'), help='Page XML file to process.') parser.add_argument('--with_conf', type=bool, default=False, help='Whether to include confidences.') return parser
def test_ActionPath_dump(self): parser = ArgumentParser() parser.add_argument('--path', action=ActionPath(mode='fc')) cfg = parser.parse_string('path: path') self.assertEqual(parser.dump(cfg), 'path: path\n') parser = ArgumentParser() parser.add_argument('--paths', nargs='+', action=ActionPath(mode='fc')) cfg = parser.parse_args(['--paths', 'path1', 'path2']) self.assertEqual(parser.dump(cfg), 'paths:\n- path1\n- path2\n')
def get_config_parser(): parser = ArgumentParser() parser.add_argument( "--producer", action=ActionParser(parser=Producer.get_config_parser())) parser.add_argument( "--transformer", action=ActionParser(parser=Transformer.get_config_parser())) return parser
def test_optional_path(self): pathlib.Path('file_fr').touch() parser = ArgumentParser(error_handler=None) parser.add_argument('--path', type=Optional[Path_fr]) self.assertIsNone(parser.parse_args(['--path=null']).path) cfg = parser.parse_args(['--path=file_fr']) self.assertEqual('file_fr', cfg.path) self.assertIsInstance(cfg.path, Path) self.assertRaises(ParserError, lambda: parser.parse_args(['--path=not_exist']))
def test_invalid_init_args_in_yaml(self): config = """cal: class_path: calendar.Calendar init_args: """ parser = ArgumentParser(error_handler=None) parser.add_argument('--config', action=ActionConfigFile) parser.add_argument('--cal', type=Calendar) self.assertRaises(ParserError, lambda: parser.parse_args([f'--config={config}']))