1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750 |
- # -*- coding: utf-8 -*-
- from textwrap import dedent
- import logging
- import sys
- import pytest
- from parso.utils import split_lines
- from parso import cache
- from parso import load_grammar
- from parso.python.diff import DiffParser, _assert_valid_graph, _assert_nodes_are_equal
- from parso import parse
- ANY = object()
- def test_simple():
- """
- The diff parser reuses modules. So check for that.
- """
- grammar = load_grammar()
- module_a = grammar.parse('a', diff_cache=True)
- assert grammar.parse('b', diff_cache=True) == module_a
- def _check_error_leaves_nodes(node):
- if node.type in ('error_leaf', 'error_node'):
- return node
- try:
- children = node.children
- except AttributeError:
- pass
- else:
- for child in children:
- x_node = _check_error_leaves_nodes(child)
- if x_node is not None:
- return x_node
- return None
- class Differ(object):
- grammar = load_grammar()
- def initialize(self, code):
- logging.debug('differ: initialize')
- try:
- del cache.parser_cache[self.grammar._hashed][None]
- except KeyError:
- pass
- self.lines = split_lines(code, keepends=True)
- self.module = parse(code, diff_cache=True, cache=True)
- assert code == self.module.get_code()
- _assert_valid_graph(self.module)
- return self.module
- def parse(self, code, copies=0, parsers=0, expect_error_leaves=False):
- logging.debug('differ: parse copies=%s parsers=%s', copies, parsers)
- lines = split_lines(code, keepends=True)
- diff_parser = DiffParser(
- self.grammar._pgen_grammar,
- self.grammar._tokenizer,
- self.module,
- )
- new_module = diff_parser.update(self.lines, lines)
- self.lines = lines
- assert code == new_module.get_code()
- _assert_valid_graph(new_module)
- without_diff_parser_module = parse(code)
- _assert_nodes_are_equal(new_module, without_diff_parser_module)
- error_node = _check_error_leaves_nodes(new_module)
- assert expect_error_leaves == (error_node is not None), error_node
- if parsers is not ANY:
- assert diff_parser._parser_count == parsers
- if copies is not ANY:
- assert diff_parser._copy_count == copies
- return new_module
- @pytest.fixture()
- def differ():
- return Differ()
- def test_change_and_undo(differ):
- func_before = 'def func():\n pass\n'
- # Parse the function and a.
- differ.initialize(func_before + 'a')
- # Parse just b.
- differ.parse(func_before + 'b', copies=1, parsers=2)
- # b has changed to a again, so parse that.
- differ.parse(func_before + 'a', copies=1, parsers=2)
- # Same as before parsers should not be used. Just a simple copy.
- differ.parse(func_before + 'a', copies=1)
- # Now that we have a newline at the end, everything is easier in Python
- # syntax, we can parse once and then get a copy.
- differ.parse(func_before + 'a\n', copies=1, parsers=2)
- differ.parse(func_before + 'a\n', copies=1)
- # Getting rid of an old parser: Still no parsers used.
- differ.parse('a\n', copies=1)
- # Now the file has completely changed and we need to parse.
- differ.parse('b\n', parsers=1)
- # And again.
- differ.parse('a\n', parsers=1)
- def test_positions(differ):
- func_before = 'class A:\n pass\n'
- m = differ.initialize(func_before + 'a')
- assert m.start_pos == (1, 0)
- assert m.end_pos == (3, 1)
- m = differ.parse('a', copies=1)
- assert m.start_pos == (1, 0)
- assert m.end_pos == (1, 1)
- m = differ.parse('a\n\n', parsers=1)
- assert m.end_pos == (3, 0)
- m = differ.parse('a\n\n ', copies=1, parsers=2)
- assert m.end_pos == (3, 1)
- m = differ.parse('a ', parsers=1)
- assert m.end_pos == (1, 2)
- def test_if_simple(differ):
- src = dedent('''\
- if 1:
- a = 3
- ''')
- else_ = "else:\n a = ''\n"
- differ.initialize(src + 'a')
- differ.parse(src + else_ + "a", copies=0, parsers=1)
- differ.parse(else_, parsers=2, expect_error_leaves=True)
- differ.parse(src + else_, parsers=1)
- def test_func_with_for_and_comment(differ):
- # The first newline is important, leave it. It should not trigger another
- # parser split.
- src = dedent("""\
- def func():
- pass
- for a in [1]:
- # COMMENT
- a""")
- differ.initialize(src)
- differ.parse('a\n' + src, copies=1, parsers=3)
- def test_one_statement_func(differ):
- src = dedent("""\
- first
- def func(): a
- """)
- differ.initialize(src + 'second')
- differ.parse(src + 'def second():\n a', parsers=1, copies=1)
- def test_for_on_one_line(differ):
- src = dedent("""\
- foo = 1
- for x in foo: pass
- def hi():
- pass
- """)
- differ.initialize(src)
- src = dedent("""\
- def hi():
- for x in foo: pass
- pass
- pass
- """)
- differ.parse(src, parsers=2)
- src = dedent("""\
- def hi():
- for x in foo: pass
- pass
- def nested():
- pass
- """)
- # The second parser is for parsing the `def nested()` which is an `equal`
- # operation in the SequenceMatcher.
- differ.parse(src, parsers=1, copies=1)
- def test_open_parentheses(differ):
- func = 'def func():\n a\n'
- code = 'isinstance(\n\n' + func
- new_code = 'isinstance(\n' + func
- differ.initialize(code)
- differ.parse(new_code, parsers=1, expect_error_leaves=True)
- new_code = 'a = 1\n' + new_code
- differ.parse(new_code, parsers=2, expect_error_leaves=True)
- func += 'def other_func():\n pass\n'
- differ.initialize('isinstance(\n' + func)
- # Cannot copy all, because the prefix of the function is once a newline and
- # once not.
- differ.parse('isinstance()\n' + func, parsers=2, copies=1)
- def test_open_parentheses_at_end(differ):
- code = "a['"
- differ.initialize(code)
- differ.parse(code, parsers=1, expect_error_leaves=True)
- def test_backslash(differ):
- src = dedent(r"""
- a = 1\
- if 1 else 2
- def x():
- pass
- """)
- differ.initialize(src)
- src = dedent(r"""
- def x():
- a = 1\
- if 1 else 2
- def y():
- pass
- """)
- differ.parse(src, parsers=1)
- src = dedent(r"""
- def first():
- if foo \
- and bar \
- or baz:
- pass
- def second():
- pass
- """)
- differ.parse(src, parsers=2)
- def test_full_copy(differ):
- code = 'def foo(bar, baz):\n pass\n bar'
- differ.initialize(code)
- differ.parse(code, copies=1)
- def test_wrong_whitespace(differ):
- code = '''
- hello
- '''
- differ.initialize(code)
- differ.parse(code + 'bar\n ', parsers=2, expect_error_leaves=True)
- code += """abc(\npass\n """
- differ.parse(code, parsers=2, expect_error_leaves=True)
- def test_issues_with_error_leaves(differ):
- code = dedent('''
- def ints():
- str..
- str
- ''')
- code2 = dedent('''
- def ints():
- str.
- str
- ''')
- differ.initialize(code)
- differ.parse(code2, parsers=1, expect_error_leaves=True)
- def test_unfinished_nodes(differ):
- code = dedent('''
- class a():
- def __init__(self, a):
- self.a = a
- def p(self):
- a(1)
- ''')
- code2 = dedent('''
- class a():
- def __init__(self, a):
- self.a = a
- def p(self):
- self
- a(1)
- ''')
- differ.initialize(code)
- differ.parse(code2, parsers=2, copies=2)
- def test_nested_if_and_scopes(differ):
- code = dedent('''
- class a():
- if 1:
- def b():
- 2
- ''')
- code2 = code + ' else:\n 3'
- differ.initialize(code)
- differ.parse(code2, parsers=1, copies=0)
- def test_word_before_def(differ):
- code1 = 'blub def x():\n'
- code2 = code1 + ' s'
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=0, expect_error_leaves=True)
- def test_classes_with_error_leaves(differ):
- code1 = dedent('''
- class X():
- def x(self):
- blablabla
- assert 3
- self.
- class Y():
- pass
- ''')
- code2 = dedent('''
- class X():
- def x(self):
- blablabla
- assert 3
- str(
- class Y():
- pass
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- def test_totally_wrong_whitespace(differ):
- code1 = '''
- class X():
- raise n
- class Y():
- pass
- '''
- code2 = '''
- class X():
- raise n
- str(
- class Y():
- pass
- '''
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=0, expect_error_leaves=True)
- def test_node_insertion(differ):
- code1 = dedent('''
- class X():
- def y(self):
- a = 1
- b = 2
- c = 3
- d = 4
- ''')
- code2 = dedent('''
- class X():
- def y(self):
- a = 1
- b = 2
- str
- c = 3
- d = 4
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=2)
- def test_whitespace_at_end(differ):
- code = dedent('str\n\n')
- differ.initialize(code)
- differ.parse(code + '\n', parsers=1, copies=1)
- def test_endless_while_loop(differ):
- """
- This was a bug in Jedi #878.
- """
- code = '#dead'
- differ.initialize(code)
- module = differ.parse(code, parsers=1)
- assert module.end_pos == (1, 5)
- code = '#dead\n'
- differ.initialize(code)
- module = differ.parse(code + '\n', parsers=1)
- assert module.end_pos == (3, 0)
- def test_in_class_movements(differ):
- code1 = dedent("""\
- class PlaybookExecutor:
- p
- b
- def run(self):
- 1
- try:
- x
- except:
- pass
- """)
- code2 = dedent("""\
- class PlaybookExecutor:
- b
- def run(self):
- 1
- try:
- x
- except:
- pass
- """)
- differ.initialize(code1)
- differ.parse(code2, parsers=1)
- def test_in_parentheses_newlines(differ):
- code1 = dedent("""
- x = str(
- True)
- a = 1
- def foo():
- pass
- b = 2""")
- code2 = dedent("""
- x = str(True)
- a = 1
- def foo():
- pass
- b = 2""")
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1)
- def test_indentation_issue(differ):
- code1 = dedent("""
- import module
- """)
- code2 = dedent("""
- class L1:
- class L2:
- class L3:
- def f(): pass
- def f(): pass
- def f(): pass
- def f(): pass
- """)
- differ.initialize(code1)
- differ.parse(code2, parsers=2)
- def test_endmarker_newline(differ):
- code1 = dedent('''\
- docu = None
- # some comment
- result = codet
- incomplete_dctassign = {
- "module"
- if "a":
- x = 3 # asdf
- ''')
- code2 = code1.replace('codet', 'coded')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- def test_newlines_at_end(differ):
- differ.initialize('a\n\n')
- differ.parse('a\n', copies=1)
- def test_end_newline_with_decorator(differ):
- code = dedent('''\
- @staticmethod
- def spam():
- import json
- json.l''')
- differ.initialize(code)
- module = differ.parse(code + '\n', copies=1, parsers=1)
- decorated, endmarker = module.children
- assert decorated.type == 'decorated'
- decorator, func = decorated.children
- suite = func.children[-1]
- assert suite.type == 'suite'
- newline, first_stmt, second_stmt = suite.children
- assert first_stmt.get_code() == ' import json\n'
- assert second_stmt.get_code() == ' json.l\n'
- def test_invalid_to_valid_nodes(differ):
- code1 = dedent('''\
- def a():
- foo = 3
- def b():
- la = 3
- else:
- la
- return
- foo
- base
- ''')
- code2 = dedent('''\
- def a():
- foo = 3
- def b():
- la = 3
- if foo:
- latte = 3
- else:
- la
- return
- foo
- base
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=3)
- def test_if_removal_and_reappearence(differ):
- code1 = dedent('''\
- la = 3
- if foo:
- latte = 3
- else:
- la
- pass
- ''')
- code2 = dedent('''\
- la = 3
- latte = 3
- else:
- la
- pass
- ''')
- code3 = dedent('''\
- la = 3
- if foo:
- latte = 3
- else:
- la
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=2, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=1)
- differ.parse(code3, parsers=1, copies=1)
- def test_add_error_indentation(differ):
- code = 'if x:\n 1\n'
- differ.initialize(code)
- differ.parse(code + ' 2\n', parsers=1, copies=0, expect_error_leaves=True)
- def test_differing_docstrings(differ):
- code1 = dedent('''\
- def foobar(x, y):
- 1
- return x
- def bazbiz():
- foobar()
- lala
- ''')
- code2 = dedent('''\
- def foobar(x, y):
- 2
- return x + y
- def bazbiz():
- z = foobar()
- lala
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1)
- differ.parse(code1, parsers=2, copies=1)
- def test_one_call_in_function_change(differ):
- code1 = dedent('''\
- def f(self):
- mro = [self]
- for a in something:
- yield a
- def g(self):
- return C(
- a=str,
- b=self,
- )
- ''')
- code2 = dedent('''\
- def f(self):
- mro = [self]
- def g(self):
- return C(
- a=str,
- t
- b=self,
- )
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=2, copies=1)
- def test_function_deletion(differ):
- code1 = dedent('''\
- class C(list):
- def f(self):
- def iterate():
- for x in b:
- break
- return list(iterate())
- ''')
- code2 = dedent('''\
- class C():
- def f(self):
- for x in b:
- break
- return list(iterate())
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=0, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=0)
- def test_docstring_removal(differ):
- code1 = dedent('''\
- class E(Exception):
- """
- 1
- 2
- 3
- """
- class S(object):
- @property
- def f(self):
- return cmd
- def __repr__(self):
- return cmd2
- ''')
- code2 = dedent('''\
- class E(Exception):
- """
- 1
- 3
- """
- class S(object):
- @property
- def f(self):
- return cmd
- return cmd2
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=2)
- differ.parse(code1, parsers=3, copies=1)
- def test_paren_in_strange_position(differ):
- code1 = dedent('''\
- class C:
- """ ha """
- def __init__(self, message):
- self.message = message
- ''')
- code2 = dedent('''\
- class C:
- """ ha """
- )
- def __init__(self, message):
- self.message = message
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=2, expect_error_leaves=True)
- differ.parse(code1, parsers=0, copies=2)
- def insert_line_into_code(code, index, line):
- lines = split_lines(code, keepends=True)
- lines.insert(index, line)
- return ''.join(lines)
- def test_paren_before_docstring(differ):
- code1 = dedent('''\
- # comment
- """
- The
- """
- from parso import tree
- from parso import python
- ''')
- code2 = insert_line_into_code(code1, 1, ' ' * 16 + 'raise InternalParseError(\n')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=2, copies=1)
- def test_parentheses_before_method(differ):
- code1 = dedent('''\
- class A:
- def a(self):
- pass
- class B:
- def b(self):
- if 1:
- pass
- ''')
- code2 = dedent('''\
- class A:
- def a(self):
- pass
- Exception.__init__(self, "x" %
- def b(self):
- if 1:
- pass
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=2, copies=1)
- def test_indentation_issues(differ):
- code1 = dedent('''\
- class C:
- def f():
- 1
- if 2:
- return 3
- def g():
- to_be_removed
- pass
- ''')
- code2 = dedent('''\
- class C:
- def f():
- 1
- ``something``, very ``weird``).
- if 2:
- return 3
- def g():
- to_be_removed
- pass
- ''')
- code3 = dedent('''\
- class C:
- def f():
- 1
- if 2:
- return 3
- def g():
- pass
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=2)
- differ.parse(code3, parsers=2, copies=1)
- differ.parse(code1, parsers=2, copies=1)
- def test_error_dedent_issues(differ):
- code1 = dedent('''\
- while True:
- try:
- 1
- except KeyError:
- if 2:
- 3
- except IndexError:
- 4
- 5
- ''')
- code2 = dedent('''\
- while True:
- try:
- except KeyError:
- 1
- except KeyError:
- if 2:
- 3
- except IndexError:
- 4
- something_inserted
- 5
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=0, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=0)
- def test_random_text_insertion(differ):
- code1 = dedent('''\
- class C:
- def f():
- return node
- def g():
- try:
- 1
- except KeyError:
- 2
- ''')
- code2 = dedent('''\
- class C:
- def f():
- return node
- Some'random text: yeah
- for push in plan.dfa_pushes:
- def g():
- try:
- 1
- except KeyError:
- 2
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=2, copies=1)
- def test_many_nested_ifs(differ):
- code1 = dedent('''\
- class C:
- def f(self):
- def iterate():
- if 1:
- yield t
- else:
- yield
- return
- def g():
- 3
- ''')
- code2 = dedent('''\
- def f(self):
- def iterate():
- if 1:
- yield t
- hahahaha
- if 2:
- else:
- yield
- return
- def g():
- 3
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=1)
- @pytest.mark.skipif(sys.version_info < (3, 5), reason="Async starts working in 3.5")
- @pytest.mark.parametrize('prefix', ['', 'async '])
- def test_with_and_funcdef_in_call(differ, prefix):
- code1 = prefix + dedent('''\
- with x:
- la = C(
- a=1,
- b=2,
- c=3,
- )
- ''')
- code2 = insert_line_into_code(code1, 3, 'def y(self, args):\n')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1)
- def test_wrong_backslash(differ):
- code1 = dedent('''\
- def y():
- 1
- for x in y:
- continue
- ''')
- code2 = insert_line_into_code(code1, 3, '\\.whl$\n')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=1)
- def test_random_unicode_characters(differ):
- """
- Those issues were all found with the fuzzer.
- """
- differ.initialize('')
- differ.parse(u'\x1dĔBϞɛˁşʑ˳˻ȣſéÎ\x90̕ȟòwʘ\x1dĔBϞɛˁşʑ˳˻ȣſéÎ', parsers=1,
- expect_error_leaves=True)
- differ.parse(u'\r\r', parsers=1)
- differ.parse(u"˟Ę\x05À\r rúƣ@\x8a\x15r()\n", parsers=1, expect_error_leaves=True)
- differ.parse(u'a\ntaǁ\rGĒōns__\n\nb', parsers=1,
- expect_error_leaves=sys.version_info[0] == 2)
- s = ' if not (self, "_fi\x02\x0e\x08\n\nle"):'
- differ.parse(s, parsers=1, expect_error_leaves=True)
- differ.parse('')
- differ.parse(s + '\n', parsers=1, expect_error_leaves=True)
- differ.parse(u' result = (\r\f\x17\t\x11res)', parsers=1, expect_error_leaves=True)
- differ.parse('')
- differ.parse(' a( # xx\ndef', parsers=1, expect_error_leaves=True)
- def test_dedent_end_positions(differ):
- code1 = dedent('''\
- if 1:
- if b:
- 2
- c = {
- 5}
- ''')
- code2 = dedent(u'''\
- if 1:
- if ⌟ഒᜈྡྷṭb:
- 2
- 'l': ''}
- c = {
- 5}
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1)
- def test_special_no_newline_ending(differ):
- code1 = dedent('''\
- 1
- ''')
- code2 = dedent('''\
- 1
- is ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=0)
- def test_random_character_insertion(differ):
- code1 = dedent('''\
- def create(self):
- 1
- if self.path is not None:
- return
- # 3
- # 4
- ''')
- code2 = dedent('''\
- def create(self):
- 1
- if 2:
- x return
- # 3
- # 4
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=1)
- def test_import_opening_bracket(differ):
- code1 = dedent('''\
- 1
- 2
- from bubu import (X,
- ''')
- code2 = dedent('''\
- 11
- 2
- from bubu import (X,
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=2, expect_error_leaves=True)
- def test_opening_bracket_at_end(differ):
- code1 = dedent('''\
- class C:
- 1
- [
- ''')
- code2 = dedent('''\
- 3
- class C:
- 1
- [
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
- def test_all_sorts_of_indentation(differ):
- code1 = dedent('''\
- class C:
- 1
- def f():
- 'same'
- if foo:
- a = b
- end
- ''')
- code2 = dedent('''\
- class C:
- 1
- def f(yield await %|(
- 'same'
- \x02\x06\x0f\x1c\x11
- if foo:
- a = b
- end
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
- code3 = dedent('''\
- if 1:
- a
- b
- c
- d
- \x00
- ''')
- differ.parse(code3, parsers=1, expect_error_leaves=True)
- differ.parse('')
- def test_dont_copy_dedents_in_beginning(differ):
- code1 = dedent('''\
- a
- 4
- ''')
- code2 = dedent('''\
- 1
- 2
- 3
- 4
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=1)
- def test_dont_copy_error_leaves(differ):
- code1 = dedent('''\
- def f(n):
- x
- if 2:
- 3
- ''')
- code2 = dedent('''\
- def f(n):
- def if 1:
- indent
- x
- if 2:
- 3
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1)
- def test_error_dedent_in_between(differ):
- code1 = dedent('''\
- class C:
- def f():
- a
- if something:
- x
- z
- ''')
- code2 = dedent('''\
- class C:
- def f():
- a
- dedent
- if other_thing:
- b
- if something:
- x
- z
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=2)
- def test_some_other_indentation_issues(differ):
- code1 = dedent('''\
- class C:
- x
- def f():
- ""
- copied
- a
- ''')
- code2 = dedent('''\
- try:
- de
- a
- b
- c
- d
- def f():
- ""
- copied
- a
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=0, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=1)
- def test_open_bracket_case1(differ):
- code1 = dedent('''\
- class C:
- 1
- 2 # ha
- ''')
- code2 = insert_line_into_code(code1, 2, ' [str\n')
- code3 = insert_line_into_code(code2, 4, ' str\n')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code3, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=1, parsers=1)
- def test_open_bracket_case2(differ):
- code1 = dedent('''\
- class C:
- def f(self):
- (
- b
- c
- def g(self):
- d
- ''')
- code2 = dedent('''\
- class C:
- def f(self):
- (
- b
- c
- self.
- def g(self):
- d
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=0, parsers=1, expect_error_leaves=True)
- differ.parse(code1, copies=0, parsers=1, expect_error_leaves=True)
- def test_some_weird_removals(differ):
- code1 = dedent('''\
- class C:
- 1
- ''')
- code2 = dedent('''\
- class C:
- 1
- @property
- A
- return
- # x
- omega
- ''')
- code3 = dedent('''\
- class C:
- 1
- ;
- omega
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
- differ.parse(code3, copies=1, parsers=3, expect_error_leaves=True)
- differ.parse(code1, copies=1)
- @pytest.mark.skipif(sys.version_info < (3, 5), reason="Async starts working in 3.5")
- def test_async_copy(differ):
- code1 = dedent('''\
- async def main():
- x = 3
- print(
- ''')
- code2 = dedent('''\
- async def main():
- x = 3
- print()
- ''')
- differ.initialize(code1)
- differ.parse(code2, copies=1, parsers=1)
- differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
- def test_parent_on_decorator(differ):
- code1 = dedent('''\
- class AClass:
- @decorator()
- def b_test(self):
- print("Hello")
- print("world")
- def a_test(self):
- pass''')
- code2 = dedent('''\
- class AClass:
- @decorator()
- def b_test(self):
- print("Hello")
- print("world")
- def a_test(self):
- pass''')
- differ.initialize(code1)
- module_node = differ.parse(code2, parsers=1)
- cls = module_node.children[0]
- cls_suite = cls.children[-1]
- assert len(cls_suite.children) == 3
- def test_wrong_indent_in_def(differ):
- code1 = dedent('''\
- def x():
- a
- b
- ''')
- code2 = dedent('''\
- def x():
- //
- b
- c
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1)
- def test_backslash_issue(differ):
- code1 = dedent('''
- pre = (
- '')
- after = 'instead'
- ''')
- code2 = dedent('''
- pre = (
- '')
- \\if
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=1, copies=1)
- def test_paren_with_indentation(differ):
- code1 = dedent('''
- class C:
- def f(self, fullname, path=None):
- x
- def load_module(self, fullname):
- a
- for prefix in self.search_path:
- try:
- b
- except ImportError:
- c
- else:
- raise
- def x():
- pass
- ''')
- code2 = dedent('''
- class C:
- def f(self, fullname, path=None):
- x
- (
- a
- for prefix in self.search_path:
- try:
- b
- except ImportError:
- c
- else:
- raise
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=3, copies=1)
- def test_error_dedent_in_function(differ):
- code1 = dedent('''\
- def x():
- a
- b
- c
- d
- ''')
- code2 = dedent('''\
- def x():
- a
- b
- c
- d
- e
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- def test_with_formfeed(differ):
- code1 = dedent('''\
- @bla
- async def foo():
- 1
- yield from []
- return
- return ''
- ''')
- code2 = dedent('''\
- @bla
- async def foo():
- 1
- \x0cimport
- return
- return ''
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
- def test_repeating_invalid_indent(differ):
- code1 = dedent('''\
- def foo():
- return
- @bla
- a
- def foo():
- a
- b
- c
- ''')
- code2 = dedent('''\
- def foo():
- return
- @bla
- a
- b
- c
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- def test_another_random_indent(differ):
- code1 = dedent('''\
- def foo():
- a
- b
- c
- return
- def foo():
- d
- ''')
- code2 = dedent('''\
- def foo():
- a
- c
- return
- def foo():
- d
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=3)
- def test_invalid_function(differ):
- code1 = dedent('''\
- a
- def foo():
- def foo():
- b
- ''')
- code2 = dedent('''\
- a
- def foo():
- def foo():
- b
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- def test_async_func2(differ):
- code1 = dedent('''\
- async def foo():
- return ''
- @bla
- async def foo():
- x
- ''')
- code2 = dedent('''\
- async def foo():
- return ''
- {
- @bla
- async def foo():
- x
- y
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
- def test_weird_ending(differ):
- code1 = dedent('''\
- def foo():
- a
- return
- ''')
- code2 = dedent('''\
- def foo():
- a
- nonlocal xF"""
- y"""''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- def test_nested_class(differ):
- code1 = dedent('''\
- def c():
- a = 3
- class X:
- b
- ''')
- code2 = dedent('''\
- def c():
- a = 3
- class X:
- elif
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- def test_class_with_paren_breaker(differ):
- code1 = dedent('''\
- class Grammar:
- x
- def parse():
- y
- parser(
- )
- z
- ''')
- code2 = dedent('''\
- class Grammar:
- x
- def parse():
- y
- parser(
- finally ;
- )
- z
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
- def test_byte_order_mark(differ):
- code2 = dedent('''\
- x
- \ufeff
- else :
- ''')
- differ.initialize('\n')
- differ.parse(code2, parsers=2, expect_error_leaves=True)
- code3 = dedent('''\
- \ufeff
- if:
- x
- ''')
- differ.initialize('\n')
- differ.parse(code3, parsers=2, expect_error_leaves=True)
- def test_byte_order_mark2(differ):
- code = u'\ufeff# foo'
- differ.initialize(code)
- differ.parse(code + 'x', parsers=ANY)
- def test_byte_order_mark3(differ):
- code1 = u"\ufeff#\ny\n"
- code2 = u'x\n\ufeff#\n\ufeff#\ny\n'
- differ.initialize(code1)
- differ.parse(code2, expect_error_leaves=True, parsers=ANY, copies=ANY)
- differ.parse(code1, parsers=1)
- def test_backslash_insertion(differ):
- code1 = dedent('''
- def f():
- x
- def g():
- base = "" \\
- ""
- return
- ''')
- code2 = dedent('''
- def f():
- x
- def g():
- base = "" \\
- def h():
- ""
- return
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
- differ.parse(code1, parsers=2, copies=1)
- def test_fstring_with_error_leaf(differ):
- code1 = dedent("""\
- def f():
- x
- def g():
- y
- """)
- code2 = dedent("""\
- def f():
- x
- F'''
- def g():
- y
- {a
- \x01
- """)
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- def test_yet_another_backslash(differ):
- code1 = dedent('''\
- def f():
- x
- def g():
- y
- base = "" \\
- "" % to
- return
- ''')
- code2 = dedent('''\
- def f():
- x
- def g():
- y
- base = "" \\
- \x0f
- return
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
- differ.parse(code1, parsers=ANY, copies=ANY)
- def test_backslash_before_def(differ):
- code1 = dedent('''\
- def f():
- x
- def g():
- y
- z
- ''')
- code2 = dedent('''\
- def f():
- x
- >\\
- def g():
- y
- x
- z
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
- def test_backslash_with_imports(differ):
- code1 = dedent('''\
- from x import y, \\
- ''')
- code2 = dedent('''\
- from x import y, \\
- z
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1)
- differ.parse(code1, parsers=1)
- def test_one_line_function_error_recovery(differ):
- code1 = dedent('''\
- class X:
- x
- def y(): word """
- # a
- # b
- c(self)
- ''')
- code2 = dedent('''\
- class X:
- x
- def y(): word """
- # a
- # b
- c(\x01+self)
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
- def test_one_line_property_error_recovery(differ):
- code1 = dedent('''\
- class X:
- x
- @property
- def encoding(self): True -
- return 1
- ''')
- code2 = dedent('''\
- class X:
- x
- @property
- def encoding(self): True -
- return 1
- ''')
- differ.initialize(code1)
- differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
|