test_diff_parser.py 38 KB

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