test_dump_tree.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from textwrap import dedent
  2. import pytest
  3. from parso import parse
  4. # Using star import for easier eval testing below.
  5. from parso.python.tree import * # noqa: F403
  6. from parso.tree import * # noqa: F403
  7. from parso.tree import ErrorLeaf, TypedLeaf
  8. @pytest.mark.parametrize(
  9. 'indent,expected_dump', [
  10. (None, "Module(["
  11. "Lambda(["
  12. "Keyword('lambda', (1, 0)), "
  13. "Param(["
  14. "Name('x', (1, 7), prefix=' '), "
  15. "Operator(',', (1, 8)), "
  16. "]), "
  17. "Param(["
  18. "Name('y', (1, 10), prefix=' '), "
  19. "]), "
  20. "Operator(':', (1, 11)), "
  21. "PythonNode('arith_expr', ["
  22. "Name('x', (1, 13), prefix=' '), "
  23. "Operator('+', (1, 15), prefix=' '), "
  24. "Name('y', (1, 17), prefix=' '), "
  25. "]), "
  26. "]), "
  27. "EndMarker('', (1, 18)), "
  28. "])"),
  29. (0, dedent('''\
  30. Module([
  31. Lambda([
  32. Keyword('lambda', (1, 0)),
  33. Param([
  34. Name('x', (1, 7), prefix=' '),
  35. Operator(',', (1, 8)),
  36. ]),
  37. Param([
  38. Name('y', (1, 10), prefix=' '),
  39. ]),
  40. Operator(':', (1, 11)),
  41. PythonNode('arith_expr', [
  42. Name('x', (1, 13), prefix=' '),
  43. Operator('+', (1, 15), prefix=' '),
  44. Name('y', (1, 17), prefix=' '),
  45. ]),
  46. ]),
  47. EndMarker('', (1, 18)),
  48. ])''')),
  49. (4, dedent('''\
  50. Module([
  51. Lambda([
  52. Keyword('lambda', (1, 0)),
  53. Param([
  54. Name('x', (1, 7), prefix=' '),
  55. Operator(',', (1, 8)),
  56. ]),
  57. Param([
  58. Name('y', (1, 10), prefix=' '),
  59. ]),
  60. Operator(':', (1, 11)),
  61. PythonNode('arith_expr', [
  62. Name('x', (1, 13), prefix=' '),
  63. Operator('+', (1, 15), prefix=' '),
  64. Name('y', (1, 17), prefix=' '),
  65. ]),
  66. ]),
  67. EndMarker('', (1, 18)),
  68. ])''')),
  69. ('\t', dedent('''\
  70. Module([
  71. \tLambda([
  72. \t\tKeyword('lambda', (1, 0)),
  73. \t\tParam([
  74. \t\t\tName('x', (1, 7), prefix=' '),
  75. \t\t\tOperator(',', (1, 8)),
  76. \t\t]),
  77. \t\tParam([
  78. \t\t\tName('y', (1, 10), prefix=' '),
  79. \t\t]),
  80. \t\tOperator(':', (1, 11)),
  81. \t\tPythonNode('arith_expr', [
  82. \t\t\tName('x', (1, 13), prefix=' '),
  83. \t\t\tOperator('+', (1, 15), prefix=' '),
  84. \t\t\tName('y', (1, 17), prefix=' '),
  85. \t\t]),
  86. \t]),
  87. \tEndMarker('', (1, 18)),
  88. ])''')),
  89. ]
  90. )
  91. def test_dump_parser_tree(indent, expected_dump):
  92. code = "lambda x, y: x + y"
  93. module = parse(code)
  94. assert module.dump(indent=indent) == expected_dump
  95. # Check that dumped tree can be eval'd to recover the parser tree and original code.
  96. recovered_code = eval(expected_dump).get_code()
  97. assert recovered_code == code
  98. @pytest.mark.parametrize(
  99. 'node,expected_dump,expected_code', [
  100. ( # Dump intermediate node (not top level module)
  101. parse("def foo(x, y): return x + y").children[0], dedent('''\
  102. Function([
  103. Keyword('def', (1, 0)),
  104. Name('foo', (1, 4), prefix=' '),
  105. PythonNode('parameters', [
  106. Operator('(', (1, 7)),
  107. Param([
  108. Name('x', (1, 8)),
  109. Operator(',', (1, 9)),
  110. ]),
  111. Param([
  112. Name('y', (1, 11), prefix=' '),
  113. ]),
  114. Operator(')', (1, 12)),
  115. ]),
  116. Operator(':', (1, 13)),
  117. ReturnStmt([
  118. Keyword('return', (1, 15), prefix=' '),
  119. PythonNode('arith_expr', [
  120. Name('x', (1, 22), prefix=' '),
  121. Operator('+', (1, 24), prefix=' '),
  122. Name('y', (1, 26), prefix=' '),
  123. ]),
  124. ]),
  125. ])'''),
  126. "def foo(x, y): return x + y",
  127. ),
  128. ( # Dump leaf
  129. parse("def foo(x, y): return x + y").children[0].children[0],
  130. "Keyword('def', (1, 0))",
  131. 'def',
  132. ),
  133. ( # Dump ErrorLeaf
  134. ErrorLeaf('error_type', 'error_code', (1, 1), prefix=' '),
  135. "ErrorLeaf('error_type', 'error_code', (1, 1), prefix=' ')",
  136. ' error_code',
  137. ),
  138. ( # Dump TypedLeaf
  139. TypedLeaf('type', 'value', (1, 1)),
  140. "TypedLeaf('type', 'value', (1, 1))",
  141. 'value',
  142. ),
  143. ]
  144. )
  145. def test_dump_parser_tree_not_top_level_module(node, expected_dump, expected_code):
  146. dump_result = node.dump()
  147. assert dump_result == expected_dump
  148. # Check that dumped tree can be eval'd to recover the parser tree and original code.
  149. recovered_code = eval(dump_result).get_code()
  150. assert recovered_code == expected_code
  151. def test_dump_parser_tree_invalid_args():
  152. module = parse("lambda x, y: x + y")
  153. with pytest.raises(TypeError):
  154. module.dump(indent=1.1)
  155. def test_eval_dump_recovers_parent():
  156. module = parse("lambda x, y: x + y")
  157. module2 = eval(module.dump())
  158. assert module2.parent is None
  159. lambda_node = module2.children[0]
  160. assert lambda_node.parent is module2
  161. assert module2.children[1].parent is module2
  162. assert lambda_node.children[0].parent is lambda_node
  163. param_node = lambda_node.children[1]
  164. assert param_node.parent is lambda_node
  165. assert param_node.children[0].parent is param_node
  166. assert param_node.children[1].parent is param_node
  167. arith_expr_node = lambda_node.children[-1]
  168. assert arith_expr_node.parent is lambda_node
  169. assert arith_expr_node.children[0].parent is arith_expr_node