test_diff_parser.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. # -*- coding: utf-8 -*-
  2. from textwrap import dedent
  3. import logging
  4. import pytest
  5. from parso.utils import split_lines
  6. from parso import cache
  7. from parso import load_grammar
  8. from parso.python.diff import DiffParser, _assert_valid_graph, _assert_nodes_are_equal
  9. from parso import parse
  10. ANY = object()
  11. def test_simple():
  12. """
  13. The diff parser reuses modules. So check for that.
  14. """
  15. grammar = load_grammar()
  16. module_a = grammar.parse('a', diff_cache=True)
  17. assert grammar.parse('b', diff_cache=True) == module_a
  18. def _check_error_leaves_nodes(node):
  19. if node.type in ('error_leaf', 'error_node'):
  20. return node
  21. try:
  22. children = node.children
  23. except AttributeError:
  24. pass
  25. else:
  26. for child in children:
  27. x_node = _check_error_leaves_nodes(child)
  28. if x_node is not None:
  29. return x_node
  30. return None
  31. class Differ:
  32. grammar = load_grammar()
  33. def initialize(self, code):
  34. logging.debug('differ: initialize')
  35. try:
  36. del cache.parser_cache[self.grammar._hashed][None]
  37. except KeyError:
  38. pass
  39. self.lines = split_lines(code, keepends=True)
  40. self.module = parse(code, diff_cache=True, cache=True)
  41. assert code == self.module.get_code()
  42. _assert_valid_graph(self.module)
  43. return self.module
  44. def parse(self, code, copies=0, parsers=0, expect_error_leaves=False):
  45. logging.debug('differ: parse copies=%s parsers=%s', copies, parsers)
  46. lines = split_lines(code, keepends=True)
  47. diff_parser = DiffParser(
  48. self.grammar._pgen_grammar,
  49. self.grammar._tokenizer,
  50. self.module,
  51. )
  52. new_module = diff_parser.update(self.lines, lines)
  53. self.lines = lines
  54. assert code == new_module.get_code()
  55. _assert_valid_graph(new_module)
  56. without_diff_parser_module = parse(code)
  57. _assert_nodes_are_equal(new_module, without_diff_parser_module)
  58. error_node = _check_error_leaves_nodes(new_module)
  59. assert expect_error_leaves == (error_node is not None), error_node
  60. if parsers is not ANY:
  61. assert diff_parser._parser_count == parsers
  62. if copies is not ANY:
  63. assert diff_parser._copy_count == copies
  64. return new_module
  65. @pytest.fixture()
  66. def differ():
  67. return Differ()
  68. def test_change_and_undo(differ):
  69. func_before = 'def func():\n pass\n'
  70. # Parse the function and a.
  71. differ.initialize(func_before + 'a')
  72. # Parse just b.
  73. differ.parse(func_before + 'b', copies=1, parsers=2)
  74. # b has changed to a again, so parse that.
  75. differ.parse(func_before + 'a', copies=1, parsers=2)
  76. # Same as before parsers should not be used. Just a simple copy.
  77. differ.parse(func_before + 'a', copies=1)
  78. # Now that we have a newline at the end, everything is easier in Python
  79. # syntax, we can parse once and then get a copy.
  80. differ.parse(func_before + 'a\n', copies=1, parsers=2)
  81. differ.parse(func_before + 'a\n', copies=1)
  82. # Getting rid of an old parser: Still no parsers used.
  83. differ.parse('a\n', copies=1)
  84. # Now the file has completely changed and we need to parse.
  85. differ.parse('b\n', parsers=1)
  86. # And again.
  87. differ.parse('a\n', parsers=1)
  88. def test_positions(differ):
  89. func_before = 'class A:\n pass\n'
  90. m = differ.initialize(func_before + 'a')
  91. assert m.start_pos == (1, 0)
  92. assert m.end_pos == (3, 1)
  93. m = differ.parse('a', copies=1)
  94. assert m.start_pos == (1, 0)
  95. assert m.end_pos == (1, 1)
  96. m = differ.parse('a\n\n', parsers=1)
  97. assert m.end_pos == (3, 0)
  98. m = differ.parse('a\n\n ', copies=1, parsers=2)
  99. assert m.end_pos == (3, 1)
  100. m = differ.parse('a ', parsers=1)
  101. assert m.end_pos == (1, 2)
  102. def test_if_simple(differ):
  103. src = dedent('''\
  104. if 1:
  105. a = 3
  106. ''')
  107. else_ = "else:\n a = ''\n"
  108. differ.initialize(src + 'a')
  109. differ.parse(src + else_ + "a", copies=0, parsers=1)
  110. differ.parse(else_, parsers=2, expect_error_leaves=True)
  111. differ.parse(src + else_, parsers=1)
  112. def test_func_with_for_and_comment(differ):
  113. # The first newline is important, leave it. It should not trigger another
  114. # parser split.
  115. src = dedent("""\
  116. def func():
  117. pass
  118. for a in [1]:
  119. # COMMENT
  120. a""")
  121. differ.initialize(src)
  122. differ.parse('a\n' + src, copies=1, parsers=3)
  123. def test_one_statement_func(differ):
  124. src = dedent("""\
  125. first
  126. def func(): a
  127. """)
  128. differ.initialize(src + 'second')
  129. differ.parse(src + 'def second():\n a', parsers=1, copies=1)
  130. def test_for_on_one_line(differ):
  131. src = dedent("""\
  132. foo = 1
  133. for x in foo: pass
  134. def hi():
  135. pass
  136. """)
  137. differ.initialize(src)
  138. src = dedent("""\
  139. def hi():
  140. for x in foo: pass
  141. pass
  142. pass
  143. """)
  144. differ.parse(src, parsers=2)
  145. src = dedent("""\
  146. def hi():
  147. for x in foo: pass
  148. pass
  149. def nested():
  150. pass
  151. """)
  152. # The second parser is for parsing the `def nested()` which is an `equal`
  153. # operation in the SequenceMatcher.
  154. differ.parse(src, parsers=1, copies=1)
  155. def test_open_parentheses(differ):
  156. func = 'def func():\n a\n'
  157. code = 'isinstance(\n\n' + func
  158. new_code = 'isinstance(\n' + func
  159. differ.initialize(code)
  160. differ.parse(new_code, parsers=1, expect_error_leaves=True)
  161. new_code = 'a = 1\n' + new_code
  162. differ.parse(new_code, parsers=2, expect_error_leaves=True)
  163. func += 'def other_func():\n pass\n'
  164. differ.initialize('isinstance(\n' + func)
  165. # Cannot copy all, because the prefix of the function is once a newline and
  166. # once not.
  167. differ.parse('isinstance()\n' + func, parsers=2, copies=1)
  168. def test_open_parentheses_at_end(differ):
  169. code = "a['"
  170. differ.initialize(code)
  171. differ.parse(code, parsers=1, expect_error_leaves=True)
  172. def test_backslash(differ):
  173. src = dedent(r"""
  174. a = 1\
  175. if 1 else 2
  176. def x():
  177. pass
  178. """)
  179. differ.initialize(src)
  180. src = dedent(r"""
  181. def x():
  182. a = 1\
  183. if 1 else 2
  184. def y():
  185. pass
  186. """)
  187. differ.parse(src, parsers=1)
  188. src = dedent(r"""
  189. def first():
  190. if foo \
  191. and bar \
  192. or baz:
  193. pass
  194. def second():
  195. pass
  196. """)
  197. differ.parse(src, parsers=2)
  198. def test_full_copy(differ):
  199. code = 'def foo(bar, baz):\n pass\n bar'
  200. differ.initialize(code)
  201. differ.parse(code, copies=1)
  202. def test_wrong_whitespace(differ):
  203. code = '''
  204. hello
  205. '''
  206. differ.initialize(code)
  207. differ.parse(code + 'bar\n ', parsers=2, expect_error_leaves=True)
  208. code += """abc(\npass\n """
  209. differ.parse(code, parsers=2, expect_error_leaves=True)
  210. def test_issues_with_error_leaves(differ):
  211. code = dedent('''
  212. def ints():
  213. str..
  214. str
  215. ''')
  216. code2 = dedent('''
  217. def ints():
  218. str.
  219. str
  220. ''')
  221. differ.initialize(code)
  222. differ.parse(code2, parsers=1, expect_error_leaves=True)
  223. def test_unfinished_nodes(differ):
  224. code = dedent('''
  225. class a():
  226. def __init__(self, a):
  227. self.a = a
  228. def p(self):
  229. a(1)
  230. ''')
  231. code2 = dedent('''
  232. class a():
  233. def __init__(self, a):
  234. self.a = a
  235. def p(self):
  236. self
  237. a(1)
  238. ''')
  239. differ.initialize(code)
  240. differ.parse(code2, parsers=2, copies=2)
  241. def test_nested_if_and_scopes(differ):
  242. code = dedent('''
  243. class a():
  244. if 1:
  245. def b():
  246. 2
  247. ''')
  248. code2 = code + ' else:\n 3'
  249. differ.initialize(code)
  250. differ.parse(code2, parsers=1, copies=0)
  251. def test_word_before_def(differ):
  252. code1 = 'blub def x():\n'
  253. code2 = code1 + ' s'
  254. differ.initialize(code1)
  255. differ.parse(code2, parsers=1, copies=0, expect_error_leaves=True)
  256. def test_classes_with_error_leaves(differ):
  257. code1 = dedent('''
  258. class X():
  259. def x(self):
  260. blablabla
  261. assert 3
  262. self.
  263. class Y():
  264. pass
  265. ''')
  266. code2 = dedent('''
  267. class X():
  268. def x(self):
  269. blablabla
  270. assert 3
  271. str(
  272. class Y():
  273. pass
  274. ''')
  275. differ.initialize(code1)
  276. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  277. def test_totally_wrong_whitespace(differ):
  278. code1 = '''
  279. class X():
  280. raise n
  281. class Y():
  282. pass
  283. '''
  284. code2 = '''
  285. class X():
  286. raise n
  287. str(
  288. class Y():
  289. pass
  290. '''
  291. differ.initialize(code1)
  292. differ.parse(code2, parsers=2, copies=0, expect_error_leaves=True)
  293. def test_node_insertion(differ):
  294. code1 = dedent('''
  295. class X():
  296. def y(self):
  297. a = 1
  298. b = 2
  299. c = 3
  300. d = 4
  301. ''')
  302. code2 = dedent('''
  303. class X():
  304. def y(self):
  305. a = 1
  306. b = 2
  307. str
  308. c = 3
  309. d = 4
  310. ''')
  311. differ.initialize(code1)
  312. differ.parse(code2, parsers=1, copies=2)
  313. def test_whitespace_at_end(differ):
  314. code = dedent('str\n\n')
  315. differ.initialize(code)
  316. differ.parse(code + '\n', parsers=1, copies=1)
  317. def test_endless_while_loop(differ):
  318. """
  319. This was a bug in Jedi #878.
  320. """
  321. code = '#dead'
  322. differ.initialize(code)
  323. module = differ.parse(code, parsers=1)
  324. assert module.end_pos == (1, 5)
  325. code = '#dead\n'
  326. differ.initialize(code)
  327. module = differ.parse(code + '\n', parsers=1)
  328. assert module.end_pos == (3, 0)
  329. def test_in_class_movements(differ):
  330. code1 = dedent("""\
  331. class PlaybookExecutor:
  332. p
  333. b
  334. def run(self):
  335. 1
  336. try:
  337. x
  338. except:
  339. pass
  340. """)
  341. code2 = dedent("""\
  342. class PlaybookExecutor:
  343. b
  344. def run(self):
  345. 1
  346. try:
  347. x
  348. except:
  349. pass
  350. """)
  351. differ.initialize(code1)
  352. differ.parse(code2, parsers=1)
  353. def test_in_parentheses_newlines(differ):
  354. code1 = dedent("""
  355. x = str(
  356. True)
  357. a = 1
  358. def foo():
  359. pass
  360. b = 2""")
  361. code2 = dedent("""
  362. x = str(True)
  363. a = 1
  364. def foo():
  365. pass
  366. b = 2""")
  367. differ.initialize(code1)
  368. differ.parse(code2, parsers=1, copies=1)
  369. def test_indentation_issue(differ):
  370. code1 = dedent("""
  371. import module
  372. """)
  373. code2 = dedent("""
  374. class L1:
  375. class L2:
  376. class L3:
  377. def f(): pass
  378. def f(): pass
  379. def f(): pass
  380. def f(): pass
  381. """)
  382. differ.initialize(code1)
  383. differ.parse(code2, parsers=2)
  384. def test_endmarker_newline(differ):
  385. code1 = dedent('''\
  386. docu = None
  387. # some comment
  388. result = codet
  389. incomplete_dctassign = {
  390. "module"
  391. if "a":
  392. x = 3 # asdf
  393. ''')
  394. code2 = code1.replace('codet', 'coded')
  395. differ.initialize(code1)
  396. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  397. def test_newlines_at_end(differ):
  398. differ.initialize('a\n\n')
  399. differ.parse('a\n', copies=1)
  400. def test_end_newline_with_decorator(differ):
  401. code = dedent('''\
  402. @staticmethod
  403. def spam():
  404. import json
  405. json.l''')
  406. differ.initialize(code)
  407. module = differ.parse(code + '\n', copies=1, parsers=1)
  408. decorated, endmarker = module.children
  409. assert decorated.type == 'decorated'
  410. decorator, func = decorated.children
  411. suite = func.children[-1]
  412. assert suite.type == 'suite'
  413. newline, first_stmt, second_stmt = suite.children
  414. assert first_stmt.get_code() == ' import json\n'
  415. assert second_stmt.get_code() == ' json.l\n'
  416. def test_invalid_to_valid_nodes(differ):
  417. code1 = dedent('''\
  418. def a():
  419. foo = 3
  420. def b():
  421. la = 3
  422. else:
  423. la
  424. return
  425. foo
  426. base
  427. ''')
  428. code2 = dedent('''\
  429. def a():
  430. foo = 3
  431. def b():
  432. la = 3
  433. if foo:
  434. latte = 3
  435. else:
  436. la
  437. return
  438. foo
  439. base
  440. ''')
  441. differ.initialize(code1)
  442. differ.parse(code2, parsers=1, copies=3)
  443. def test_if_removal_and_reappearence(differ):
  444. code1 = dedent('''\
  445. la = 3
  446. if foo:
  447. latte = 3
  448. else:
  449. la
  450. pass
  451. ''')
  452. code2 = dedent('''\
  453. la = 3
  454. latte = 3
  455. else:
  456. la
  457. pass
  458. ''')
  459. code3 = dedent('''\
  460. la = 3
  461. if foo:
  462. latte = 3
  463. else:
  464. la
  465. ''')
  466. differ.initialize(code1)
  467. differ.parse(code2, parsers=3, copies=2, expect_error_leaves=True)
  468. differ.parse(code1, parsers=1, copies=1)
  469. differ.parse(code3, parsers=1, copies=1)
  470. def test_add_error_indentation(differ):
  471. code = 'if x:\n 1\n'
  472. differ.initialize(code)
  473. differ.parse(code + ' 2\n', parsers=1, copies=0, expect_error_leaves=True)
  474. def test_differing_docstrings(differ):
  475. code1 = dedent('''\
  476. def foobar(x, y):
  477. 1
  478. return x
  479. def bazbiz():
  480. foobar()
  481. lala
  482. ''')
  483. code2 = dedent('''\
  484. def foobar(x, y):
  485. 2
  486. return x + y
  487. def bazbiz():
  488. z = foobar()
  489. lala
  490. ''')
  491. differ.initialize(code1)
  492. differ.parse(code2, parsers=2, copies=1)
  493. differ.parse(code1, parsers=2, copies=1)
  494. def test_one_call_in_function_change(differ):
  495. code1 = dedent('''\
  496. def f(self):
  497. mro = [self]
  498. for a in something:
  499. yield a
  500. def g(self):
  501. return C(
  502. a=str,
  503. b=self,
  504. )
  505. ''')
  506. code2 = dedent('''\
  507. def f(self):
  508. mro = [self]
  509. def g(self):
  510. return C(
  511. a=str,
  512. t
  513. b=self,
  514. )
  515. ''')
  516. differ.initialize(code1)
  517. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  518. differ.parse(code1, parsers=2, copies=1)
  519. def test_function_deletion(differ):
  520. code1 = dedent('''\
  521. class C(list):
  522. def f(self):
  523. def iterate():
  524. for x in b:
  525. break
  526. return list(iterate())
  527. ''')
  528. code2 = dedent('''\
  529. class C():
  530. def f(self):
  531. for x in b:
  532. break
  533. return list(iterate())
  534. ''')
  535. differ.initialize(code1)
  536. differ.parse(code2, parsers=1, copies=0, expect_error_leaves=True)
  537. differ.parse(code1, parsers=1, copies=0)
  538. def test_docstring_removal(differ):
  539. code1 = dedent('''\
  540. class E(Exception):
  541. """
  542. 1
  543. 2
  544. 3
  545. """
  546. class S(object):
  547. @property
  548. def f(self):
  549. return cmd
  550. def __repr__(self):
  551. return cmd2
  552. ''')
  553. code2 = dedent('''\
  554. class E(Exception):
  555. """
  556. 1
  557. 3
  558. """
  559. class S(object):
  560. @property
  561. def f(self):
  562. return cmd
  563. return cmd2
  564. ''')
  565. differ.initialize(code1)
  566. differ.parse(code2, parsers=1, copies=2)
  567. differ.parse(code1, parsers=3, copies=1)
  568. def test_paren_in_strange_position(differ):
  569. code1 = dedent('''\
  570. class C:
  571. """ ha """
  572. def __init__(self, message):
  573. self.message = message
  574. ''')
  575. code2 = dedent('''\
  576. class C:
  577. """ ha """
  578. )
  579. def __init__(self, message):
  580. self.message = message
  581. ''')
  582. differ.initialize(code1)
  583. differ.parse(code2, parsers=1, copies=2, expect_error_leaves=True)
  584. differ.parse(code1, parsers=0, copies=2)
  585. def insert_line_into_code(code, index, line):
  586. lines = split_lines(code, keepends=True)
  587. lines.insert(index, line)
  588. return ''.join(lines)
  589. def test_paren_before_docstring(differ):
  590. code1 = dedent('''\
  591. # comment
  592. """
  593. The
  594. """
  595. from parso import tree
  596. from parso import python
  597. ''')
  598. code2 = insert_line_into_code(code1, 1, ' ' * 16 + 'raise InternalParseError(\n')
  599. differ.initialize(code1)
  600. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  601. differ.parse(code1, parsers=2, copies=1)
  602. def test_parentheses_before_method(differ):
  603. code1 = dedent('''\
  604. class A:
  605. def a(self):
  606. pass
  607. class B:
  608. def b(self):
  609. if 1:
  610. pass
  611. ''')
  612. code2 = dedent('''\
  613. class A:
  614. def a(self):
  615. pass
  616. Exception.__init__(self, "x" %
  617. def b(self):
  618. if 1:
  619. pass
  620. ''')
  621. differ.initialize(code1)
  622. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  623. differ.parse(code1, parsers=2, copies=1)
  624. def test_indentation_issues(differ):
  625. code1 = dedent('''\
  626. class C:
  627. def f():
  628. 1
  629. if 2:
  630. return 3
  631. def g():
  632. to_be_removed
  633. pass
  634. ''')
  635. code2 = dedent('''\
  636. class C:
  637. def f():
  638. 1
  639. ``something``, very ``weird``).
  640. if 2:
  641. return 3
  642. def g():
  643. to_be_removed
  644. pass
  645. ''')
  646. code3 = dedent('''\
  647. class C:
  648. def f():
  649. 1
  650. if 2:
  651. return 3
  652. def g():
  653. pass
  654. ''')
  655. differ.initialize(code1)
  656. differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
  657. differ.parse(code1, copies=1, parsers=2)
  658. differ.parse(code3, parsers=2, copies=1)
  659. differ.parse(code1, parsers=2, copies=1)
  660. def test_error_dedent_issues(differ):
  661. code1 = dedent('''\
  662. while True:
  663. try:
  664. 1
  665. except KeyError:
  666. if 2:
  667. 3
  668. except IndexError:
  669. 4
  670. 5
  671. ''')
  672. code2 = dedent('''\
  673. while True:
  674. try:
  675. except KeyError:
  676. 1
  677. except KeyError:
  678. if 2:
  679. 3
  680. except IndexError:
  681. 4
  682. something_inserted
  683. 5
  684. ''')
  685. differ.initialize(code1)
  686. differ.parse(code2, parsers=3, copies=0, expect_error_leaves=True)
  687. differ.parse(code1, parsers=1, copies=0)
  688. def test_random_text_insertion(differ):
  689. code1 = dedent('''\
  690. class C:
  691. def f():
  692. return node
  693. def g():
  694. try:
  695. 1
  696. except KeyError:
  697. 2
  698. ''')
  699. code2 = dedent('''\
  700. class C:
  701. def f():
  702. return node
  703. Some'random text: yeah
  704. for push in plan.dfa_pushes:
  705. def g():
  706. try:
  707. 1
  708. except KeyError:
  709. 2
  710. ''')
  711. differ.initialize(code1)
  712. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  713. differ.parse(code1, parsers=2, copies=1)
  714. def test_many_nested_ifs(differ):
  715. code1 = dedent('''\
  716. class C:
  717. def f(self):
  718. def iterate():
  719. if 1:
  720. yield t
  721. else:
  722. yield
  723. return
  724. def g():
  725. 3
  726. ''')
  727. code2 = dedent('''\
  728. def f(self):
  729. def iterate():
  730. if 1:
  731. yield t
  732. hahahaha
  733. if 2:
  734. else:
  735. yield
  736. return
  737. def g():
  738. 3
  739. ''')
  740. differ.initialize(code1)
  741. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  742. differ.parse(code1, parsers=1, copies=1)
  743. @pytest.mark.parametrize('prefix', ['', 'async '])
  744. def test_with_and_funcdef_in_call(differ, prefix):
  745. code1 = prefix + dedent('''\
  746. with x:
  747. la = C(
  748. a=1,
  749. b=2,
  750. c=3,
  751. )
  752. ''')
  753. code2 = insert_line_into_code(code1, 3, 'def y(self, args):\n')
  754. differ.initialize(code1)
  755. differ.parse(code2, parsers=1, expect_error_leaves=True)
  756. differ.parse(code1, parsers=1)
  757. def test_wrong_backslash(differ):
  758. code1 = dedent('''\
  759. def y():
  760. 1
  761. for x in y:
  762. continue
  763. ''')
  764. code2 = insert_line_into_code(code1, 3, '\\.whl$\n')
  765. differ.initialize(code1)
  766. differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
  767. differ.parse(code1, parsers=1, copies=1)
  768. def test_random_unicode_characters(differ):
  769. """
  770. Those issues were all found with the fuzzer.
  771. """
  772. differ.initialize('')
  773. differ.parse('\x1dĔBϞɛˁşʑ˳˻ȣſéÎ\x90̕ȟòwʘ\x1dĔBϞɛˁşʑ˳˻ȣſéÎ', parsers=1,
  774. expect_error_leaves=True)
  775. differ.parse('\r\r', parsers=1)
  776. differ.parse("˟Ę\x05À\r rúƣ@\x8a\x15r()\n", parsers=1, expect_error_leaves=True)
  777. differ.parse('a\ntaǁ\rGĒōns__\n\nb', parsers=1)
  778. s = ' if not (self, "_fi\x02\x0e\x08\n\nle"):'
  779. differ.parse(s, parsers=1, expect_error_leaves=True)
  780. differ.parse('')
  781. differ.parse(s + '\n', parsers=1, expect_error_leaves=True)
  782. differ.parse(' result = (\r\f\x17\t\x11res)', parsers=1, expect_error_leaves=True)
  783. differ.parse('')
  784. differ.parse(' a( # xx\ndef', parsers=1, expect_error_leaves=True)
  785. def test_dedent_end_positions(differ):
  786. code1 = dedent('''\
  787. if 1:
  788. if b:
  789. 2
  790. c = {
  791. 5}
  792. ''')
  793. code2 = dedent('''\
  794. if 1:
  795. if ⌟ഒᜈྡྷṭb:
  796. 2
  797. 'l': ''}
  798. c = {
  799. 5}
  800. ''')
  801. differ.initialize(code1)
  802. differ.parse(code2, parsers=1, expect_error_leaves=True)
  803. differ.parse(code1, parsers=1)
  804. def test_special_no_newline_ending(differ):
  805. code1 = dedent('''\
  806. 1
  807. ''')
  808. code2 = dedent('''\
  809. 1
  810. is ''')
  811. differ.initialize(code1)
  812. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  813. differ.parse(code1, copies=1, parsers=0)
  814. def test_random_character_insertion(differ):
  815. code1 = dedent('''\
  816. def create(self):
  817. 1
  818. if self.path is not None:
  819. return
  820. # 3
  821. # 4
  822. ''')
  823. code2 = dedent('''\
  824. def create(self):
  825. 1
  826. if 2:
  827. x return
  828. # 3
  829. # 4
  830. ''')
  831. differ.initialize(code1)
  832. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  833. differ.parse(code1, copies=1, parsers=1)
  834. def test_import_opening_bracket(differ):
  835. code1 = dedent('''\
  836. 1
  837. 2
  838. from bubu import (X,
  839. ''')
  840. code2 = dedent('''\
  841. 11
  842. 2
  843. from bubu import (X,
  844. ''')
  845. differ.initialize(code1)
  846. differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
  847. differ.parse(code1, copies=1, parsers=2, expect_error_leaves=True)
  848. def test_opening_bracket_at_end(differ):
  849. code1 = dedent('''\
  850. class C:
  851. 1
  852. [
  853. ''')
  854. code2 = dedent('''\
  855. 3
  856. class C:
  857. 1
  858. [
  859. ''')
  860. differ.initialize(code1)
  861. differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
  862. differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
  863. def test_all_sorts_of_indentation(differ):
  864. code1 = dedent('''\
  865. class C:
  866. 1
  867. def f():
  868. 'same'
  869. if foo:
  870. a = b
  871. end
  872. ''')
  873. code2 = dedent('''\
  874. class C:
  875. 1
  876. def f(yield await %|(
  877. 'same'
  878. \x02\x06\x0f\x1c\x11
  879. if foo:
  880. a = b
  881. end
  882. ''')
  883. differ.initialize(code1)
  884. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  885. differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
  886. code3 = dedent('''\
  887. if 1:
  888. a
  889. b
  890. c
  891. d
  892. \x00
  893. ''')
  894. differ.parse(code3, parsers=1, expect_error_leaves=True)
  895. differ.parse('')
  896. def test_dont_copy_dedents_in_beginning(differ):
  897. code1 = dedent('''\
  898. a
  899. 4
  900. ''')
  901. code2 = dedent('''\
  902. 1
  903. 2
  904. 3
  905. 4
  906. ''')
  907. differ.initialize(code1)
  908. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  909. differ.parse(code1, parsers=1, copies=1)
  910. def test_dont_copy_error_leaves(differ):
  911. code1 = dedent('''\
  912. def f(n):
  913. x
  914. if 2:
  915. 3
  916. ''')
  917. code2 = dedent('''\
  918. def f(n):
  919. def if 1:
  920. indent
  921. x
  922. if 2:
  923. 3
  924. ''')
  925. differ.initialize(code1)
  926. differ.parse(code2, parsers=1, expect_error_leaves=True)
  927. differ.parse(code1, parsers=1)
  928. def test_error_dedent_in_between(differ):
  929. code1 = dedent('''\
  930. class C:
  931. def f():
  932. a
  933. if something:
  934. x
  935. z
  936. ''')
  937. code2 = dedent('''\
  938. class C:
  939. def f():
  940. a
  941. dedent
  942. if other_thing:
  943. b
  944. if something:
  945. x
  946. z
  947. ''')
  948. differ.initialize(code1)
  949. differ.parse(code2, copies=1, parsers=2, expect_error_leaves=True)
  950. differ.parse(code1, copies=1, parsers=2)
  951. def test_some_other_indentation_issues(differ):
  952. code1 = dedent('''\
  953. class C:
  954. x
  955. def f():
  956. ""
  957. copied
  958. a
  959. ''')
  960. code2 = dedent('''\
  961. try:
  962. de
  963. a
  964. b
  965. c
  966. d
  967. def f():
  968. ""
  969. copied
  970. a
  971. ''')
  972. differ.initialize(code1)
  973. differ.parse(code2, copies=0, parsers=1, expect_error_leaves=True)
  974. differ.parse(code1, copies=1, parsers=1)
  975. def test_open_bracket_case1(differ):
  976. code1 = dedent('''\
  977. class C:
  978. 1
  979. 2 # ha
  980. ''')
  981. code2 = insert_line_into_code(code1, 2, ' [str\n')
  982. code3 = insert_line_into_code(code2, 4, ' str\n')
  983. differ.initialize(code1)
  984. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  985. differ.parse(code3, copies=1, parsers=1, expect_error_leaves=True)
  986. differ.parse(code1, copies=1, parsers=1)
  987. def test_open_bracket_case2(differ):
  988. code1 = dedent('''\
  989. class C:
  990. def f(self):
  991. (
  992. b
  993. c
  994. def g(self):
  995. d
  996. ''')
  997. code2 = dedent('''\
  998. class C:
  999. def f(self):
  1000. (
  1001. b
  1002. c
  1003. self.
  1004. def g(self):
  1005. d
  1006. ''')
  1007. differ.initialize(code1)
  1008. differ.parse(code2, copies=0, parsers=1, expect_error_leaves=True)
  1009. differ.parse(code1, copies=0, parsers=1, expect_error_leaves=True)
  1010. def test_some_weird_removals(differ):
  1011. code1 = dedent('''\
  1012. class C:
  1013. 1
  1014. ''')
  1015. code2 = dedent('''\
  1016. class C:
  1017. 1
  1018. @property
  1019. A
  1020. return
  1021. # x
  1022. omega
  1023. ''')
  1024. code3 = dedent('''\
  1025. class C:
  1026. 1
  1027. ;
  1028. omega
  1029. ''')
  1030. differ.initialize(code1)
  1031. differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True)
  1032. differ.parse(code3, copies=1, parsers=3, expect_error_leaves=True)
  1033. differ.parse(code1, copies=1)
  1034. def test_async_copy(differ):
  1035. code1 = dedent('''\
  1036. async def main():
  1037. x = 3
  1038. print(
  1039. ''')
  1040. code2 = dedent('''\
  1041. async def main():
  1042. x = 3
  1043. print()
  1044. ''')
  1045. differ.initialize(code1)
  1046. differ.parse(code2, copies=1, parsers=1)
  1047. differ.parse(code1, copies=1, parsers=1, expect_error_leaves=True)
  1048. def test_parent_on_decorator(differ):
  1049. code1 = dedent('''\
  1050. class AClass:
  1051. @decorator()
  1052. def b_test(self):
  1053. print("Hello")
  1054. print("world")
  1055. def a_test(self):
  1056. pass''')
  1057. code2 = dedent('''\
  1058. class AClass:
  1059. @decorator()
  1060. def b_test(self):
  1061. print("Hello")
  1062. print("world")
  1063. def a_test(self):
  1064. pass''')
  1065. differ.initialize(code1)
  1066. module_node = differ.parse(code2, parsers=1)
  1067. cls = module_node.children[0]
  1068. cls_suite = cls.children[-1]
  1069. assert len(cls_suite.children) == 3
  1070. def test_wrong_indent_in_def(differ):
  1071. code1 = dedent('''\
  1072. def x():
  1073. a
  1074. b
  1075. ''')
  1076. code2 = dedent('''\
  1077. def x():
  1078. //
  1079. b
  1080. c
  1081. ''')
  1082. differ.initialize(code1)
  1083. differ.parse(code2, parsers=1, expect_error_leaves=True)
  1084. differ.parse(code1, parsers=1)
  1085. def test_backslash_issue(differ):
  1086. code1 = dedent('''
  1087. pre = (
  1088. '')
  1089. after = 'instead'
  1090. ''')
  1091. code2 = dedent('''
  1092. pre = (
  1093. '')
  1094. \\if
  1095. ''') # noqa
  1096. differ.initialize(code1)
  1097. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1098. differ.parse(code1, parsers=1, copies=1)
  1099. def test_paren_with_indentation(differ):
  1100. code1 = dedent('''
  1101. class C:
  1102. def f(self, fullname, path=None):
  1103. x
  1104. def load_module(self, fullname):
  1105. a
  1106. for prefix in self.search_path:
  1107. try:
  1108. b
  1109. except ImportError:
  1110. c
  1111. else:
  1112. raise
  1113. def x():
  1114. pass
  1115. ''')
  1116. code2 = dedent('''
  1117. class C:
  1118. def f(self, fullname, path=None):
  1119. x
  1120. (
  1121. a
  1122. for prefix in self.search_path:
  1123. try:
  1124. b
  1125. except ImportError:
  1126. c
  1127. else:
  1128. raise
  1129. ''')
  1130. differ.initialize(code1)
  1131. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1132. differ.parse(code1, parsers=3, copies=1)
  1133. def test_error_dedent_in_function(differ):
  1134. code1 = dedent('''\
  1135. def x():
  1136. a
  1137. b
  1138. c
  1139. d
  1140. ''')
  1141. code2 = dedent('''\
  1142. def x():
  1143. a
  1144. b
  1145. c
  1146. d
  1147. e
  1148. ''')
  1149. differ.initialize(code1)
  1150. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  1151. def test_with_formfeed(differ):
  1152. code1 = dedent('''\
  1153. @bla
  1154. async def foo():
  1155. 1
  1156. yield from []
  1157. return
  1158. return ''
  1159. ''')
  1160. code2 = dedent('''\
  1161. @bla
  1162. async def foo():
  1163. 1
  1164. \x0cimport
  1165. return
  1166. return ''
  1167. ''') # noqa
  1168. differ.initialize(code1)
  1169. differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
  1170. def test_repeating_invalid_indent(differ):
  1171. code1 = dedent('''\
  1172. def foo():
  1173. return
  1174. @bla
  1175. a
  1176. def foo():
  1177. a
  1178. b
  1179. c
  1180. ''')
  1181. code2 = dedent('''\
  1182. def foo():
  1183. return
  1184. @bla
  1185. a
  1186. b
  1187. c
  1188. ''')
  1189. differ.initialize(code1)
  1190. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  1191. def test_another_random_indent(differ):
  1192. code1 = dedent('''\
  1193. def foo():
  1194. a
  1195. b
  1196. c
  1197. return
  1198. def foo():
  1199. d
  1200. ''')
  1201. code2 = dedent('''\
  1202. def foo():
  1203. a
  1204. c
  1205. return
  1206. def foo():
  1207. d
  1208. ''')
  1209. differ.initialize(code1)
  1210. differ.parse(code2, parsers=1, copies=3)
  1211. def test_invalid_function(differ):
  1212. code1 = dedent('''\
  1213. a
  1214. def foo():
  1215. def foo():
  1216. b
  1217. ''')
  1218. code2 = dedent('''\
  1219. a
  1220. def foo():
  1221. def foo():
  1222. b
  1223. ''')
  1224. differ.initialize(code1)
  1225. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1226. def test_async_func2(differ):
  1227. code1 = dedent('''\
  1228. async def foo():
  1229. return ''
  1230. @bla
  1231. async def foo():
  1232. x
  1233. ''')
  1234. code2 = dedent('''\
  1235. async def foo():
  1236. return ''
  1237. {
  1238. @bla
  1239. async def foo():
  1240. x
  1241. y
  1242. ''')
  1243. differ.initialize(code1)
  1244. differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
  1245. def test_weird_ending(differ):
  1246. code1 = dedent('''\
  1247. def foo():
  1248. a
  1249. return
  1250. ''')
  1251. code2 = dedent('''\
  1252. def foo():
  1253. a
  1254. nonlocal xF"""
  1255. y"""''')
  1256. differ.initialize(code1)
  1257. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1258. def test_nested_class(differ):
  1259. code1 = dedent('''\
  1260. def c():
  1261. a = 3
  1262. class X:
  1263. b
  1264. ''')
  1265. code2 = dedent('''\
  1266. def c():
  1267. a = 3
  1268. class X:
  1269. elif
  1270. ''')
  1271. differ.initialize(code1)
  1272. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1273. def test_class_with_paren_breaker(differ):
  1274. code1 = dedent('''\
  1275. class Grammar:
  1276. x
  1277. def parse():
  1278. y
  1279. parser(
  1280. )
  1281. z
  1282. ''')
  1283. code2 = dedent('''\
  1284. class Grammar:
  1285. x
  1286. def parse():
  1287. y
  1288. parser(
  1289. finally ;
  1290. )
  1291. z
  1292. ''')
  1293. differ.initialize(code1)
  1294. differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
  1295. def test_byte_order_mark(differ):
  1296. code2 = dedent('''\
  1297. x
  1298. \ufeff
  1299. else :
  1300. ''')
  1301. differ.initialize('\n')
  1302. differ.parse(code2, parsers=2, expect_error_leaves=True)
  1303. code3 = dedent('''\
  1304. \ufeff
  1305. if:
  1306. x
  1307. ''')
  1308. differ.initialize('\n')
  1309. differ.parse(code3, parsers=2, expect_error_leaves=True)
  1310. def test_byte_order_mark2(differ):
  1311. code = '\ufeff# foo'
  1312. differ.initialize(code)
  1313. differ.parse(code + 'x', parsers=ANY)
  1314. def test_byte_order_mark3(differ):
  1315. code1 = "\ufeff#\ny\n"
  1316. code2 = 'x\n\ufeff#\n\ufeff#\ny\n'
  1317. differ.initialize(code1)
  1318. differ.parse(code2, expect_error_leaves=True, parsers=ANY, copies=ANY)
  1319. differ.parse(code1, parsers=1)
  1320. def test_backslash_insertion(differ):
  1321. code1 = dedent('''
  1322. def f():
  1323. x
  1324. def g():
  1325. base = "" \\
  1326. ""
  1327. return
  1328. ''')
  1329. code2 = dedent('''
  1330. def f():
  1331. x
  1332. def g():
  1333. base = "" \\
  1334. def h():
  1335. ""
  1336. return
  1337. ''')
  1338. differ.initialize(code1)
  1339. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)
  1340. differ.parse(code1, parsers=2, copies=1)
  1341. def test_fstring_with_error_leaf(differ):
  1342. code1 = dedent("""\
  1343. def f():
  1344. x
  1345. def g():
  1346. y
  1347. """)
  1348. code2 = dedent("""\
  1349. def f():
  1350. x
  1351. F'''
  1352. def g():
  1353. y
  1354. {a
  1355. \x01
  1356. """)
  1357. differ.initialize(code1)
  1358. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1359. def test_yet_another_backslash(differ):
  1360. code1 = dedent('''\
  1361. def f():
  1362. x
  1363. def g():
  1364. y
  1365. base = "" \\
  1366. "" % to
  1367. return
  1368. ''')
  1369. code2 = dedent('''\
  1370. def f():
  1371. x
  1372. def g():
  1373. y
  1374. base = "" \\
  1375. \x0f
  1376. return
  1377. ''')
  1378. differ.initialize(code1)
  1379. differ.parse(code2, parsers=ANY, copies=ANY, expect_error_leaves=True)
  1380. differ.parse(code1, parsers=ANY, copies=ANY)
  1381. def test_backslash_before_def(differ):
  1382. code1 = dedent('''\
  1383. def f():
  1384. x
  1385. def g():
  1386. y
  1387. z
  1388. ''')
  1389. code2 = dedent('''\
  1390. def f():
  1391. x
  1392. >\\
  1393. def g():
  1394. y
  1395. x
  1396. z
  1397. ''')
  1398. differ.initialize(code1)
  1399. differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
  1400. def test_backslash_with_imports(differ):
  1401. code1 = dedent('''\
  1402. from x import y, \\
  1403. ''')
  1404. code2 = dedent('''\
  1405. from x import y, \\
  1406. z
  1407. ''')
  1408. differ.initialize(code1)
  1409. differ.parse(code2, parsers=1)
  1410. differ.parse(code1, parsers=1)
  1411. def test_one_line_function_error_recovery(differ):
  1412. code1 = dedent('''\
  1413. class X:
  1414. x
  1415. def y(): word """
  1416. # a
  1417. # b
  1418. c(self)
  1419. ''')
  1420. code2 = dedent('''\
  1421. class X:
  1422. x
  1423. def y(): word """
  1424. # a
  1425. # b
  1426. c(\x01+self)
  1427. ''')
  1428. differ.initialize(code1)
  1429. differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
  1430. def test_one_line_property_error_recovery(differ):
  1431. code1 = dedent('''\
  1432. class X:
  1433. x
  1434. @property
  1435. def encoding(self): True -
  1436. return 1
  1437. ''')
  1438. code2 = dedent('''\
  1439. class X:
  1440. x
  1441. @property
  1442. def encoding(self): True -
  1443. return 1
  1444. ''')
  1445. differ.initialize(code1)
  1446. differ.parse(code2, parsers=2, copies=1, expect_error_leaves=True)