def test_get_type_from_module_locate(self) -> None: result = get_type_from_module('int', THIS) assert result.type == int assert result.method == 'locate' result = get_type_from_module('float', THIS) assert result.type == float assert result.method == 'locate'
def get_return_type(self, doc: str, module_type: ModuleType) -> Type: """Finds the return-type as string and returns it. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: If unable to parse the return type line. Returns: Type: The return type parsed from the docs. """ try: if 'Returns:' not in doc: return type(None) _, returns = doc.split("Returns:") try: doctype, _ = returns.strip().split(":") except ValueError: raise ParseException(returns) return get_type_from_module(doctype, module_type).type except Exception: raise ParseException()
def get_parameters(self, doc: str, module_type: ModuleType) -> List[Parameter]: """Finds the function arguments as strings, and returns their types as Parameter instances. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: If unable to parse an argument-line. Returns: List[Parameter]: The parameters parsed from the docstring. """ if 'Args:' not in doc: return [] _, tail = doc.split("Args:") if 'Returns:' in tail: arguments_string, _ = tail.split('Returns:') else: arguments_string = tail if 'Raises:' in arguments_string: arguments_string, _ = tail.split('Raises:') # TODO: Improve this. We might encounter more newlines. # Google styleguide appears to suggest using tab-indents for separating arguments # Could perhaps regex for NAME (TYPE): DESCRIPTION args_strings = [ arg.strip() for arg in arguments_string.strip().split("\n") ] parameters = [] for arg_string in args_strings: try: docname, tail = [ x.strip() for x in arg_string.split('(', maxsplit=1) ] doctype, tail = tail.split(':') doctype = doctype.replace(')', '') doctype = doctype.replace( ', optional', '' ) # TODO: How do we deal with Optional[int] being (Optional[int], optional)? located_type = get_type_from_module(doctype, module_type) parameters.append(Parameter(docname, located_type.type)) except ValueError: raise ParseException(arg_string) except Exception: raise ParseException(arg_string) return parameters
def get_return_type(self, doc: str, module_type: ModuleType) -> Type: """Base method for Parsers to return the return-type of a function from its docstring. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: Raised if an exception occurs during parsing Returns: Type: The return type parsed from the docs. """ # TODO: Use section split regex so we know 'Returns' is not just a random word in docstring, but actually a section header if 'Returns' not in doc: return type(None) try: splits = self.section_regex.split(doc) parameters_idx = splits.index('Returns') if parameters_idx == -1 or len(splits) < parameters_idx + 1: raise ParseException() returns_section = splits[parameters_idx + 1] returns_line = returns_section.split('\n')[0] # Test for line with name/type combo if ':' in returns_line: match = self.returns_with_name_regex.match(returns_line) if match is not None: name, doctype = match.groups() else: raise ParseException() else: doctype = returns_line.rstrip('\n') return get_type_from_module(doctype, module_type).type except Exception: raise ParseException()
def get_parameters(self, doc: str, module_type: ModuleType) -> List[Parameter]: """Finds the function arguments as strings, and returns their types as Parameter instances. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: Raised if any error happens during parsing. Returns: List[Parameter]: The parameters parsed from the docstring. """ try: lines = doc.split('\n') parameters: List[Parameter] = [] var_name: Optional[str] = None for line in lines: if var_name is None: match = self.parameter_name_regex.match(line) if match is not None: var_name = match.groups()[0] else: match = self.parameter_type_regex.match(line) if match is not None: var_type = match.groups()[0] located_type = get_type_from_module( var_type, module_type) parameters.append( Parameter(var_name, located_type.type)) var_name = None if var_name is not None: # There must have been an error parsing :type: raise ParseException() return parameters except Exception: raise ParseException()
def get_return_type(self, doc: str, module_type: ModuleType) -> Type: """Base method for Parsers to return the return-type of a function from its docstring. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: Raised if an exception occurs during parsing Returns: Type: The return type parsed from the docs. """ try: for line in doc.split('\n'): match = self.return_type_regex.match(line) if match is None: continue doctype = match.groups()[0] return get_type_from_module(doctype, module_type).type return type(None) except Exception: raise ParseException()
def get_parameters(self, doc: str, module_type: ModuleType) -> List[Parameter]: """Finds the function arguments as strings, and returns their types as Parameter instances. Args: doc (str): Function docstring. module_type (ModuleType): The module the docstring was extracted from. Raises: ParseException: Raised if any error happens during parsing. Returns: List[Parameter]: The parameters parsed from the docstring. """ if 'Parameters' not in doc: return [] try: splits = self.section_regex.split(doc) parameters_idx = splits.index('Parameters') if parameters_idx == -1 or len(splits) < parameters_idx + 1: raise ParseException() parameters_section = splits[parameters_idx + 1] matches = self.parameter_regex.findall(parameters_section) # If we have a parameters section with text, but no matches, we must have bad formatting if len(parameters_section) > 0 and len(matches) == 0: raise ParseException() parameters: List[Parameter] = [] for param_name, param_type in matches: located_type = get_type_from_module(param_type, module_type) parameters.append(Parameter(param_name, located_type.type)) return parameters except Exception: raise ParseException()
def test_get_type_from_module_bfs(self) -> None: # Parser is not found in this module, but it is imported by Configuration which we do import. result = get_type_from_module('Parser', THIS) assert result.type == pydoctest.parsers.parser.Parser assert result.method == 'deque'
def test_get_type_from_module_eval(self) -> None: result = get_type_from_module('DataObject', THIS) assert result.type == DataObject assert result.method == 'eval'