|
1 | 1 | """Top-level package for unasync."""
|
2 | 2 |
|
| 3 | +import ast |
3 | 4 | import collections
|
4 | 5 | import errno
|
5 | 6 | import os
|
@@ -68,17 +69,37 @@ def _unasync_file(self, filepath):
|
68 | 69 | encoding, _ = std_tokenize.detect_encoding(f.readline)
|
69 | 70 |
|
70 | 71 | with open(filepath, "rt", encoding=encoding) as f:
|
71 |
| - tokens = tokenize_rt.src_to_tokens(f.read()) |
72 |
| - tokens = self._unasync_tokens(tokens) |
73 |
| - result = tokenize_rt.tokens_to_src(tokens) |
74 |
| - outfilepath = filepath.replace(self.fromdir, self.todir) |
75 |
| - os.makedirs(os.path.dirname(outfilepath), exist_ok=True) |
76 |
| - with open(outfilepath, "wb") as f: |
77 |
| - f.write(result.encode(encoding)) |
78 |
| - |
79 |
| - def _unasync_tokens(self, tokens): |
| 72 | + contents = f.read() |
| 73 | + tokens = self._unasync_tokenize(contents=contents, filename=filepath) |
| 74 | + result = tokenize_rt.tokens_to_src(tokens) |
| 75 | + outfilepath = filepath.replace(self.fromdir, self.todir) |
| 76 | + os.makedirs(os.path.dirname(outfilepath), exist_ok=True) |
| 77 | + with open(outfilepath, "wb") as f: |
| 78 | + f.write(result.encode(encoding)) |
| 79 | + |
| 80 | + def _unasync_tokenize(self, contents, filename): |
| 81 | + tokens = tokenize_rt.src_to_tokens(contents) |
| 82 | + |
| 83 | + comment_lines_locations = [] |
| 84 | + for token in tokens: |
| 85 | + # find line numbers where "unasync: remove" comments are found |
| 86 | + if token.name == 'COMMENT' and 'unasync: remove' in token.src: # XXX: maybe make this a little more strict |
| 87 | + comment_lines_locations.append(token.line) |
| 88 | + |
| 89 | + lines_to_remove = set() |
| 90 | + if comment_lines_locations: # only parse ast if we actually have "unasync: remove" comments |
| 91 | + tree = ast.parse(contents, filename=filename) |
| 92 | + for node in ast.walk(tree): |
| 93 | + # find nodes whose line number (start line) intersect with unasync: remove comments |
| 94 | + if hasattr(node, 'lineno') and node.lineno in comment_lines_locations: |
| 95 | + for lineno in range(node.lineno, node.end_lineno + 1): |
| 96 | + # find all lines related to each node and mark those lines for removal |
| 97 | + lines_to_remove.add(lineno) |
| 98 | + |
80 | 99 | skip_next = False
|
81 |
| - for i, token in enumerate(tokens): |
| 100 | + for token in tokens: |
| 101 | + if token.line in lines_to_remove: |
| 102 | + continue |
82 | 103 | if skip_next:
|
83 | 104 | skip_next = False
|
84 | 105 | continue
|
|
0 commit comments