def _infer_default(_param, infer_type): """ Internal function to infer the default. Not intended for use by more than [the current] one function. :param _param: dict with keys: 'typ', 'doc', 'default' :type _param: ```dict``` :param infer_type: Whether to try inferring the typ (from the default) :type infer_type: ```bool``` """ if isinstance(_param["default"], (ast.Str, ast.Num, ast.Constant, ast.NameConstant)): _param["default"] = get_value(_param["default"]) if _param.get("default", False) in (None, "None"): _param["default"] = NoneStr if (infer_type and _param.get("typ") is None and _param["default"] not in (None, "None", NoneStr)): _param["typ"] = type(_param["default"]).__name__ if needs_quoting(_param.get("typ")) or isinstance(_param["default"], str): _param["default"] = unquote(_param["default"]) elif isinstance(_param["default"], AST): _param["default"] = "```{default}```".format( default=paren_wrap_code(to_code(_param["default"]).rstrip("\n"))) if _param.get("typ") is None and _param["default"]: _param["typ"] = type(_param["default"]).__name__ if (isinstance(_param["default"], str) and _param["default"].startswith("```") and _param["default"].endswith("```") and "[" not in _param[ "typ"] # Skip if you've actually formed a proper type ): del _param["typ"] # Could make it `object` I supposeā¦
def _parse_default_from_ast(action, default, required, typ): """ Internal function to acquire (action, default, required, typ) from AST types :param action: Name of the action :type action: ```Optional[str]``` :param default: Initial default value :type default: ```ast.AST``` :param required: Whether to require the argument :type required: ```bool``` :param typ: The type of the argument :type typ: ```Optional[str]``` :return: action, default, required, typ :rtype: ```Tuple[Optional[str], Optional[List[str]], bool, Optional[str]]``` """ if isinstance(default, (Constant, Expr, Str, Num)): default = get_value(default) # if type(default).__name__ in simple_types: # typ, default = type(default).__name__, default # else: if isinstance(default, (ast.Dict, ast.Tuple)): typ, default = "loads", _to_code(default).rstrip("\n") elif isinstance(default, (ast.List, ast.Tuple)): if len(default.elts) == 0: action, default, required, typ = "append", None, False, None elif len(default.elts) == 1: action, default = "append", get_value(default.elts[0]) typ = type(default).__name__ # else: # typ, default = "loads", _to_code(default).rstrip("\n") elif default is not None: typ, default = None, "```{default}```".format( default=paren_wrap_code(_to_code(default).rstrip("\n")) ) # if required is None: # required = "Optional" in ( # typ or iter(()) # ) # TODO: Work for `Union[None, AnyStr]` and `Any` return action, default, required, typ
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. del ir["params"]["writer"]["typ"] ir["params"]["writer"]["default"] = "```{}```".format( paren_wrap_code("stdout")) self.assertDictEqual( ir, method_complex_args_variety_ir, )
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 _infer_default(_param, infer_type): """ Internal function to infer the default. Not intended for use by more than [the current] one function. :param _param: dict with keys: 'typ', 'doc', 'default' :type _param: ```dict``` :param infer_type: Whether to try inferring the typ (from the default) :type infer_type: ```bool``` """ if isinstance(_param["default"], (ast.Str, ast.Num, ast.Constant, ast.NameConstant)): _param["default"] = get_value(_param["default"]) if _param.get("default", False) in none_types: _param["default"] = NoneStr if infer_type and _param.get( "typ") is None and _param["default"] not in none_types: _param["typ"] = type(_param["default"]).__name__ if needs_quoting(_param.get("typ")) or isinstance(_param["default"], str): _param["default"] = unquote(_param["default"]) elif isinstance(_param["default"], AST): try: _param["default"] = ast.literal_eval(_param["default"]) # if _param.get("typ") is None or _param["typ"] == "UnaryOp": # _param["typ"] = type(_param["default"]).__name__ except ValueError: _param["default"] = "```{default}```".format( default=paren_wrap_code( to_code(_param["default"]).rstrip("\n"))) if _param.get("typ") is None and _param["default"] != NoneStr: _param["typ"] = type(_param["default"]).__name__ if (_param["default"] != NoneStr and code_quoted(_param["default"]) and "[" not in _param.get("typ", iter( ())) # Skip if you've actually formed a proper type ): del _param["typ"] # Could make it `object` I supposeā¦
"`tf`.", "typ": "Literal['np', 'tf']", }, ), ( "tfds_dir", { "default": "~/tensorflow_datasets", "doc": "directory to look for models in.", "typ": "str", }, ), ( "writer", { "default": "```{}```".format(paren_wrap_code("stdout")), "doc": "IO object to write out to", }, ), ( "kwargs", { "doc": "additional keyword arguments", "typ": "Optional[dict]", "default": NoneStr, }, ), )), "returns": OrderedDict((( "return_type",