Created
September 23, 2023 19:15
-
-
Save matthew-brett/6f03bf2917b64f154a8b094a3a0faa2b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" Process .py file with nosetests assert_true etc for pytest | |
It does a fairly crude (regexp) job of taking lines nosetests lines like:: | |
yield assert_true, 1 == 2 | |
and replacing them with:: | |
assert 1 == 2 | |
suitable for pytest. | |
It will attempt to deal with multiline tests:: | |
yield assert_equal, 1 * 2 * 3, \ | |
2 * 3 | |
should become:: | |
assert (1 * 2 * 3, | |
2 * 3) | |
Use at your own risk! Check the diff! | |
""" | |
from pathlib import Path | |
from argparse import ArgumentParser, RawDescriptionHelpFormatter | |
import re | |
YIELDER = re.compile( | |
r'^(\s+)yield\s+(assert_[a-z_]+|pytest\.raises)\s*,\s*(.*)\s*\\?\s*$') | |
def proc_contents(contents): | |
state = 'search' | |
newline = '\n' if contents.endswith('\n') else '' | |
sb = '' | |
out_lines = [] | |
for line in contents.splitlines(): | |
line = line.rstrip() | |
if state == 'search': | |
if (match := YIELDER.match(line)): | |
state = 'search' | |
indent, asserter, args = match.groups() | |
if asserter.startswith('('): | |
state = 'backslashed' | |
asserter = asserter[1:] | |
elif line.endswith('\\'): | |
state = 'backslashed' | |
sb = '(' if state in ('bracketed' or 'backslashed') else '' | |
eb = '' if state == 'backslashed' else ')' | |
if asserter == 'assert_true': | |
line = f'{indent}assert {sb}{args}' | |
elif asserter == 'assert_false': | |
line = f'{indent}assert not {sb}{args}' | |
elif asserter == 'assert_equal': | |
before, after = re.split(',\s*', args, 1) | |
line = f'{indent}assert {sb}{before} == {after}' | |
elif asserter == 'pytest.raises': | |
line = f'{indent}pytest.raises({args}{eb}' | |
else: | |
line = f'{indent}{asserter}({args}{eb}' | |
elif state == 'backslashed': | |
if not line.endswith('\\'): | |
state = 'search' | |
line += ')' | |
elif state == 'bracketed': | |
if line.endswith(')'): | |
state = 'search' | |
out_lines.append(line) | |
return '\n'.join(out_lines) + newline | |
def process_py_file(py_file): | |
py_file = Path(py_file) | |
contents = py_file.read_text() | |
fixed = proc_contents(contents) | |
py_file.write_text(fixed) | |
def get_parser(): | |
parser = ArgumentParser(description=__doc__, # Usage from docstring | |
formatter_class=RawDescriptionHelpFormatter) | |
parser.add_argument('py_file', | |
help='Python filename') | |
return parser | |
def main(): | |
parser = get_parser() | |
args = parser.parse_args() | |
process_py_file(args.py_file) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment