You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.5 KiB
Python
134 lines
3.5 KiB
Python
5 years ago
|
from __future__ import print_function
|
||
|
|
||
|
import doctest
|
||
|
import functools
|
||
|
import os
|
||
|
import re
|
||
|
import sys
|
||
|
import unittest
|
||
|
|
||
|
|
||
|
|
||
|
# Ignore tracebacks: ZeroDivisionError
|
||
|
|
||
|
|
||
|
def myfunction(*_args, **_kwargs):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class RENormalizingOutputChecker(doctest.OutputChecker):
|
||
|
"""
|
||
|
Pattern-normalizing output checker. Inspired by one used in zope.testing.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, patterns):
|
||
|
self.transformers = [functools.partial(re.sub, replacement) for re, replacement in patterns]
|
||
|
|
||
|
def check_output(self, want, got, optionflags):
|
||
|
if got == want:
|
||
|
return True
|
||
|
|
||
|
for transformer in self.transformers:
|
||
|
want = transformer(want)
|
||
|
got = transformer(got)
|
||
|
|
||
|
return doctest.OutputChecker.check_output(self, want, got, optionflags)
|
||
|
|
||
|
FORBIDDEN_MODULES = set()
|
||
|
|
||
|
|
||
|
class Modules(object):
|
||
|
|
||
|
def __init__(self, allowed_modules):
|
||
|
from gevent.testing import walk_modules
|
||
|
self.allowed_modules = allowed_modules
|
||
|
self.modules = set()
|
||
|
|
||
|
for path, module in walk_modules(recursive=True):
|
||
|
self.add_module(module, path)
|
||
|
|
||
|
|
||
|
def add_module(self, name, path):
|
||
|
if self.allowed_modules and name not in self.allowed_modules:
|
||
|
return
|
||
|
if name in FORBIDDEN_MODULES:
|
||
|
return
|
||
|
self.modules.add((name, path))
|
||
|
|
||
|
def __bool__(self):
|
||
|
return bool(self.modules)
|
||
|
|
||
|
__nonzero__ = __bool__
|
||
|
|
||
|
def __iter__(self):
|
||
|
return iter(self.modules)
|
||
|
|
||
|
|
||
|
def main(): # pylint:disable=too-many-locals
|
||
|
cwd = os.getcwd()
|
||
|
# Use pure_python to get the correct module source and docstrings
|
||
|
os.environ['PURE_PYTHON'] = '1'
|
||
|
|
||
|
import gevent
|
||
|
from gevent import socket
|
||
|
|
||
|
|
||
|
from gevent.testing import util
|
||
|
from gevent.testing import sysinfo
|
||
|
|
||
|
if sysinfo.WIN:
|
||
|
FORBIDDEN_MODULES.update({
|
||
|
# Uses commands only found on posix
|
||
|
'gevent.subprocess',
|
||
|
})
|
||
|
|
||
|
try:
|
||
|
allowed_modules = sys.argv[1:]
|
||
|
sys.path.append('.')
|
||
|
|
||
|
globs = {
|
||
|
'myfunction': myfunction,
|
||
|
'gevent': gevent,
|
||
|
'socket': socket,
|
||
|
}
|
||
|
|
||
|
modules = Modules(allowed_modules)
|
||
|
|
||
|
if not modules:
|
||
|
sys.exit('No modules found matching %s' % ' '.join(allowed_modules))
|
||
|
|
||
|
suite = unittest.TestSuite()
|
||
|
checker = RENormalizingOutputChecker((
|
||
|
# Normalize subprocess.py: BSD ls is in the example, gnu ls outputs
|
||
|
# 'cannot access'
|
||
|
(re.compile(
|
||
|
"ls: cannot access 'non_existent_file': No such file or directory"),
|
||
|
"ls: non_existent_file: No such file or directory"),
|
||
|
# Python 3 bytes add a "b".
|
||
|
(re.compile(r'b(".*?")'), r"\1"),
|
||
|
(re.compile(r"b('.*?')"), r"\1"),
|
||
|
))
|
||
|
|
||
|
tests_count = 0
|
||
|
modules_count = 0
|
||
|
for m, path in sorted(modules):
|
||
|
with open(path, 'rb') as f:
|
||
|
contents = f.read()
|
||
|
if re.search(br'^\s*>>> ', contents, re.M):
|
||
|
s = doctest.DocTestSuite(m, extraglobs=globs, checker=checker)
|
||
|
test_count = len(s._tests)
|
||
|
util.log('%s (from %s): %s tests', m, path, test_count)
|
||
|
suite.addTest(s)
|
||
|
modules_count += 1
|
||
|
tests_count += test_count
|
||
|
|
||
|
util.log('Total: %s tests in %s modules', tests_count, modules_count)
|
||
|
# TODO: Pass this off to unittest.main()
|
||
|
runner = unittest.TextTestRunner(verbosity=2)
|
||
|
runner.run(suite)
|
||
|
finally:
|
||
|
os.chdir(cwd)
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|