blob: 5371aec9fd88d7b896f89f981141ae7c438f8892 [file] [log] [blame]
#!/usr/bin/env vpython3
# Copyright 2018 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
"""General tests during the python3 transition."""
import ast
import difflib
import linecache
import os
import unittest
import warnings
from lib2to3 import refactor
from libfuturize.fixes import (lib2to3_fix_names_stage1,
libfuturize_fix_names_stage1)
import test_env
def _py_files():
for (dirpath, dirnames, filenames) in os.walk(test_env.ROOT_DIR):
try:
dirnames.remove('.recipe_deps')
except ValueError:
pass
yield from (
os.path.join(dirpath, n)
for n in filenames
if n.endswith('.py')
)
class _2to3TestTool(refactor.RefactoringTool):
def __init__(self, test_fail, *args, **kwargs):
self.test_fail = test_fail
super().__init__(*args, **kwargs)
@staticmethod
def diff_texts(a, b, filename):
"""Return a unified diff of two strings."""
a = a.splitlines()
b = b.splitlines()
return difflib.unified_diff(
a, b, filename, filename,
"(original)", "(refactored)",
lineterm="")
def print_output(self, old_text, new_text, filename, equal):
if equal:
return
self.test_fail('\n' + '\n'.join(self.diff_texts(
old_text, new_text, filename)))
class Py3Syntax(unittest.TestCase):
def test_python3_syntax(self):
for fname in _py_files():
with self.subTest(fname=fname):
with open(fname) as sourcef:
with warnings.catch_warnings(record=True) as warn_msgs:
ast.parse(sourcef.read(), fname, type_comments=True,
feature_version=(3, 8))
if warn_msgs:
fmt = 'line {msg.lineno}: {category}: {msg.message}\n {line}'
self.fail('\n' + '\n'.join(
fmt.format(
msg=msg,
category=msg.category.__name__,
line=linecache.getline(msg.filename, msg.lineno)
) for msg in warn_msgs
))
def test_futurize_stage1(self):
avail_fixes = lib2to3_fix_names_stage1 | libfuturize_fix_names_stage1
tool = _2to3TestTool(self.fail, avail_fixes)
for fname in _py_files():
with self.subTest(fname=fname):
with open(fname) as f:
data = f.read()
if '#py3Only\n' in data:
continue # this file has marked itself as python3-only compatible.
# extra newline is cargo-culted from tool.refactor_file.
tool.refactor_string(data+'\n', fname)
if __name__ == '__main__':
test_env.main()