def get_parameter_default_annotations(func, keep_instance_ref=False): """ Get all the parameter names, default values, and types from the signature :param func: function to extract parameter from :param keep_instance_ref: boolean indication if self, cls should be kept as parameter :return A dictionary with the parameter names as key and a ParameterInfo instance as value """ params = getargspec(func) result = OrderedDict() if not params.args: return result if not keep_instance_ref and ismethod(func): params.args.pop(0) defaults = params.defaults or [] nb_defaults = len(defaults) # Trick to ensure that params.args[:-nb_defaults] returns the full array when # there is no default values if nb_defaults == 0: nb_defaults = -len(params.args) for name in params.args[:-nb_defaults]: result[name] = ParameterInfo(name, required=True) for name, default in zip(params.args[-nb_defaults:], defaults): result[name] = ParameterInfo(name, default=default) # Gettattr has to be used because of the compability with 2.7 for name, type_ in getattr(params, "annotations", {}).items(): result[name].type = str(type_.__name__) return result
def test_get_parameter_info_should_return_combine_information_from_signature_and_docstring( ): def func(a, bool_flag=False): """ :param a: :type a: str :param bool_flag: :type bool_flag: bool :return: """ pass result = get_parameter_infos(func) assert result["a"] == ParameterInfo("a", "str", required=True) assert result["bool_flag"] == ParameterInfo("bool_flag", "bool", default=False)
def test_get_parameters_single_param_str_annotation_str_default(): def func(a: str = "ab"): pass parameter_infos = get_parameter_default_annotations(func) assert parameter_infos["a"] == ParameterInfo("a", type_="str", default="ab", required=False)
def test_get_parameters_single_param_str_default(): def func(a="ab"): pass parameter_infos = get_parameter_default_annotations(func) assert list(parameter_infos.keys()) == ["a"] assert parameter_infos["a"] == ParameterInfo("a", default="ab", required=False)
def test_get_parameters_single_param_no_default(): def func(a): pass parameter_infos = get_parameter_default_annotations(func) assert list(parameter_infos.keys()) == ["a"] assert parameter_infos["a"] == ParameterInfo("a", default=NoDefault, required=True)
def test_get_parameters_multiple_params_defaults(): def func(a, a_b=12.5, T_test_param="abcd", underscore_=123): pass parameter_infos = get_parameter_default_annotations(func) assert list( parameter_infos.keys()) == ["a", "a_b", "T_test_param", "underscore_"] assert parameter_infos["a"] == ParameterInfo("a", default=NoDefault, required=True) assert parameter_infos["a_b"] == ParameterInfo("a_b", default=12.5, required=False) assert parameter_infos["T_test_param"] == ParameterInfo("T_test_param", default="abcd", required=False) assert parameter_infos["underscore_"] == ParameterInfo("underscore_", default=123, required=False)
def test_get_parameters_multiple_params_no_default(): def func(a, a_b, T_test_param, underscore_): pass parameter_infos = get_parameter_default_annotations(func) assert list( parameter_infos.keys()) == ["a", "a_b", "T_test_param", "underscore_"] assert parameter_infos["a"] == ParameterInfo("a", default=NoDefault, required=True) assert parameter_infos["a_b"] == ParameterInfo("a_b", default=NoDefault, required=True) assert parameter_infos["T_test_param"] == ParameterInfo("T_test_param", default=NoDefault, required=True) assert parameter_infos["underscore_"] == ParameterInfo("underscore_", default=NoDefault, required=True)
def parse(self, docstring): """ Parse the docstring :param docstring: docstring to parse :return: Dictionary of ParameterInfo with the name as key """ lines = [line for line in docstring.split("\n") if line.strip() != ""] result = OrderedDict() length = len(lines) index = 0 while index < length: match = self._regex.match(lines[index]) if match is None: index += 1 continue name = match.group(self.NAME) text = match.group(self.DESCRIPTION) type_info = match.group(self.TYPE_INFO) index, additional_text = self._get_info_text(lines, index, length) text += additional_text if type_info == self.TYPE_INFO_DESCRIPTION: if name not in result: result[name] = ParameterInfo(name) result[name].description = text if type_info == self.TYPE_INFO_TYPE: if name not in result: result[name] = ParameterInfo(name) result[name].type = text return result
def test_get_parameters_multiple_params_no_default_method(): class TmpClass: def tmp(self, a, a_b, T_test_param, underscore_): pass inst = TmpClass() func = inst.tmp parameter_infos = get_parameter_default_annotations(func) assert list( parameter_infos.keys()) == ["a", "a_b", "T_test_param", "underscore_"] assert parameter_infos["a"] == ParameterInfo("a", default=NoDefault, required=True) assert parameter_infos["a_b"] == ParameterInfo("a_b", default=NoDefault, required=True) assert parameter_infos["T_test_param"] == ParameterInfo("T_test_param", default=NoDefault, required=True) assert parameter_infos["underscore_"] == ParameterInfo("underscore_", default=NoDefault, required=True)