Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

teyit assumes space-indented source #20

Open
nega0 opened this issue Aug 16, 2023 · 0 comments
Open

teyit assumes space-indented source #20

nega0 opened this issue Aug 16, 2023 · 0 comments

Comments

@nega0
Copy link

nega0 commented Aug 16, 2023

teyit mishandles tab-indented source. Yeah, I know, tabs...

Given the following test file:

import unittest
# indentation is tabs
class foo(unittest.TestCase):
	def testBar(self):
		print("testing")
		self.assertTrue("s" in "strings", "yay")
		print("testing done")

and the following diff against teyit.py (for illustrative purposes):

diff --git a/teyit.py b/teyit.py
index bfc9f59..a2d52aa 100644
--- a/teyit.py
+++ b/teyit.py
@@ -267,6 +267,8 @@ def rewrite_source(source, *, blacklist=frozenset()):
         return source, []
 
     original_source = source
+    print(source)
+    print("calling astparse()")
     tree = ast.parse(source)
     rewriter = _AssertRewriter(blacklist=blacklist)
     rewriter.visit(tree)
@@ -298,6 +300,7 @@ def rewrite_source(source, *, blacklist=frozenset()):
 def refactor_until_deterministic(source, blacklist=frozenset(), *, max=5):
     refactors = []
     for iteration in range(max):
+        print(f"{iteration=}")
         source, _refactors = rewrite_source(source, blacklist=blacklist)
         if len(_refactors) == 0:
             break

We get the following output

$ python3 teyit.py --show-stats t.py
iteration=0
import unittest

class foo(unittest.TestCase):
	def testBar(self):
		print("testing")
		self.assertTrue("s" in "strings", "yay")
		print("testing done")

calling astparse()
iteration=1
import unittest

class foo(unittest.TestCase):
	def testBar(self):
		print("testing")
  self.assertIn("s", "strings", "yay")
		print("testing done")

calling astparse()
Traceback (most recent call last):
  File "/Users/nega/Downloads/teyit/teyit.py", line 404, in <module>
    main()
  File "/Users/nega/Downloads/teyit/teyit.py", line 400, in main
    raise SystemExit(_refactor_files(**vars(options)))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nega/Downloads/teyit/teyit.py", line 357, in _refactor_files
    if len(refactors := _refactor_file(path)) > 0:
                        ^^^^^^^^^^^^^^^^^^^^
  File "/Users/nega/Downloads/teyit/teyit.py", line 345, in _refactor_file
    refactored_source, refactors = refactor_until_deterministic(
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nega/Downloads/teyit/teyit.py", line 304, in refactor_until_deterministic
    source, _refactors = rewrite_source(source, blacklist=blacklist)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nega/Downloads/teyit/teyit.py", line 272, in rewrite_source
    tree = ast.parse(source)
           ^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 50, in parse
    return compile(source, filename, mode, flags,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<unknown>", line 6
    self.assertIn("s", "strings", "yay")
                                        ^
IndentationError: unindent does not match any outer indentation level

It looks like teyit is replacing "tab stops" with single spaces. Indeed that replacement is in as_source(). The column offset of our node is recorded, and the new code we're injecting is then indented by that many spaces (instead of that many "indent characters"). Not being that familiar with teyit or Python's ast, I don't see a clean way of getting the "indent character" into as_source().

@nega0 nega0 changed the title teyit fails to handle tab-indented files teyit assumes space-indented source Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant