import tokenize import io import sys import os def force_1space(path): try: with open(path, 'rb') as f: content = f.read() tokens = list(tokenize.tokenize(io.BytesIO(content).readline)) except Exception: return col_to_level = {0: 0} level = 0 for tok in tokens: if tok.type == tokenize.INDENT: level += 1 col_to_level[tok.end[1]] = level elif tok.type == tokenize.DEDENT: level -= 1 new_content = [] level = 0 last_line = -1 last_end = (1, 0) for tok in tokens: if tok.type == tokenize.ENCODING: continue if tok.type == tokenize.ENDMARKER: break if tok.type == tokenize.INDENT: level += 1 continue if tok.type == tokenize.DEDENT: level -= 1 continue if tok.start[0] > last_line: if tok.type not in (tokenize.NEWLINE, tokenize.NL): if tok.type == tokenize.COMMENT: actual_level = col_to_level.get(tok.start[1], level) else: actual_level = level new_content.append(" " * actual_level) new_content.append(tok.string) else: new_content.append(tok.string) last_line = tok.start[0] last_end = tok.end else: if tok.start[1] > last_end[1]: new_content.append(" " * (tok.start[1] - last_end[1])) new_content.append(tok.string) last_end = tok.end with open(path, 'w', encoding='utf-8') as f: f.write("".join(new_content)) if __name__ == "__main__": for arg in sys.argv[1:]: if os.path.isfile(arg): force_1space(arg)