1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
from __future__ import print_function
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import config
import doctest
import logging
import sys
import re
import os
class DocTest(fixtures.TestBase):
def _setup_logger(self):
rootlogger = logging.getLogger('sqlalchemy.engine.base.Engine')
class MyStream(object):
def write(self, string):
sys.stdout.write(string)
sys.stdout.flush()
def flush(self):
pass
self._handler = handler = logging.StreamHandler(MyStream())
handler.setFormatter(logging.Formatter('%(message)s'))
rootlogger.addHandler(handler)
def _teardown_logger(self):
rootlogger = logging.getLogger('sqlalchemy.engine.base.Engine')
rootlogger.removeHandler(self._handler)
def _setup_create_table_patcher(self):
from sqlalchemy.sql import ddl
self.orig_sort = ddl.sort_tables_and_constraints
def our_sort(tables, **kw):
return self.orig_sort(
sorted(tables, key=lambda t: t.key), **kw
)
ddl.sort_tables_and_constraints = our_sort
def _teardown_create_table_patcher(self):
from sqlalchemy.sql import ddl
ddl.sort_tables_and_constraints = self.orig_sort
def setup(self):
self._setup_logger()
self._setup_create_table_patcher()
def teardown(self):
self._teardown_create_table_patcher()
self._teardown_logger()
def _run_doctest_for_content(self, name, content):
optionflags = (
doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
doctest.IGNORE_EXCEPTION_DETAIL |
_get_allow_unicode_flag()
)
runner = doctest.DocTestRunner(
verbose=None, optionflags=optionflags,
checker=_get_unicode_checker())
globs = {
'print_function': print_function}
parser = doctest.DocTestParser()
test = parser.get_doctest(content, globs, name, name, 0)
runner.run(test)
runner.summarize()
assert not runner.failures
def _run_doctest(self, fname):
here = os.path.dirname(__file__)
sqla_base = os.path.normpath(os.path.join(here, "..", ".."))
path = os.path.join(sqla_base, "doc/build", fname)
if not os.path.exists(path):
config.skip_test("Can't find documentation file %r" % path)
with open(path) as file_:
content = file_.read()
content = re.sub(r'{(?:stop|sql|opensql)}', '', content)
self._run_doctest_for_content(fname, content)
def test_orm(self):
self._run_doctest("orm/tutorial.rst")
def test_core(self):
self._run_doctest("core/tutorial.rst")
# unicode checker courtesy py.test
def _get_unicode_checker():
"""
Returns a doctest.OutputChecker subclass that takes in account the
ALLOW_UNICODE option to ignore u'' prefixes in strings. Useful
when the same doctest should run in Python 2 and Python 3.
An inner class is used to avoid importing "doctest" at the module
level.
"""
if hasattr(_get_unicode_checker, 'UnicodeOutputChecker'):
return _get_unicode_checker.UnicodeOutputChecker()
import doctest
import re
class UnicodeOutputChecker(doctest.OutputChecker):
"""
Copied from doctest_nose_plugin.py from the nltk project:
https://github.com/nltk/nltk
"""
_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
def check_output(self, want, got, optionflags):
res = doctest.OutputChecker.check_output(self, want, got,
optionflags)
if res:
return True
if not (optionflags & _get_allow_unicode_flag()):
return False
else: # pragma: no cover
# the code below will end up executed only in Python 2 in
# our tests, and our coverage check runs in Python 3 only
def remove_u_prefixes(txt):
return re.sub(self._literal_re, r'\1\2', txt)
want = remove_u_prefixes(want)
got = remove_u_prefixes(got)
res = doctest.OutputChecker.check_output(self, want, got,
optionflags)
return res
_get_unicode_checker.UnicodeOutputChecker = UnicodeOutputChecker
return _get_unicode_checker.UnicodeOutputChecker()
def _get_allow_unicode_flag():
"""
Registers and returns the ALLOW_UNICODE flag.
"""
import doctest
return doctest.register_optionflag('ALLOW_UNICODE')
|