test_get_code.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import difflib
  2. import pytest
  3. from parso import parse
  4. code_basic_features = '''
  5. """A mod docstring"""
  6. def a_function(a_argument, a_default = "default"):
  7. """A func docstring"""
  8. a_result = 3 * a_argument
  9. print(a_result) # a comment
  10. b = """
  11. from
  12. to""" + "huhu"
  13. if a_default == "default":
  14. return str(a_result)
  15. else
  16. return None
  17. '''
  18. def diff_code_assert(a, b, n=4):
  19. if a != b:
  20. diff = "\n".join(difflib.unified_diff(
  21. a.splitlines(),
  22. b.splitlines(),
  23. n=n,
  24. lineterm=""
  25. ))
  26. assert False, "Code does not match:\n%s\n\ncreated code:\n%s" % (
  27. diff,
  28. b
  29. )
  30. pass
  31. def test_basic_parsing():
  32. """Validate the parsing features"""
  33. m = parse(code_basic_features)
  34. diff_code_assert(
  35. code_basic_features,
  36. m.get_code()
  37. )
  38. def test_operators():
  39. src = '5 * 3'
  40. module = parse(src)
  41. diff_code_assert(src, module.get_code())
  42. def test_get_code():
  43. """Use the same code that the parser also generates, to compare"""
  44. s = '''"""a docstring"""
  45. class SomeClass(object, mixin):
  46. def __init__(self):
  47. self.xy = 3.0
  48. """statement docstr"""
  49. def some_method(self):
  50. return 1
  51. def yield_method(self):
  52. while hasattr(self, 'xy'):
  53. yield True
  54. for x in [1, 2]:
  55. yield x
  56. def empty(self):
  57. pass
  58. class Empty:
  59. pass
  60. class WithDocstring:
  61. """class docstr"""
  62. pass
  63. def method_with_docstring():
  64. """class docstr"""
  65. pass
  66. '''
  67. assert parse(s).get_code() == s
  68. def test_end_newlines():
  69. """
  70. The Python grammar explicitly needs a newline at the end. Jedi though still
  71. wants to be able, to return the exact same code without the additional new
  72. line the parser needs.
  73. """
  74. def test(source, end_pos):
  75. module = parse(source)
  76. assert module.get_code() == source
  77. assert module.end_pos == end_pos
  78. test('a', (1, 1))
  79. test('a\n', (2, 0))
  80. test('a\nb', (2, 1))
  81. test('a\n#comment\n', (3, 0))
  82. test('a\n#comment', (2, 8))
  83. test('a#comment', (1, 9))
  84. test('def a():\n pass', (2, 5))
  85. test('def a(', (1, 6))
  86. @pytest.mark.parametrize(('code', 'types'), [
  87. ('\r', ['endmarker']),
  88. ('\n\r', ['endmarker'])
  89. ])
  90. def test_carriage_return_at_end(code, types):
  91. """
  92. By adding an artificial newline this created weird side effects for
  93. \r at the end of files.
  94. """
  95. tree = parse(code)
  96. assert tree.get_code() == code
  97. assert [c.type for c in tree.children] == types
  98. assert tree.end_pos == (len(code) + 1, 0)
  99. @pytest.mark.parametrize('code', [
  100. ' ',
  101. ' F"""',
  102. ' F"""\n',
  103. ' F""" \n',
  104. ' F""" \n3',
  105. ' f"""\n"""',
  106. ' f"""\n"""\n',
  107. ])
  108. def test_full_code_round_trip(code):
  109. assert parse(code).get_code() == code