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_linking_deep_targets_mapping(self): class D: pass class A: def __init__(self, d: D) -> None: self.d = d class BSuper: pass class BSub(BSuper): def __init__(self, a_map: Mapping[str, A]) -> None: self.a_map = a_map class C: def fn(self) -> D: return D() with mock_module(D, A, BSuper, BSub, C) as module: config = { "b": { "class_path": f"{module}.BSub", "init_args": { "a_map": { "name": { "class_path": f"{module}.A", }, }, }, }, "c": {}, } config_path = os.path.join(self.tmpdir, 'config.yaml') with open(config_path, 'w') as f: yaml.safe_dump(config, f) parser = ArgumentParser() parser.add_argument("--config", action=ActionConfigFile) parser.add_subclass_arguments(BSuper, nested_key="b", required=True) parser.add_class_arguments(C, nested_key="c") parser.link_arguments("c", "b.init_args.a_map.name.init_args.d", compute_fn=C.fn, apply_on="instantiate") config = parser.parse_args(["--config", config_path]) config_init = parser.instantiate_classes(config) self.assertIsInstance(config_init["b"].a_map["name"].d, D) config_init = parser.instantiate_classes(config) self.assertIsInstance(config_init["b"].a_map["name"].d, D)
def test_enable_path(self): data = {'a': 1, 'b': 2, 'c': [3, 4]} cal = {'class_path': 'calendar.Calendar'} with open('data.yaml', 'w') as f: json.dump(data, f) with open('cal.yaml', 'w') as f: json.dump(cal, f) parser = ArgumentParser(error_handler=None) parser.add_argument('--data', type=Dict[str, Any], enable_path=True) parser.add_argument('--cal', type=Calendar, enable_path=True) cfg = parser.parse_args(['--data=data.yaml']) self.assertEqual('data.yaml', str(cfg['data'].pop('__path__'))) self.assertEqual(data, cfg['data']) cfg = parser.instantiate_classes(parser.parse_args(['--cal=cal.yaml'])) self.assertIsInstance(cfg['cal'], Calendar) self.assertRaises( ParserError, lambda: parser.parse_args(['--data=does-not-exist.yaml']))
def test_mapping_class_typehint(self): class A: pass class B: def __init__( self, class_map: Mapping[str, A], int_list: List[int], ): self.class_map = class_map self.int_list = int_list with mock_module(A, B) as module: parser = ArgumentParser(error_handler=None) parser.add_class_arguments(B, 'b') config = { 'b': { 'class_map': { 'one': { 'class_path': f'{module}.A' }, }, 'int_list': [1], }, } cfg = parser.parse_object(config) self.assertEqual(cfg.b.class_map, {'one': Namespace(class_path=f'{module}.A')}) self.assertEqual(cfg.b.int_list, [1]) cfg_init = parser.instantiate_classes(cfg) self.assertIsInstance(cfg_init.b, B) self.assertIsInstance(cfg_init.b.class_map, dict) self.assertIsInstance(cfg_init.b.class_map['one'], A) config['b']['int_list'] = config['b']['class_map'] self.assertRaises(ParserError, lambda: parser.parse_object(config))
def test_Callable_with_class_path(self): class MyFunc1: def __init__(self, p1: int = 1): self.p1 = p1 def __call__(self): return self.p1 class MyFunc2(MyFunc1): pass parser = ArgumentParser(error_handler=None) parser.add_argument('--callable', type=Callable) with mock_module(MyFunc1, MyFunc2) as module: value = {'class_path': f'{module}.MyFunc2', 'init_args': {'p1': 1}} cfg = parser.parse_args([f'--callable={module}.MyFunc2']) self.assertEqual(cfg.callable.as_dict(), value) value = {'class_path': f'{module}.MyFunc1', 'init_args': {'p1': 2}} cfg = parser.parse_args([f'--callable={json.dumps(value)}']) self.assertEqual(cfg.callable.as_dict(), value) self.assertEqual( yaml.safe_load(parser.dump(cfg))['callable'], value) cfg_init = parser.instantiate_classes(cfg) self.assertIsInstance(cfg_init.callable, MyFunc1) self.assertEqual(cfg_init.callable(), 2) self.assertRaises(ParserError, lambda: parser.parse_args(['--callable={}'])) self.assertRaises( ParserError, lambda: parser.parse_args( ['--callable=jsonargparse.SUPPRESS'])) self.assertRaises( ParserError, lambda: parser.parse_args(['--callable=calendar.Calendar'])) value = {'class_path': f'{module}.MyFunc1', 'key': 'val'} self.assertRaises( ParserError, lambda: parser.parse_args([f'--callable={json.dumps(value)}']))
def test_class_type(self): parser = ArgumentParser(error_handler=None) parser.add_argument('--op', type=Optional[List[Calendar]]) class_path = '"class_path": "calendar.Calendar"' expected = [{ 'class_path': 'calendar.Calendar', 'init_args': { 'firstweekday': 0 } }] cfg = parser.parse_args(['--op=[{' + class_path + '}]']) self.assertEqual(cfg.as_dict()['op'], expected) cfg = parser.parse_args(['--op=["calendar.Calendar"]']) self.assertEqual(cfg.as_dict()['op'], expected) cfg = parser.instantiate_classes(cfg) self.assertIsInstance(cfg['op'][0], Calendar) with self.assertRaises(ParserError): parser.parse_args( ['--op=[{"class_path": "jsonargparse.ArgumentParser"}]']) with self.assertRaises(ParserError): parser.parse_args( ['--op=[{"class_path": "jsonargparse.NotExist"}]']) with self.assertRaises(ParserError): parser.parse_args( ['--op=[{"class_path": "jsonargparse0.IncorrectModule"}]']) with self.assertRaises(ParserError): parser.parse_args(['--op=[1]']) init_args = '"init_args": {"bad_arg": True}' with self.assertRaises(ParserError): parser.parse_args( ['--op=[{' + class_path + ', ' + init_args + '}]']) init_args = '"init_args": {"firstweekday": 3}' cfg = parser.parse_args( ['--op=[{' + class_path + ', ' + init_args + '}]']) self.assertEqual(cfg['op'][0]['init_args'].as_dict(), {'firstweekday': 3}) cfg = parser.instantiate_classes(cfg) self.assertIsInstance(cfg['op'][0], Calendar) self.assertEqual(3, cfg['op'][0].firstweekday) parser = ArgumentParser(error_handler=None) parser.add_argument('--n.op', type=Optional[Calendar]) cfg = parser.parse_args( ['--n.op={' + class_path + ', ' + init_args + '}']) cfg = parser.instantiate_classes(cfg) self.assertIsInstance(cfg['n']['op'], Calendar) self.assertEqual(3, cfg['n']['op'].firstweekday) parser = ArgumentParser() parser.add_argument('--op', type=Calendar) cfg = parser.parse_args( ['--op={' + class_path + ', ' + init_args + '}']) cfg = parser.instantiate_classes(cfg) self.assertIsInstance(cfg['op'], Calendar) self.assertEqual(3, cfg['op'].firstweekday) cfg = parser.instantiate_classes(parser.parse_args([])) self.assertIsNone(cfg['op'])