def test_from_method_in_memory_return_complex(self) -> None: """ Tests that `parse.function` produces properly from a function in memory of current interpreter with: - complex return type - kwonly args """ method_complex_args_variety_with_imports_str = ( "from sys import stdout\n" "from {package} import Literal\n" "{body}".format( package="typing" if PY_GTE_3_8 else "typing_extensions", body=function_adder_str, )) add_6_5 = getattr( inspectable_compile(method_complex_args_variety_with_imports_str), "add_6_5", ) ir = parse.function(add_6_5) del ir["_internal"] # Not needed for this test self.assertDictEqual( ir, function_adder_ir, )
def test_to_function_with_inline_types(self) -> None: """ Tests that `function` can generate a function_def with inline types """ function_def = deepcopy( next( filter( rpartial(isinstance, FunctionDef), class_with_method_types_ast.body ) ) ) function_name = function_def.name function_type = get_function_type(function_def) gen_ast = emit.function( intermediate_repr=parse.function( function_def=function_def, function_name=function_name, function_type=function_type, ), function_name=function_name, function_type=function_type, emit_default_doc=False, inline_types=True, emit_separating_tab=True, indent_level=1, emit_as_kwonlyargs=False, ) # emit.file(gen_ast, os.path.join(os.path.dirname(__file__), 'delme.py'), mode='wt') run_ast_test( self, gen_ast=gen_ast, gold=function_def, )
def test_from_function_kw_only(self) -> None: """ Tests that parse.function produces properly from function with only keyword arguments """ gen_ir = parse.function(function_adder_ast, function_type="static") del gen_ir["_internal"] # Not needed for this test self.assertDictEqual( gen_ir, function_adder_ir, )
def test_from_method_complex_args_variety(self) -> None: """ Tests that `parse.function` produces correctly with: - kw only args; - default args; - annotations - required; - unannotated; - splat """ gen_ir = parse.function(method_complex_args_variety_ast) del gen_ir["_internal"] # Not needed for this test self.assertDictEqual( gen_ir, method_complex_args_variety_ir, )
def test_from_function_in_memory(self) -> None: """ Tests that parse.function produces properly from a function in memory of current interpreter """ def foo(a=5, b=6): """ the foo function :param a: the a value :param b: the b value """ self.assertIsNone(foo(5, 6)) ir = parse.function(foo) del ir["_internal"] # Not needed for this test self.assertDictEqual( ir, { "doc": "the foo function", "name": "TestParsers.test_from_function_in_memory.<locals>.foo", "params": params_to_ordered_dict(( { "default": 5, "doc": "the a value", "name": "a", "typ": "int" }, { "default": 6, "doc": "the b value", "name": "b", "typ": "int" }, )), "returns": None, "type": "static", }, )
def test_from_method_in_memory(self) -> None: """ Tests that `parse.function` produces properly from a function in memory of current interpreter with: - kw only args; - default args; - annotations - required; - unannotated; - splat """ method_complex_args_variety_with_imports_str = ( "from sys import stdout\n" "from {package} import Literal\n" "{body}".format( package="typing" if PY_GTE_3_8 else "typing_extensions", body=method_complex_args_variety_str, )) call_cliff = getattr( inspectable_compile(method_complex_args_variety_with_imports_str), "call_cliff", ) ir = parse.function(call_cliff) del ir["_internal"] # Not needed for this test # This is a hack because JetBrains wraps stdout self.assertIn( type(ir["params"]["writer"]["default"]).__name__, frozenset(("FlushingStringIO", "TextIOWrapper")), ) # This extra typ is copied, for now. TODO: Update AST-level parser to set types when defaults are given. ir["params"]["writer"].update({ "default": "stdout", "typ": method_complex_args_variety_ir["params"]["writer"]["typ"], }) self.assertDictEqual( ir, method_complex_args_variety_ir, )
def test_from_function_google_tf_squared_hinge_str_to_class(self) -> None: """ Tests that `emit.function` produces correctly with: - __call__ """ gen_ast = emit.class_( parse.function( ast.parse(function_google_tf_squared_hinge_str).body[0], infer_type=True, ), class_name="SquaredHingeConfig", emit_call=True, emit_default_doc=True, ) run_ast_test( self, gen_ast=gen_ast, gold=class_squared_hinge_config_ast, )
def test_from_function(self) -> None: """ Tests that parse.function produces properly """ gen_ir = parse.function(function_default_complex_default_arg_ast) gold_ir = { "name": "call_peril", "params": OrderedDict(( ( "dataset_name", { "default": "mnist", "typ": "str" }, ), ( "writer", { "default": "```{}```".format( paren_wrap_code( get_value( function_default_complex_default_arg_ast. args.defaults[1]))), }, ), )), "returns": None, "type": "static", } del gen_ir["_internal"] # Not needed for this test self.assertDictEqual( gen_ir, gold_ir, )
def test_to_function_with_docstring_types(self) -> None: """ Tests that `function` can generate a function_def with types in docstring """ # Sanity check run_ast_test( self, class_with_method_ast, gold=ast.parse(class_with_method_str).body[0], ) function_def = deepcopy( next(filter(rpartial(isinstance, FunctionDef), class_with_method_ast.body)) ) # Reindent docstring function_def.body[0].value.value = "\n{tab}{docstring}\n{tab}".format( tab=tab, docstring=reindent(ast.get_docstring(function_def)) ) ir = parse.function(function_def) gen_ast = emit.function( ir, function_name=function_def.name, function_type=get_function_type(function_def), emit_default_doc=False, inline_types=False, indent_level=1, emit_separating_tab=True, emit_as_kwonlyargs=False, ) gen_ast.body[0].value.value = "\n{tab}{docstring}\n{tab}".format( tab=tab, docstring=reindent(ast.get_docstring(gen_ast)) ) run_ast_test( self, gen_ast=gen_ast, gold=function_def, )
def test_from_class_with_body_in_method_to_method_with_body(self) -> None: """ Tests if this can make the roundtrip from a full function to a full function """ annotate_ancestry(class_with_method_and_body_types_ast) function_def = next( filter( rpartial(isinstance, FunctionDef), class_with_method_and_body_types_ast.body, ) ) # Reindent docstring function_def.body[0].value.value = "\n{tab}{docstring}\n{tab}".format( tab=tab, docstring=reindent(ast.get_docstring(function_def)) ) ir = parse.function( find_in_ast( "C.function_name".split("."), class_with_method_and_body_types_ast, ), ) gen_ast = emit.function( ir, emit_default_doc=False, function_name="function_name", function_type="self", indent_level=1, emit_separating_tab=True, emit_as_kwonlyargs=False, ) # emit.file(gen_ast, os.path.join(os.path.dirname(__file__), "delme.py"), mode="wt") run_ast_test( self, gen_ast=gen_ast, gold=function_def, )
def populate_files(tempdir, input_module_str=None): """ Populate files in the tempdir :param tempdir: Temporary directory :type tempdir: ```str``` :param input_module_str: Input string to write to the input_filename. If None, uses preset mock module. :type input_module_str: ```Optional[str]``` :return: input filename, input str, expected_output :rtype: ```Tuple[str, str, str, Module]``` """ input_filename = os.path.join(tempdir, "input.py") input_class_name = "Foo" input_class_ast = emit.class_( parse.function(deepcopy(method_adder_ast)), emit_call=False, class_name=input_class_name, ) input_module_ast = Module( body=[ input_class_ast, Assign( targets=[Name("input_map", Store())], value=Dict( keys=[set_value(input_class_name)], values=[Name(input_class_name, Load())], expr=None, ), expr=None, lineno=None, **maybe_type_comment ), Assign( targets=[Name("__all__", Store())], value=List( ctx=Load(), elts=[set_value(input_class_name), set_value("input_map")], expr=None, ), expr=None, lineno=None, **maybe_type_comment ), ], type_ignores=[], stmt=None, ) input_module_str = input_module_str or to_code(input_module_ast) # expected_output_class_str = ( # "class FooConfig(object):\n" # ' """\n' # " The amazing Foo\n\n" # " :cvar a: An a. Defaults to 5\n" # ' :cvar b: A b. Defaults to 16"""\n' # " a = 5\n" # " b = 16\n\n" # " def __call__(self):\n" # " self.a = 5\n" # " self.b = 16\n" # ) expected_class_ast = emit.class_( parse.function(deepcopy(method_adder_ast)), emit_call=True, class_name="{input_class_name}Config".format(input_class_name=input_class_name), ) with open(input_filename, "wt") as f: f.write(input_module_str) return input_filename, input_module_ast, input_class_ast, expected_class_ast