123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746 |
- # -*- coding: utf-8 -*-
- from textwrap import dedent
- import logging
- 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:
- 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.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('\x1dĔBϞɛˁşʑ˳˻ȣſéÎ\x90̕ȟòwʘ\x1dĔBϞɛˁşʑ˳˻ȣſéÎ', parsers=1,
- expect_error_leaves=True)
- differ.parse('\r\r', parsers=1)
- differ.parse("˟Ę\x05À\r rúƣ@\x8a\x15r()\n", parsers=1, expect_error_leaves=True)
- differ.parse('a\ntaǁ\rGĒōns__\n\nb', parsers=1)
- 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(' 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('''\
- 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)
- 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
- ''') # noqa
- 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 ''
- ''') # noqa
- 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 = '\ufeff# foo'
- differ.initialize(code)
- differ.parse(code + 'x', parsers=ANY)
- def test_byte_order_mark3(differ):
- code1 = "\ufeff#\ny\n"
- code2 = '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)
|