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
Exemple #4
0
    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()
Exemple #5
0
    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()
Exemple #6
0
    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()
Exemple #7
0
    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'