示例#1
0
def test_PythonBlock_doctest_only_first_in_function_3():
    block = PythonBlock(dedent("""
        def f():
            return '>>> x'
    """).lstrip())
    expected = []
    assert block.get_doctests() == expected
示例#2
0
def test_PythonBlock_doctest_only_first_in_function_4():
    block = PythonBlock(dedent("""
        def f():
            ('>>> a' + '')
            3
    """).lstrip())
    expected = []
    assert block.get_doctests() == expected
示例#3
0
def test_PythonBlock_doctest_only_first_in_class_1():
    block = PythonBlock(dedent("""
        class C:
            '>>> C(11475111)'
            def f(self): pass
            '>>> x'

    """).lstrip())
    expected = [PythonBlock('C(11475111)\n', startpos=(2,5))]
    assert block.get_doctests() == expected
示例#4
0
def test_PythonBlock_doctest_1():
    block = PythonBlock(dedent("""
        # x
        '''
          >>> foo(bar
          ...     + baz)
        '''
    """).lstrip())
    expected = [PythonBlock('foo(bar\n    + baz)\n', startpos=(3,3))]
    assert block.get_doctests() == expected
示例#5
0
def test_PythonBlock_doctest_only_first_in_function_not_try_1():
    block = PythonBlock(dedent("""
        def f():
            '>>> a'
            try:
                '>>> b'
            except:
                pass
    """).lstrip())
    expected = [PythonBlock('a\n', startpos=(2,5))]
    assert block.get_doctests() == expected
示例#6
0
def test_PythonBlock_doctest_only_first_in_function_1():
    # Verify that we only include doctests from the first string in a
    # function.
    block = PythonBlock(dedent("""
        def f():
            '>>> a'
            3
            '>>> b'
    """).lstrip())
    expected = [PythonBlock('a\n', startpos=(2,5))]
    assert block.get_doctests() == expected
示例#7
0
def test_PythonBlock_doctest_nested_cond_1():
    block = PythonBlock(dedent("""
        def f():
            '>>> f(17556901)'
            if True:
                def g():
                    '>>> g(21607865)'
    """).lstrip())
    expected = [PythonBlock('f(17556901)\n', startpos=(2,5)),
                PythonBlock('g(21607865)\n', startpos=(5,13))]
    assert block.get_doctests() == expected
示例#8
0
def test_PythonBlock_doctest_nested_1():
    # Verify that we only include doctests from nested functions.
    block = PythonBlock(dedent("""
        def f():
            '>>> f(18739149)'
            def g():
                '>>> g(29355493)'
    """).lstrip())
    expected = [PythonBlock('f(18739149)\n', startpos=(2,5)),
                PythonBlock('g(29355493)\n', startpos=(4,9))]
    assert block.get_doctests() == expected
示例#9
0
def test_PythonBlock_doctest_ignore_doctest_options_1():
    block = PythonBlock(dedent('''
        def foo():
            """
            >>> 123 # doctest:+FOOBAR
            """
    '''))
    doctest_blocks = block.get_doctests()
    doctest_block, = doctest_blocks
    expected = (PythonStatement("123 # doctest:+FOOBAR\n", startpos=(4, 9)),)
    assert doctest_block.statements == expected
示例#10
0
def test_PythonBlock_doctest_assignments_ClassDef_1():
    block = PythonBlock(dedent("""
        class C:
            ">>> C(17621216)"
            x = 5
            ">>> C(28208124)"
            def f(self): pass
            ">>> x"
    """).lstrip())
    expected = [PythonBlock('C(17621216)\n', startpos=(2,5)),
                PythonBlock('C(28208124)\n', startpos=(4,5))]
    assert block.get_doctests() == expected
示例#11
0
def test_PythonBlock_doctest_with_1():
    block = PythonBlock(dedent('''
        def foo():
            """
            hello
              >>> with 11:
              ...   22
            """
    '''))
    doctest_blocks = block.get_doctests()
    doctest_block, = doctest_blocks
    expected = (PythonStatement("with 11:\n  22\n", startpos=(5, 11)),)
    assert doctest_block.statements == expected
示例#12
0
def test_PythonBlock_doctest_nested_class_1():
    block = PythonBlock(dedent("""
        def f():
            '>>> f(11462083)'
            class C:
                '>>> C(21800340)'
                @classmethod
                def g(cls):
                    '>>> g(35606252)'
    """).lstrip())
    expected = [PythonBlock('f(11462083)\n', startpos=(2,5)),
                PythonBlock('C(21800340)\n', startpos=(4,9)),
                PythonBlock('g(35606252)\n', startpos=(7,13))]
    assert block.get_doctests() == expected
示例#13
0
def test_PythonBlock_doctest_assignments_method_1():
    block = PythonBlock(dedent("""
        class C:
            ">>> C(13798505)"
            def __init__(self):
                ">>> C(25709748)"
                self.x = 0
                ">>> C(32231717)"
                f()
                ">>> x"
    """).lstrip())
    expected = [PythonBlock('C(13798505)\n', startpos=(2,5)),
                PythonBlock('C(25709748)\n', startpos=(4,9)),
                PythonBlock('C(32231717)\n', startpos=(6,9))]
    assert block.get_doctests() == expected
示例#14
0
def test_PythonBlock_doctest_assignments_at_global_scope_1():
    # Verify that we only include doctests from (Epydoc) "variable docstrings"
    # at global scope.
    block = PythonBlock(dedent("""
        '>>> x'
        def f(): pass

        a = 4
        '>>> a'

        def g(): pass

        b = 5
        '>>> b'
    """).lstrip())
    expected = [PythonBlock('x\n'),
                PythonBlock('a\n', startpos=(5,1)),
                PythonBlock('b\n', startpos=(10,1))]
    assert block.get_doctests() == expected
示例#15
0
def find_unused_and_missing_imports(codeblock):
    """
    Find unused imports and missing imports, taking docstrings into account.

    Pyflakes is used to statically analyze for unused and missing imports.
    Doctests in docstrings are analyzed as code and epydoc references in
    docstrings also prevent removal.

    In the following example, 'bar' is not considered unused because there is
    a string that references it in braces:

      >>> find_unused_and_missing_imports("import foo as bar, baz\\n'{bar}'\\n")
      ([('baz', 1)], [])

    @type codeblock:
      L{PythonBlock} or convertible
    @return:
      C{(unused_imports, missing_imports)} where C{unused_imports} and
      C{missing_imports} each are sequences of C{(import_as, lineno)} tuples.
    """
    # TODO: rewrite this using our own AST parser.
    # Once we do that we can also process doctests and literal brace
    # identifiers at the proper scope level.  We should treat both doctests
    # and literal brace identifiers as "soft" uses that don't trigger missing
    # imports but do trigger as used imports.
    codeblock = PythonBlock(codeblock)
    # Run pyflakes on the main code.
    unused_imports, missing_imports = (
        _pyflakes_find_unused_and_missing_imports(codeblock))
    # Find doctests.
    doctest_blocks = codeblock.get_doctests()
    if doctest_blocks:
        # There are doctests.  Re-run pyflakes on main code + doctests.  Don't
        # report missing imports in doctests, but do treat existing imports as
        # 'used' if they are used in doctests.
        # Create one data structure to pass to pyflakes.  This is going to
        # screw up linenos but we won't use them, so it doesn't matter.
        bigblock = PythonBlock.concatenate([codeblock] + doctest_blocks,
                                           assume_contiguous=True)
        wdt_unused_imports, _ = (  # wdt = with doc tests
            _pyflakes_find_unused_and_missing_imports(bigblock))
        wdt_unused_asimports = set(import_as
                                   for import_as, lineno in wdt_unused_imports)
        # Keep only the intersection of unused imports.
        unused_imports = [(import_as, lineno)
                          for import_as, lineno in unused_imports
                          if import_as in wdt_unused_asimports]
    # Find literal brace identifiers like "... L{Foo} ...".
    # TODO: merge this into our own AST-based missing/unused-import-finder
    # (replacing pyflakes).
    literal_brace_identifiers = set(iden for f in codeblock.string_literals()
                                    for iden in brace_identifiers(f.s))
    if literal_brace_identifiers:
        # Pyflakes doesn't look at docstrings containing references like
        # "L{foo}" which require an import, nor at C{str.format} strings like
        # '''"{foo}".format(...)'''.  Don't remove supposedly-unused imports
        # which match a string literal brace identifier.
        unused_imports = [(import_as, lineno)
                          for import_as, lineno in unused_imports
                          if import_as not in literal_brace_identifiers]
    return unused_imports, missing_imports