Exemplo n.º 1
0
    def test_missing_parameter_types(self):
        program = '\n'.join([
            'def function_with_excess_parameter(extra):',
            '    """We have an extra parameter below, extra.',
            '',
            '    Args:',
            '        extra: This shouldn\'t be here.',
            '',
            '    """',
            '    print(\'Hey!\')',
        ])
        tree = ast.parse(program)
        functions = get_function_descriptions(tree)

        checker = IntegrityChecker(config=Configuration(
            ignore=[],
            message_template=None,
            style=DocstringStyle.GOOGLE,
            strictness=Strictness.FULL_DESCRIPTION,
            enable=['DAR104']
        ))
        checker.run_checks(functions[0])
        errors = checker.errors
        self.assertEqual(len(errors), 1)
        self.assertTrue(isinstance(errors[0], ParameterTypeMissingError))
Exemplo n.º 2
0
 def assertHasErrors(self, config, docstring):
     checker = IntegrityChecker(config)
     checker.run_checks(self.get_function_with(docstring))
     errors = checker.errors
     self.assertTrue(
         len(errors) > 0
     )
Exemplo n.º 3
0
 def test_doesnt_require_private_arguments(self):
     program = '\n'.join([
         'def reduce(fn, l, _curr=None):',
         '    """Reduce the list with the given function.',
         '',
         '    Parameters',
         '    ----------',
         '    fn',
         '        A function which takes two items and produces',
         '        one as a result.',
         '    l',
         '        The list to reduce.',
         '',
         '    Returns',
         '    -------',
         '    The final, reduced result of the list.',
         '',
         '    """',
         '    if not l:',
         '        return _curr',
         '    if not _curr:',
         '        return reduce(fn, l[1:], l[0])',
         '    return reduce(fn, l[1:], fn(l[0], _curr))',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker(self.config)
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(
         len(errors),
         0,
         [(x.message()) for x in errors],
     )
Exemplo n.º 4
0
    def test_ignore_private_methods(self):
        program = '\n'.join([
            'def function_with_missing_parameter(x):',
            '    """We\'re missing a description of x."""',
            '    print(x / 2)',
            ''
            'def _same_error_but_private_method(x):',
            '    """We\'re missing a description of x."""',
            '    print(x / 2)',
        ])
        tree = ast.parse(program)
        functions = get_function_descriptions(tree)
        checker = IntegrityChecker(
            config=Configuration(
                ignore=[],
                message_template=None,
                style=DocstringStyle.GOOGLE,
                strictness=Strictness.FULL_DESCRIPTION,
                ignore_regex=r'^_(.*)'
            )
        )
        checker.run_checks(functions[0])
        checker.run_checks(functions[1])

        errors = checker.errors
        self.assertEqual(len(errors), 1)
Exemplo n.º 5
0
 def test_runs_other_checks_on_private_arguments(self):
     program = '\n'.join([
         'def reduce(fn, l, _curr=None):',
         '    """Reduce the list with the given function.',
         '',
         '    :param fn: A function which takes two items and produces',
         '        one as a result.',
         '    :param l: The list to reduce.',
         '    :param _curr:',
         '    :return: The final, reduced result of the list.',
         '',
         '    """',
         '    if not l:',
         '        return _curr',
         '    if not _curr:',
         '        return reduce(fn, l[1:], l[0])',
         '    return reduce(fn, l[1:], fn(l[0], _curr))',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker(self.config)
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(
         len(errors),
         1,
         [(x.message()) for x in errors],
     )
     self.assertTrue(isinstance(errors[0], EmptyDescriptionError),
                     errors[0].__class__.__name__)
Exemplo n.º 6
0
    def test_try_block_no_excess_error(self):
        """Make sure the else and except blocks are checked.

        See Issue 20.

        """
        program = '\n'.join([
            'def check_module_installed(name):',
            '    """Temp',
            '    ',
            '    Args:',
            '        name (str): module name',
            '    ',
            '    Returns:',
            '        bool: Whether the module can be imported',
            '    ',
            '    """',
            '    try:',
            '        __import__(name)',
            '    except ImportError:',
            '        return False',
            '    else:',
            '        return True',
        ])
        tree = ast.parse(program)
        functions = get_function_descriptions(tree)
        checker = IntegrityChecker()
        checker.run_checks(functions[0])
        errors = checker.errors
        self.assertEqual(len(errors), 0)
Exemplo n.º 7
0
 def test_raises_style_error_if_no_content_after_colon(self):
     program_template = '\n'.join([
         'def hello_world():',
         '    """Tell the person hello.',
         '',
         '    {}:',
         '        {}:',
         '',
         '    """',
         '    person.hello()',
     ])
     for section, item in [
         ('Args', 'name'),
         ('Raises', 'Exception'),
     ]:
         program = program_template.format(section, item)
         tree = ast.parse(program)
         functions = get_function_descriptions(tree)
         checker = IntegrityChecker()
         checker.run_checks(functions[0])
         errors = checker.errors
         self.assertTrue(
             len(errors) > 0,
             'Failed to raise any errors for {}'.format(section),
         )
         self.assertTrue(
             any([
                 isinstance(error, EmptyDescriptionError)
                 for error in errors
             ]),
             'Failed to raise EmptyDescriptionError for {}'.format(section),
         )
Exemplo n.º 8
0
    def test_empty_description_error(self):
        program_template = '\n'.join([
            'def f():',
            '    """Makes the thing scream.'
            '    ',
            '    :{}:',
            '    """',
            '    scream()',
        ])

        for section in [
                'param x', 'return', 'var x', 'type x', 'vartype x',
                'raises Exception', 'yield', 'ytype', 'rtype'
        ]:
            program = program_template.format(section)
            tree = ast.parse(program)
            function = get_function_descriptions(tree)[0]
            checker = IntegrityChecker(self.config)
            checker.run_checks(function)
            errors = checker.errors
            self.assertTrue(
                len(errors) > 0,
                'EmptyDescriptionError not defined for {}'.format(section),
            )
            self.assertTrue(
                any([
                    isinstance(error, EmptyDescriptionError)
                    for error in errors
                ]),
                'EmptyDescriptionError not defined for {}: {}'.format(
                    section,
                    errors,
                ),
            )
Exemplo n.º 9
0
 def test_extra_raises_added_to_error(self):
     program = '\n'.join([
         'def non_explicitly_errorful_function(x, y):',
         '    """Should not have a raises section.',
         '',
         '    Args:',
         '        x: The divisor.',
         '        y: The dividend.',
         '',
         '    Raises:',
         '        ZeroDivisionError: If y is zero.',
         '',
         '    Returns:',
         '        The quotient.',
         '',
         '    """',
         '    return x / y',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(
         len(checker.errors), 1,
         checker.errors
     )
     error = checker.errors[0]
     self.assertTrue(isinstance(error, ExcessRaiseError))
     self.assertEqual(error.name, 'ZeroDivisionError')
Exemplo n.º 10
0
 def assertHasNoErrors(self, config, docstring):
     checker = IntegrityChecker(config)
     checker.run_checks(self.get_function_with(docstring))
     errors = checker.errors
     self.assertEqual(
         len(errors),
         0,
         [(x.message()) for x in errors]
     )
Exemplo n.º 11
0
 def has_no_errors(self, program):
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(
         len(checker.errors), 0,
         'Expected there to be no errors, but there were {}'.format(
             len(checker.errors)))
Exemplo n.º 12
0
 def test_skips_functions_without_docstrings(self):
     program = '\n'.join([
         'def function_without_docstring(arg1, arg2):',
         '    return 3',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(len(checker.errors), 0)
Exemplo n.º 13
0
 def get_single_error(self, src):
     tree = ast.parse(src)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(
         len(errors), 1,
         'There should only be one error, but there were {}: {}.'.format(
             len(errors), ' '.join([x.__class__.__name__ for x in errors])))
     return errors[0]
Exemplo n.º 14
0
 def test_yields_from_added_to_error(self):
     program = '\n'.join([
         'def function_with_yield():',
         '    """This should have a yields section."""',
         '    yield from (x for x in range(10))',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(len(checker.errors), 1)
     self.assertTrue(isinstance(checker.errors[0], MissingYieldError))
Exemplo n.º 15
0
 def get_n_errors(self, amount, src, config=dict()):
     tree = ast.parse(src)
     functions = get_function_descriptions(tree)
     with ConfigurationContext(**config):
         checker = IntegrityChecker()
         checker.run_checks(functions[0])
         errors = checker.errors
         self.assertEqual(len(errors), amount,
                          ('There should only be {} errors, '
                           'but there were {}: {}.').format(
                               amount, len(errors), ' '.join(
                                   [x.__class__.__name__ for x in errors])))
     return errors
Exemplo n.º 16
0
 def test_missing_parameter_added(self):
     program = '\n'.join([
         'def function_with_missing_parameter(x):',
         '    """We\'re missing a description of x."""',
         '    print(x / 2)',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1)
     self.assertTrue(isinstance(errors[0], MissingParameterError))
Exemplo n.º 17
0
 def test_return_incorrectly_has_parameter(self):
     """Make sure that a return with a parameter is parsed correctly."""
     program = '\n'.join([
         'def f():',
         '    """Some fn',
         '    :return x: some value',
         '    """',
         '    return 3',
     ])
     tree = ast.parse(program)
     function = get_function_descriptions(tree)[0]
     checker = IntegrityChecker(self.config)
     checker.run_checks(function)
Exemplo n.º 18
0
 def test_missing_return_parameter_added(self):
     program = '\n'.join([
         'def function_without_return():',
         '    """This should have a return in the docstring."""',
         '    global bad_number',
         '    return bad_number',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1)
     self.assertTrue(isinstance(errors[0], MissingReturnError))
Exemplo n.º 19
0
    def test_incorrect_syntax_raises_exception_optionally(self):
        # example taken from https://github.com/deezer/html-linter
        program = '\n'.join([
            'def lint(html, exclude=None):',
            '    """Lints and HTML5 file.',
            '',
            '    Args:',
            '      html: str the contents of the file.',
            '      exclude: optional iterable with the Message classes',
            '               to be ommited from the output.',
            '    """',
            '    exclude = exclude or []',
            '    messages = [m.__unicode__() for m in HTML5Linter(html',
            '        ).messages',
            '                if not isinstance(m, tuple(exclude))]',
            '    return \'\\n\'.join(messages)',
        ])
        tree = ast.parse(program)
        functions = get_function_descriptions(tree)
        checker = IntegrityChecker(raise_errors=True)

        with self.assertRaises(ParserException):
            checker.run_checks(functions[0])

        # The default is to not raise exceptions.
        checker = IntegrityChecker()
        checker.run_checks(functions[0])
        errors = checker.errors
        self.assertTrue(isinstance(errors[0], GenericSyntaxError))
Exemplo n.º 20
0
    def test_throws_assertion_if_no_colon_in_parameter_line(self):
        program = '\n'.join([
            'def hash_integer(value):',
            '    """Return the hash value of an integer.',
            '',
            '    Args:',
            '        value: The integer that we want',
            # This line should cause an error because it is at the
            # level for parameter identifiers.
            '        to make a hashed value of.',
            '',
            '    Returns:',
            '        The hashed value.',
            '',
            '    """',
            '    return value % 7',
        ])
        tree = ast.parse(program)
        functions = get_function_descriptions(tree)

        checker = IntegrityChecker(raise_errors=True)

        with self.assertRaises(ParserException):
            checker.run_checks(functions[0])

        checker = IntegrityChecker()
        checker.run_checks(functions[0])
        errors = checker.errors
        self.assertTrue(isinstance(errors[0], GenericSyntaxError))
Exemplo n.º 21
0
 def test_missing_raises_added_to_error(self):
     program = '\n'.join([
         'def errorful_function():',
         '    """Should have a raises section here."""',
         '    raise AttributeError',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(len(checker.errors), 1)
     error = checker.errors[0]
     self.assertTrue(isinstance(error, MissingRaiseError))
     self.assertEqual(error.name, 'AttributeError')
Exemplo n.º 22
0
 def test_raises_style_error_if_no_content_after_colon(self):
     program = '\n'.join([
         'def hello_world(name):',
         '    """Tell the person hello.',
         '',
         '    Args:',
         '        name:',
         '',
         '    """',
         '    print("Hello, {}".format(name))',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
Exemplo n.º 23
0
 def test_return_type_unchecked_if_not_defined_in_function(self):
     program = '\n'.join([
         'def foo():',
         '    """Just a foobar.',
         '',
         '    Returns:',
         '        str: bar',
         '',
         '    """',
         '    return "bar"',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(len(checker.errors), 0)
Exemplo n.º 24
0
 def test_excess_yield_added_to_errors(self):
     program = '\n'.join([
         'def function_with_yield():',
         '    """This should not have a yields section.',
         '',
         '    Yields:',
         '        A number.',
         '',
         '    """',
         '    print(\'Doesnt yield\')',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     self.assertEqual(len(checker.errors), 1)
     self.assertTrue(isinstance(checker.errors[0], ExcessYieldError))
Exemplo n.º 25
0
 def test_excess_parameter_added(self):
     program = '\n'.join([
         'def function_with_excess_parameter():',
         '    """We have an extra parameter below, extra.',
         '',
         '    Args:',
         '        extra: This shouldn\'t be here.',
         '',
         '    """',
         '    print(\'Hey!\')',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1)
     self.assertTrue(isinstance(errors[0], ExcessParameterError))
Exemplo n.º 26
0
 def test_empty_type_section(self):
     program = '\n'.join([
         'def foo(bar):',
         '    """Foo.',
         '',
         '    Args:',
         '        bar (): A bar.',
         '    """',
         '    print(bar)',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker()
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1, [(x.message()) for x in errors])
     self.assertTrue(isinstance(errors[0], EmptyTypeError),
                     errors[0].__class__.__name__)
Exemplo n.º 27
0
 def test_missing_parameter(self):
     """Make sure we capture missing parameters."""
     program = '\n'.join([
         'def cons(x, l):',
         '    """Add an item to the head of the list.',
         '    ',
         '    :param x: The item to add to the list.',
         '    :return: The list with the item attached.',
         '    ',
         '    """',
         '    return [x] + l',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker(self.config)
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1, [(x.message()) for x in errors])
     self.assertTrue(isinstance(errors[0], MissingParameterError))
Exemplo n.º 28
0
 def test_variable_doesnt_exist(self):
     """Ensure described variables must exist in the function."""
     program = '\n'.join([
         'def circle_area(r):',
         '    """Calculate the circle\'s area.',
         '    ',
         '    :param r: The radius of the circle.',
         '    :var pi: An estimate of PI.',
         '    :return: The area of the circle.',
         '    ',
         '    """',
         '    return 3.1415 * r**2',
     ])
     tree = ast.parse(program)
     functions = get_function_descriptions(tree)
     checker = IntegrityChecker(self.config)
     checker.run_checks(functions[0])
     errors = checker.errors
     self.assertEqual(len(errors), 1, [(x.message()) for x in errors])
     self.assertTrue(isinstance(errors[0], ExcessVariableError))
     self.assertEqual(errors[0].terse_message, '+v pi')
Exemplo n.º 29
0
 def test_catch_and_raise(self):
     program = '\n'.join([
         'def false_positive() -> None:',
         '    """summary',
         '',
         '    :raises ValueError: description',
         '    """',
         '    try:',
         '        raise ValueError("233")',
         '    except ValueError as e:',
         '        raise e from None',
     ])
     tree = ast.parse(program)
     function = get_function_descriptions(tree)[0]
     checker = IntegrityChecker(self.config)
     checker.run_checks(function)
     self.assertEqual(
         len(checker.errors),
         0,
         checker.errors,
     )
Exemplo n.º 30
0
    def test_empty_description_error(self):
        program_template = '\n'.join([
            'def f():',
            '    """Has arguments.',
            '    ',
            '    {}',
            '    {}',
            '    {}',
            '',
            '    """',
            '    scream()',
        ])

        for section, item in [('Parameters', 'x')]:
            program = program_template.format(
                section,
                '-' * len(section),
                item,
            )
            tree = ast.parse(program)
            function = get_function_descriptions(tree)[0]
            checker = IntegrityChecker(self.config)
            checker.run_checks(function)
            errors = checker.errors
            self.assertTrue(
                len(errors) > 0,
                'EmptyDescriptionError not defined for {}'.format(section),
            )
            self.assertTrue(
                any([
                    isinstance(error, EmptyDescriptionError)
                    for error in errors
                ]),
                'EmptyDescriptionError not defined for {}: {}'.format(
                    section,
                    errors,
                ),
            )