def test_sync_properties(self) -> None: """Tests `sync_properties` with `call=False`""" with TemporaryDirectory() as tempdir: ( input_filename, input_str, output_filename, output_str, ) = populate_files(tempdir) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("Foo.g.f",), input_eval=False, output_filename=output_filename, output_params=("f.h",), ) ) self.run_sync_properties_test( input_filename, input_str, output_filename, ast.parse(output_str.replace("h: Literal['b']", "f: Literal['a']")), )
def test_sync_properties_output_param_wrap_subscript_eval0(self) -> None: """Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript""" with TemporaryDirectory() as tempdir: (input_filename, input_str, output_filename, output_str,) = populate_files( tempdir, input_str="a = tuple(range(5))", output_str="def j(k): pass" ) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("a",), input_eval=True, output_filename=output_filename, output_params=("j.k",), output_param_wrap=None, ) ) self.run_sync_properties_test( input_filename=input_filename, output_filename=output_filename, input_str=input_str, gold=ast.parse( output_str.replace("(k)", "(k: Literal[0, 1, 2, 3, 4])") ), )
def test_sync_properties_output_param_wrap_subscript(self) -> None: """Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript and !input_eval""" with TemporaryDirectory() as tempdir: (input_filename, input_str, output_filename, output_str,) = populate_files( tempdir, input_str="a = tuple(range(5))", output_str="def j(k):\n" "{tab}pass\n".format(tab=tab), ) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("a",), input_eval=False, output_filename=output_filename, output_params=("j.k",), output_param_wrap=None, ) ) with open(output_filename, "rt") as f: # Technically this produces an invalid AST, but we don't care… `input_eval is False` self.assertEqual( f.read().rstrip(), output_str.replace("(k)", "(a: tuple(range(5)))").rstrip(), )
def test_sync_properties_output_param_wrap_no_annotation(self) -> None: """Tests `sync_properties` with `output_param_wrap` set when type annotation isn't being replaced""" with TemporaryDirectory() as tempdir: (input_filename, input_str, output_filename, output_str,) = populate_files( tempdir, input_str=( "from {package} import Literal\n\n" "class Foo(object):\n" "{tab}def g(f):\n" "{tab}{tab}pass".format( package="typing" if PY_GTE_3_8 else "typing_extensions", tab=tab ) ), ) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("Foo.g.f",), input_eval=False, output_filename=output_filename, output_params=("f.h",), output_param_wrap="Optional[List[Union[{output_param}, str]]]", ) ) self.run_sync_properties_test( input_filename=input_filename, output_filename=output_filename, input_str=input_str, gold=ast.parse(output_str.replace("h: Literal['b']", "f")), )
def test_sync_properties_output_param_wrap(self) -> None: """Tests `sync_properties` with `output_param_wrap` set""" with TemporaryDirectory() as tempdir: ( input_filename, input_str, output_filename, output_str, ) = populate_files(tempdir) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("Foo.g.f",), input_eval=False, output_filename=output_filename, output_params=("f.h",), output_param_wrap="Optional[List[Union[{output_param}, str]]]", ) ) self.run_sync_properties_test( input_filename=input_filename, output_filename=output_filename, input_str=input_str, gold=ast.parse( output_str.replace( "h: Literal['b']", "f: Optional[List[Union[Literal['a'], str]]]" ) ), )
def test_sync_properties_eval(self) -> None: """Tests `sync_properties` with `call=True`""" with open( os.path.join( os.path.dirname( os.path.dirname( resource_filename( modules[__name__].__name__, "__init__{extsep}py".format(extsep=extsep), ) ) ), "tests", "mocks", "eval{extsep}py".format(extsep=extsep), ), "rt", ) as f: eval_mock_str = f.read() with TemporaryDirectory() as tempdir: ( input_filename, input_str, output_filename, output_str, ) = populate_files(tempdir, input_str=eval_mock_str) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("get_modules",), input_eval=True, output_filename=output_filename, output_params=("f.h",), ) ) self.run_sync_properties_test( input_filename=input_filename, output_filename=output_filename, input_str=eval_mock_str, gold=ast.parse( output_str.replace("h: Literal['b']", "h: Literal['mocks']") ), )
def test_sync_properties_output_param_wrap_fails(self) -> None: """Tests `sync_properties` fails with `output_param_wrap` set when replacement_node is unknown""" with TemporaryDirectory() as tempdir: ( input_filename, input_str, output_filename, output_str, ) = populate_files(tempdir, input_str="local = locals()") self.assertRaises( NotImplementedError, lambda: sync_properties( input_filename=input_filename, input_params=("local",), input_eval=False, output_filename=output_filename, output_params=("f.h",), output_param_wrap="Optional[List[Union[{output_param}, str]]]", ), )
def test_sync_properties_eval_fails(self) -> None: """Tests `sync_properties` fails with `call=True` and dots""" with TemporaryDirectory() as tempdir: input_filename = os.path.join( tempdir, "input_{extsep}py".format(extsep=extsep) ) output_filename = os.path.join( tempdir, "input_str{extsep}py".format(extsep=extsep) ) open(input_filename, "wt").close() open(output_filename, "wt").close() self.assertRaises( NotImplementedError, lambda: sync_properties( input_filename=input_filename, input_params=("foo.bar",), input_eval=True, output_filename=output_filename, output_params=("f.h",), ), )
def test_sync_properties_output_param_wrap_subscript_eval1(self) -> None: """Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript""" with TemporaryDirectory() as tempdir: (input_filename, input_str, output_filename, output_str,) = populate_files( tempdir, input_str="import pip\n" "c = { attr: getattr(pip, attr)" " for attr in dir(pip)" " if attr in frozenset(('__version__', '__name__')) }\n" "a = tuple(sorted(c.keys()))\n", output_str="class C(object):\n" "{tab}def j(k: str):\n" "{tab}{tab}pass\n".format(tab=tab), ) self.assertIsNone( sync_properties( input_filename=input_filename, input_params=("a",), input_eval=True, output_filename=output_filename, output_params=("C.j.k",), output_param_wrap=None, ) ) self.run_sync_properties_test( input_filename=input_filename, output_filename=output_filename, input_str=input_str, gold=ast.parse( output_str.replace( "(k: str)", "(k: Literal['__name__', '__version__'])" ) ), )
def main(cli_argv=None, return_args=False): """ Run the CLI parser :param cli_argv: CLI arguments. If None uses `sys.argv`. :type cli_argv: ```Optional[List[str]]``` :param return_args: Primarily use is for tests. Returns the args rather than executing anything. :type return_args: ```bool``` :returns: the args if `return_args`, else None :rtype: ```Optional[Namespace]``` """ _parser = _build_parser() args = _parser.parse_args(args=cli_argv) command = args.command args_dict = {k: v for k, v in vars(args).items() if k != "command"} if command == "sync": args = Namespace( **{ k: v if k == "truth" or isinstance(v, list) or v is None else [v] for k, v in args_dict.items() } ) truth_file = getattr(args, pluralise(args.truth)) require_file_existent( _parser, truth_file[0] if truth_file else truth_file, name="truth" ) truth_file = path.realpath(path.expanduser(truth_file[0])) number_of_files = sum( len(val) for key, val in vars(args).items() if isinstance(val, list) and not key.endswith("_names") ) if number_of_files < 2: _parser.error( "Two or more of `--argparse-function`, `--class`, and `--function` must" " be specified" ) require_file_existent(_parser, truth_file, name="truth") return args if return_args else ground_truth(args, truth_file) elif command == "sync_properties": deque( ( setattr( args, fname, path.realpath(path.expanduser(getattr(args, fname))) ) for fname in ("input_filename", "output_filename") if path.isfile(getattr(args, fname)) ), maxlen=0, ) for filename, arg_name in (args.input_filename, "input-file"), ( args.output_filename, "output-file", ): require_file_existent(_parser, filename, name=arg_name) sync_properties(**args_dict) elif command == "gen": if path.isfile(args.output_filename): raise IOError( "File exists and this is a destructive operation. Delete/move {output_filename!r} then" " rerun.".format(output_filename=args.output_filename) ) gen(**args_dict) elif command == "gen_routes": if args.route is None: args.route = "/api/{model_name}".format(model_name=args.model_name.lower()) ( lambda routes__primary_key: upsert_routes( app=args.app_name, route=args.route, routes=routes__primary_key[0], routes_path=getattr(args, "routes_path", None), primary_key=routes__primary_key[1], ) )( gen_routes( app=args.app_name, crud=args.crud, model_name=args.model_name, model_path=args.model_path, route=args.route, ) ) elif command == "openapi": openapi_bulk( app_name=args.app_name, model_paths=args.model_paths, routes_paths=args.routes_paths, ) elif command == "doctrans": require_file_existent(_parser, args.filename, name="filename") doctrans( filename=args.filename, docstring_format=args.format, type_annotations=args.type_annotations, ) elif command == "exmod": exmod( module=args.module, emit_name=args.emit, blacklist=args.blacklist, whitelist=args.whitelist, output_directory=args.output_directory, dry_run=args.dry_run, )