Skip to content

Instantly share code, notes, and snippets.

@matthew-brett
Created September 23, 2023 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthew-brett/6f03bf2917b64f154a8b094a3a0faa2b to your computer and use it in GitHub Desktop.
Save matthew-brett/6f03bf2917b64f154a8b094a3a0faa2b to your computer and use it in GitHub Desktop.
#!/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