aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/parso/py3/tests/test_get_code.py
blob: d99d792b93c052f3e8f1f32b8a7ea32c1c5689c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import difflib

import pytest

from parso import parse

code_basic_features = '''
"""A mod docstring"""

def a_function(a_argument, a_default = "default"):
    """A func docstring"""

    a_result = 3 * a_argument
    print(a_result)  # a comment
    b = """
from
to""" + "huhu"


    if a_default == "default":
        return str(a_result)
    else
        return None
'''


def diff_code_assert(a, b, n=4):
    if a != b:
        diff = "\n".join(difflib.unified_diff(
            a.splitlines(),
            b.splitlines(),
            n=n,
            lineterm=""
        ))
        assert False, "Code does not match:\n%s\n\ncreated code:\n%s" % (
            diff,
            b
        )
    pass


def test_basic_parsing():
    """Validate the parsing features"""

    m = parse(code_basic_features)
    diff_code_assert(
        code_basic_features,
        m.get_code()
    )


def test_operators():
    src = '5  * 3'
    module = parse(src)
    diff_code_assert(src, module.get_code())


def test_get_code():
    """Use the same code that the parser also generates, to compare"""
    s = '''"""a docstring"""
class SomeClass(object, mixin):
    def __init__(self):
        self.xy = 3.0
        """statement docstr"""
    def some_method(self):
        return 1
    def yield_method(self):
        while hasattr(self, 'xy'):
            yield True
        for x in [1, 2]:
            yield x
    def empty(self):
        pass
class Empty:
    pass
class WithDocstring:
    """class docstr"""
    pass
def method_with_docstring():
    """class docstr"""
    pass
'''
    assert parse(s).get_code() == s


def test_end_newlines():
    """
    The Python grammar explicitly needs a newline at the end. Jedi though still
    wants to be able, to return the exact same code without the additional new
    line the parser needs.
    """
    def test(source, end_pos):
        module = parse(source)
        assert module.get_code() == source
        assert module.end_pos == end_pos

    test('a', (1, 1))
    test('a\n', (2, 0))
    test('a\nb', (2, 1))
    test('a\n#comment\n', (3, 0))
    test('a\n#comment', (2, 8))
    test('a#comment', (1, 9))
    test('def a():\n pass', (2, 5))

    test('def a(', (1, 6))


@pytest.mark.parametrize(('code', 'types'), [
    ('\r', ['endmarker']),
    ('\n\r', ['endmarker'])
])
def test_carriage_return_at_end(code, types):
    """
    By adding an artificial newline this created weird side effects for
    \r at the end of files.
    """
    tree = parse(code)
    assert tree.get_code() == code
    assert [c.type for c in tree.children] == types
    assert tree.end_pos == (len(code) + 1, 0)


@pytest.mark.parametrize('code', [
    ' ',
    '    F"""',
    '    F"""\n',
    '    F""" \n',
    '    F""" \n3',
    '    f"""\n"""',
    '    f"""\n"""\n',
])
def test_full_code_round_trip(code):
    assert parse(code).get_code() == code