summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/test
diff options
context:
space:
mode:
authorttt2017-05-13 00:29:47 +0530
committerttt2017-05-13 00:29:47 +0530
commitabf599be33b383a6a5baf9493093b2126a622ac8 (patch)
tree4c5ab6e0d935d5e65fabcf0258e4a00dd20a5afa /lib/python2.7/site-packages/django/test
downloadSBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.gz
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.bz2
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.zip
added all server files
Diffstat (limited to 'lib/python2.7/site-packages/django/test')
-rw-r--r--lib/python2.7/site-packages/django/test/__init__.py10
-rw-r--r--lib/python2.7/site-packages/django/test/_doctest.py2755
-rw-r--r--lib/python2.7/site-packages/django/test/client.py623
-rw-r--r--lib/python2.7/site-packages/django/test/html.py238
-rw-r--r--lib/python2.7/site-packages/django/test/runner.py291
-rw-r--r--lib/python2.7/site-packages/django/test/signals.py81
-rw-r--r--lib/python2.7/site-packages/django/test/simple.py253
-rw-r--r--lib/python2.7/site-packages/django/test/testcases.py1208
-rw-r--r--lib/python2.7/site-packages/django/test/utils.py469
9 files changed, 5928 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/django/test/__init__.py b/lib/python2.7/site-packages/django/test/__init__.py
new file mode 100644
index 0000000..7a49875
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/__init__.py
@@ -0,0 +1,10 @@
+"""
+Django Unit Test and Doctest framework.
+"""
+
+from django.test.client import Client, RequestFactory
+from django.test.testcases import (TestCase, TransactionTestCase,
+ SimpleTestCase, LiveServerTestCase, skipIfDBFeature,
+ skipUnlessDBFeature
+)
+from django.test.utils import Approximate
diff --git a/lib/python2.7/site-packages/django/test/_doctest.py b/lib/python2.7/site-packages/django/test/_doctest.py
new file mode 100644
index 0000000..5381cff
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/_doctest.py
@@ -0,0 +1,2755 @@
+# This is a slightly modified version of the doctest.py that shipped with Python 2.5
+# It incorporates changes that have been submitted to the Python ticket tracker
+# as ticket #1521051. These changes allow for a DoctestRunner and Doctest base
+# class to be specified when constructing a DoctestSuite.
+
+# Module doctest.
+# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).
+# Major enhancements and refactoring by:
+# Jim Fulton
+# Edward Loper
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+r"""Module doctest -- a framework for running examples in docstrings.
+
+In simplest use, end each module M to be tested with:
+
+def _test():
+ import doctest
+ doctest.testmod()
+
+if __name__ == "__main__":
+ _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=True" to testmod, or prohibit
+it by passing "verbose=False". In either of those cases, sys.argv is not
+examined by testmod.
+
+There are a variety of other ways to run doctests, including integration
+with the unittest framework, and support for running non-Python text
+files containing doctests. There are also many ways to override parts
+of doctest's default behaviors. See the Library Reference Manual for
+details.
+"""
+import warnings
+
+warnings.warn(
+ "The django.test._doctest module is deprecated; "
+ "use the doctest module from the Python standard library instead.",
+ PendingDeprecationWarning)
+
+
+__docformat__ = 'reStructuredText en'
+
+__all__ = [
+ # 0, Option Flags
+ 'register_optionflag',
+ 'DONT_ACCEPT_TRUE_FOR_1',
+ 'DONT_ACCEPT_BLANKLINE',
+ 'NORMALIZE_WHITESPACE',
+ 'ELLIPSIS',
+ 'SKIP',
+ 'IGNORE_EXCEPTION_DETAIL',
+ 'COMPARISON_FLAGS',
+ 'REPORT_UDIFF',
+ 'REPORT_CDIFF',
+ 'REPORT_NDIFF',
+ 'REPORT_ONLY_FIRST_FAILURE',
+ 'REPORTING_FLAGS',
+ # 1. Utility Functions
+ # 2. Example & DocTest
+ 'Example',
+ 'DocTest',
+ # 3. Doctest Parser
+ 'DocTestParser',
+ # 4. Doctest Finder
+ 'DocTestFinder',
+ # 5. Doctest Runner
+ 'DocTestRunner',
+ 'OutputChecker',
+ 'DocTestFailure',
+ 'UnexpectedException',
+ 'DebugRunner',
+ # 6. Test Functions
+ 'testmod',
+ 'testfile',
+ 'run_docstring_examples',
+ # 7. Tester
+ 'Tester',
+ # 8. Unittest Support
+ 'DocTestSuite',
+ 'DocFileSuite',
+ 'set_unittest_reportflags',
+ # 9. Debugging Support
+ 'script_from_examples',
+ 'testsource',
+ 'debug_src',
+ 'debug',
+]
+
+import __future__
+
+import sys, traceback, inspect, linecache, os, re
+import unittest, difflib, pdb, tempfile
+import warnings
+
+from django.utils import six
+from django.utils.six.moves import StringIO, xrange
+
+if sys.platform.startswith('java'):
+ # On Jython, isclass() reports some modules as classes. Patch it.
+ def patch_isclass(isclass):
+ def patched_isclass(obj):
+ return isclass(obj) and hasattr(obj, '__module__')
+ return patched_isclass
+ inspect.isclass = patch_isclass(inspect.isclass)
+
+# There are 4 basic classes:
+# - Example: a <source, want> pair, plus an intra-docstring line number.
+# - DocTest: a collection of examples, parsed from a docstring, plus
+# info about where the docstring came from (name, filename, lineno).
+# - DocTestFinder: extracts DocTests from a given object's docstring and
+# its contained objects' docstrings.
+# - DocTestRunner: runs DocTest cases, and accumulates statistics.
+#
+# So the basic picture is:
+#
+# list of:
+# +------+ +---------+ +-------+
+# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results|
+# +------+ +---------+ +-------+
+# | Example |
+# | ... |
+# | Example |
+# +---------+
+
+# Option constants.
+
+OPTIONFLAGS_BY_NAME = {}
+def register_optionflag(name):
+ # Create a new flag unless `name` is already known.
+ return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME))
+
+DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
+DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
+NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
+ELLIPSIS = register_optionflag('ELLIPSIS')
+SKIP = register_optionflag('SKIP')
+IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
+
+COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
+ DONT_ACCEPT_BLANKLINE |
+ NORMALIZE_WHITESPACE |
+ ELLIPSIS |
+ SKIP |
+ IGNORE_EXCEPTION_DETAIL)
+
+REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
+REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
+REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
+REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
+
+REPORTING_FLAGS = (REPORT_UDIFF |
+ REPORT_CDIFF |
+ REPORT_NDIFF |
+ REPORT_ONLY_FIRST_FAILURE)
+
+# Special string markers for use in `want` strings:
+BLANKLINE_MARKER = '<BLANKLINE>'
+ELLIPSIS_MARKER = '...'
+
+######################################################################
+## Table of Contents
+######################################################################
+# 1. Utility Functions
+# 2. Example & DocTest -- store test cases
+# 3. DocTest Parser -- extracts examples from strings
+# 4. DocTest Finder -- extracts test cases from objects
+# 5. DocTest Runner -- runs test cases
+# 6. Test Functions -- convenient wrappers for testing
+# 7. Tester Class -- for backwards compatibility
+# 8. Unittest Support
+# 9. Debugging Support
+# 10. Example Usage
+
+######################################################################
+## 1. Utility Functions
+######################################################################
+
+def _extract_future_flags(globs):
+ """
+ Return the compiler-flags associated with the future features that
+ have been imported into the given namespace (globs).
+ """
+ flags = 0
+ for fname in __future__.all_feature_names:
+ feature = globs.get(fname, None)
+ if feature is getattr(__future__, fname):
+ flags |= feature.compiler_flag
+ return flags
+
+def _normalize_module(module, depth=2):
+ """
+ Return the module specified by `module`. In particular:
+ - If `module` is a module, then return module.
+ - If `module` is a string, then import and return the
+ module with that name.
+ - If `module` is None, then return the calling module.
+ The calling module is assumed to be the module of
+ the stack frame at the given depth in the call stack.
+ """
+ if inspect.ismodule(module):
+ return module
+ elif isinstance(module, six.string_types):
+ return __import__(module, globals(), locals(), ["*"])
+ elif module is None:
+ return sys.modules[sys._getframe(depth).f_globals['__name__']]
+ else:
+ raise TypeError("Expected a module, string, or None")
+
+def _load_testfile(filename, package, module_relative):
+ if module_relative:
+ package = _normalize_module(package, 3)
+ filename = _module_relative_path(package, filename)
+ if hasattr(package, '__loader__'):
+ if hasattr(package.__loader__, 'get_data'):
+ file_contents = package.__loader__.get_data(filename)
+ # get_data() opens files as 'rb', so one must do the equivalent
+ # conversion as universal newlines would do.
+ return file_contents.replace(os.linesep, '\n'), filename
+ with open(filename) as fp:
+ return fp.read(), filename
+
+def _indent(s, indent=4):
+ """
+ Add the given number of space characters to the beginning every
+ non-blank line in `s`, and return the result.
+ """
+ # This regexp matches the start of non-blank lines:
+ return re.sub('(?m)^(?!$)', indent*' ', s)
+
+def _exception_traceback(exc_info):
+ """
+ Return a string containing a traceback message for the given
+ exc_info tuple (as returned by sys.exc_info()).
+ """
+ # Get a traceback message.
+ excout = StringIO()
+ exc_type, exc_val, exc_tb = exc_info
+ traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
+ return excout.getvalue()
+
+# Override some StringIO methods.
+class _SpoofOut(StringIO):
+ def getvalue(self):
+ result = StringIO.getvalue(self)
+ # If anything at all was written, make sure there's a trailing
+ # newline. There's no way for the expected output to indicate
+ # that a trailing newline is missing.
+ if result and not result.endswith("\n"):
+ result += "\n"
+ # Prevent softspace from screwing up the next test case, in
+ # case they used print with a trailing comma in an example.
+ if hasattr(self, "softspace"):
+ del self.softspace
+ return result
+
+ def truncate(self, size=None):
+ StringIO.truncate(self, size)
+ if hasattr(self, "softspace"):
+ del self.softspace
+
+# Worst-case linear-time ellipsis matching.
+def _ellipsis_match(want, got):
+ """
+ Essentially the only subtle case:
+ >>> _ellipsis_match('aa...aa', 'aaa')
+ False
+ """
+ if ELLIPSIS_MARKER not in want:
+ return want == got
+
+ # Find "the real" strings.
+ ws = want.split(ELLIPSIS_MARKER)
+ assert len(ws) >= 2
+
+ # Deal with exact matches possibly needed at one or both ends.
+ startpos, endpos = 0, len(got)
+ w = ws[0]
+ if w: # starts with exact match
+ if got.startswith(w):
+ startpos = len(w)
+ del ws[0]
+ else:
+ return False
+ w = ws[-1]
+ if w: # ends with exact match
+ if got.endswith(w):
+ endpos -= len(w)
+ del ws[-1]
+ else:
+ return False
+
+ if startpos > endpos:
+ # Exact end matches required more characters than we have, as in
+ # _ellipsis_match('aa...aa', 'aaa')
+ return False
+
+ # For the rest, we only need to find the leftmost non-overlapping
+ # match for each piece. If there's no overall match that way alone,
+ # there's no overall match period.
+ for w in ws:
+ # w may be '' at times, if there are consecutive ellipses, or
+ # due to an ellipsis at the start or end of `want`. That's OK.
+ # Search for an empty string succeeds, and doesn't change startpos.
+ startpos = got.find(w, startpos, endpos)
+ if startpos < 0:
+ return False
+ startpos += len(w)
+
+ return True
+
+def _comment_line(line):
+ "Return a commented form of the given line"
+ line = line.rstrip()
+ if line:
+ return '# '+line
+ else:
+ return '#'
+
+class _OutputRedirectingPdb(pdb.Pdb):
+ """
+ A specialized version of the python debugger that redirects stdout
+ to a given stream when interacting with the user. Stdout is *not*
+ redirected when traced code is executed.
+ """
+ def __init__(self, out):
+ self.__out = out
+ self.__debugger_used = False
+ pdb.Pdb.__init__(self, stdout=out)
+
+ def set_trace(self, frame=None):
+ self.__debugger_used = True
+ if frame is None:
+ frame = sys._getframe().f_back
+ pdb.Pdb.set_trace(self, frame)
+
+ def set_continue(self):
+ # Calling set_continue unconditionally would break unit test
+ # coverage reporting, as Bdb.set_continue calls sys.settrace(None).
+ if self.__debugger_used:
+ pdb.Pdb.set_continue(self)
+
+ def trace_dispatch(self, *args):
+ # Redirect stdout to the given stream.
+ save_stdout = sys.stdout
+ sys.stdout = self.__out
+ # Call Pdb's trace dispatch method.
+ try:
+ return pdb.Pdb.trace_dispatch(self, *args)
+ finally:
+ sys.stdout = save_stdout
+
+# [XX] Normalize with respect to os.path.pardir?
+def _module_relative_path(module, path):
+ if not inspect.ismodule(module):
+ raise TypeError('Expected a module: %r' % module)
+ if path.startswith('/'):
+ raise ValueError('Module-relative files may not have absolute paths')
+
+ # Find the base directory for the path.
+ if hasattr(module, '__file__'):
+ # A normal module/package
+ basedir = os.path.split(module.__file__)[0]
+ elif module.__name__ == '__main__':
+ # An interactive session.
+ if len(sys.argv)>0 and sys.argv[0] != '':
+ basedir = os.path.split(sys.argv[0])[0]
+ else:
+ basedir = os.curdir
+ else:
+ # A module w/o __file__ (this includes builtins)
+ raise ValueError("Can't resolve paths relative to the module " +
+ module + " (it has no __file__)")
+
+ # Combine the base directory and the path.
+ return os.path.join(basedir, *(path.split('/')))
+
+######################################################################
+## 2. Example & DocTest
+######################################################################
+## - An "example" is a <source, want> pair, where "source" is a
+## fragment of source code, and "want" is the expected output for
+## "source." The Example class also includes information about
+## where the example was extracted from.
+##
+## - A "doctest" is a collection of examples, typically extracted from
+## a string (such as an object's docstring). The DocTest class also
+## includes information about where the string was extracted from.
+
+class Example:
+ """
+ A single doctest example, consisting of source code and expected
+ output. `Example` defines the following attributes:
+
+ - source: A single Python statement, always ending with a newline.
+ The constructor adds a newline if needed.
+
+ - want: The expected output from running the source code (either
+ from stdout, or a traceback in case of exception). `want` ends
+ with a newline unless it's empty, in which case it's an empty
+ string. The constructor adds a newline if needed.
+
+ - exc_msg: The exception message generated by the example, if
+ the example is expected to generate an exception; or `None` if
+ it is not expected to generate an exception. This exception
+ message is compared against the return value of
+ `traceback.format_exception_only()`. `exc_msg` ends with a
+ newline unless it's `None`. The constructor adds a newline
+ if needed.
+
+ - lineno: The line number within the DocTest string containing
+ this Example where the Example begins. This line number is
+ zero-based, with respect to the beginning of the DocTest.
+
+ - indent: The example's indentation in the DocTest string.
+ I.e., the number of space characters that preceed the
+ example's first prompt.
+
+ - options: A dictionary mapping from option flags to True or
+ False, which is used to override default options for this
+ example. Any option flags not contained in this dictionary
+ are left at their default value (as specified by the
+ DocTestRunner's optionflags). By default, no options are set.
+ """
+ def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
+ options=None):
+ # Normalize inputs.
+ if not source.endswith('\n'):
+ source += '\n'
+ if want and not want.endswith('\n'):
+ want += '\n'
+ if exc_msg is not None and not exc_msg.endswith('\n'):
+ exc_msg += '\n'
+ # Store properties.
+ self.source = source
+ self.want = want
+ self.lineno = lineno
+ self.indent = indent
+ if options is None: options = {}
+ self.options = options
+ self.exc_msg = exc_msg
+
+class DocTest:
+ """
+ A collection of doctest examples that should be run in a single
+ namespace. Each `DocTest` defines the following attributes:
+
+ - examples: the list of examples.
+
+ - globs: The namespace (aka globals) that the examples should
+ be run in.
+
+ - name: A name identifying the DocTest (typically, the name of
+ the object whose docstring this DocTest was extracted from).
+
+ - filename: The name of the file that this DocTest was extracted
+ from, or `None` if the filename is unknown.
+
+ - lineno: The line number within filename where this DocTest
+ begins, or `None` if the line number is unavailable. This
+ line number is zero-based, with respect to the beginning of
+ the file.
+
+ - docstring: The string that the examples were extracted from,
+ or `None` if the string is unavailable.
+ """
+ def __init__(self, examples, globs, name, filename, lineno, docstring):
+ """
+ Create a new DocTest containing the given examples. The
+ DocTest's globals are initialized with a copy of `globs`.
+ """
+ assert not isinstance(examples, six.string_types), \
+ "DocTest no longer accepts str; use DocTestParser instead"
+ self.examples = examples
+ self.docstring = docstring
+ self.globs = globs.copy()
+ self.name = name
+ self.filename = filename
+ self.lineno = lineno
+
+ def __repr__(self):
+ if len(self.examples) == 0:
+ examples = 'no examples'
+ elif len(self.examples) == 1:
+ examples = '1 example'
+ else:
+ examples = '%d examples' % len(self.examples)
+ return ('<DocTest %s from %s:%s (%s)>' %
+ (self.name, self.filename, self.lineno, examples))
+
+
+ # This lets us sort tests by name:
+ def _cmpkey(self):
+ return (self.name, self.filename, self.lineno, id(self))
+ def __cmp__(self, other):
+ if not isinstance(other, DocTest):
+ return -1
+ return cmp(self._cmpkey(), other._cmpkey())
+
+ def __lt__(self, other):
+ return self._cmpkey() < other._cmpkey()
+
+ def __le__(self, other):
+ return self._cmpkey() <= other._cmpkey()
+
+ def __gt__(self, other):
+ return self._cmpkey() > other._cmpkey()
+
+ def __ge__(self, other):
+ return self._cmpkey() >= other._cmpkey()
+
+ def __eq__(self, other):
+ return self._cmpkey() == other._cmpkey()
+
+ def __ne__(self, other):
+ return self._cmpkey() != other._cmpkey()
+
+
+######################################################################
+## 3. DocTestParser
+######################################################################
+
+class DocTestParser:
+ """
+ A class used to parse strings containing doctest examples.
+ """
+ # This regular expression is used to find doctest examples in a
+ # string. It defines three groups: `source` is the source code
+ # (including leading indentation and prompts); `indent` is the
+ # indentation of the first (PS1) line of the source code; and
+ # `want` is the expected output (including leading indentation).
+ _EXAMPLE_RE = re.compile(r'''
+ # Source consists of a PS1 line followed by zero or more PS2 lines.
+ (?P<source>
+ (?:^(?P<indent> [ ]*) >>> .*) # PS1 line
+ (?:\n [ ]* \.\.\. .*)*) # PS2 lines
+ \n?
+ # Want consists of any non-blank lines that do not start with PS1.
+ (?P<want> (?:(?![ ]*$) # Not a blank line
+ (?![ ]*>>>) # Not a line starting with PS1
+ .*$\n? # But any other line
+ )*)
+ ''', re.MULTILINE | re.VERBOSE)
+
+ # A regular expression for handling `want` strings that contain
+ # expected exceptions. It divides `want` into three pieces:
+ # - the traceback header line (`hdr`)
+ # - the traceback stack (`stack`)
+ # - the exception message (`msg`), as generated by
+ # traceback.format_exception_only()
+ # `msg` may have multiple lines. We assume/require that the
+ # exception message is the first non-indented line starting with a word
+ # character following the traceback header line.
+ _EXCEPTION_RE = re.compile(r"""
+ # Grab the traceback header. Different versions of Python have
+ # said different things on the first traceback line.
+ ^(?P<hdr> Traceback\ \(
+ (?: most\ recent\ call\ last
+ | innermost\ last
+ ) \) :
+ )
+ \s* $ # toss trailing whitespace on the header.
+ (?P<stack> .*?) # don't blink: absorb stuff until...
+ ^ (?P<msg> \w+ .*) # a line *starts* with alphanum.
+ """, re.VERBOSE | re.MULTILINE | re.DOTALL)
+
+ # A callable returning a true value if its argument is a blank line
+ # or contains a single comment.
+ _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match
+
+ def parse(self, string, name='<string>'):
+ """
+ Divide the given string into examples and intervening text,
+ and return them as a list of alternating Examples and strings.
+ Line numbers for the Examples are 0-based. The optional
+ argument `name` is a name identifying this string, and is only
+ used for error messages.
+ """
+ string = string.expandtabs()
+ # If all lines begin with the same indentation, then strip it.
+ min_indent = self._min_indent(string)
+ if min_indent > 0:
+ string = '\n'.join([l[min_indent:] for l in string.split('\n')])
+
+ output = []
+ charno, lineno = 0, 0
+ # Find all doctest examples in the string:
+ for m in self._EXAMPLE_RE.finditer(string):
+ # Add the pre-example text to `output`.
+ output.append(string[charno:m.start()])
+ # Update lineno (lines before this example)
+ lineno += string.count('\n', charno, m.start())
+ # Extract info from the regexp match.
+ (source, options, want, exc_msg) = \
+ self._parse_example(m, name, lineno)
+ # Create an Example, and add it to the list.
+ if not self._IS_BLANK_OR_COMMENT(source):
+ output.append( Example(source, want, exc_msg,
+ lineno=lineno,
+ indent=min_indent+len(m.group('indent')),
+ options=options) )
+ # Update lineno (lines inside this example)
+ lineno += string.count('\n', m.start(), m.end())
+ # Update charno.
+ charno = m.end()
+ # Add any remaining post-example text to `output`.
+ output.append(string[charno:])
+ return output
+
+ def get_doctest(self, string, globs, name, filename, lineno):
+ """
+ Extract all doctest examples from the given string, and
+ collect them into a `DocTest` object.
+
+ `globs`, `name`, `filename`, and `lineno` are attributes for
+ the new `DocTest` object. See the documentation for `DocTest`
+ for more information.
+ """
+ return DocTest(self.get_examples(string, name), globs,
+ name, filename, lineno, string)
+
+ def get_examples(self, string, name='<string>'):
+ """
+ Extract all doctest examples from the given string, and return
+ them as a list of `Example` objects. Line numbers are
+ 0-based, because it's most common in doctests that nothing
+ interesting appears on the same line as opening triple-quote,
+ and so the first interesting line is called \"line 1\" then.
+
+ The optional argument `name` is a name identifying this
+ string, and is only used for error messages.
+ """
+ return [x for x in self.parse(string, name)
+ if isinstance(x, Example)]
+
+ def _parse_example(self, m, name, lineno):
+ """
+ Given a regular expression match from `_EXAMPLE_RE` (`m`),
+ return a pair `(source, want)`, where `source` is the matched
+ example's source code (with prompts and indentation stripped);
+ and `want` is the example's expected output (with indentation
+ stripped).
+
+ `name` is the string's name, and `lineno` is the line number
+ where the example starts; both are used for error messages.
+ """
+ # Get the example's indentation level.
+ indent = len(m.group('indent'))
+
+ # Divide source into lines; check that they're properly
+ # indented; and then strip their indentation & prompts.
+ source_lines = m.group('source').split('\n')
+ self._check_prompt_blank(source_lines, indent, name, lineno)
+ self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno)
+ source = '\n'.join([sl[indent+4:] for sl in source_lines])
+
+ # Divide want into lines; check that it's properly indented; and
+ # then strip the indentation. Spaces before the last newline should
+ # be preserved, so plain rstrip() isn't good enough.
+ want = m.group('want')
+ want_lines = want.split('\n')
+ if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
+ del want_lines[-1] # forget final newline & spaces after it
+ self._check_prefix(want_lines, ' '*indent, name,
+ lineno + len(source_lines))
+ want = '\n'.join([wl[indent:] for wl in want_lines])
+
+ # If `want` contains a traceback message, then extract it.
+ m = self._EXCEPTION_RE.match(want)
+ if m:
+ exc_msg = m.group('msg')
+ else:
+ exc_msg = None
+
+ # Extract options from the source.
+ options = self._find_options(source, name, lineno)
+
+ return source, options, want, exc_msg
+
+ # This regular expression looks for option directives in the
+ # source code of an example. Option directives are comments
+ # starting with "doctest:". Warning: this may give false
+ # positives for string-literals that contain the string
+ # "#doctest:". Eliminating these false positives would require
+ # actually parsing the string; but we limit them by ignoring any
+ # line containing "#doctest:" that is *followed* by a quote mark.
+ _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$',
+ re.MULTILINE)
+
+ def _find_options(self, source, name, lineno):
+ """
+ Return a dictionary containing option overrides extracted from
+ option directives in the given source string.
+
+ `name` is the string's name, and `lineno` is the line number
+ where the example starts; both are used for error messages.
+ """
+ options = {}
+ # (note: with the current regexp, this will match at most once:)
+ for m in self._OPTION_DIRECTIVE_RE.finditer(source):
+ option_strings = m.group(1).replace(',', ' ').split()
+ for option in option_strings:
+ if (option[0] not in '+-' or
+ option[1:] not in OPTIONFLAGS_BY_NAME):
+ raise ValueError('line %r of the doctest for %s '
+ 'has an invalid option: %r' %
+ (lineno+1, name, option))
+ flag = OPTIONFLAGS_BY_NAME[option[1:]]
+ options[flag] = (option[0] == '+')
+ if options and self._IS_BLANK_OR_COMMENT(source):
+ raise ValueError('line %r of the doctest for %s has an option '
+ 'directive on a line with no example: %r' %
+ (lineno, name, source))
+ return options
+
+ # This regular expression finds the indentation of every non-blank
+ # line in a string.
+ _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE)
+
+ def _min_indent(self, s):
+ "Return the minimum indentation of any non-blank line in `s`"
+ indents = [len(indent) for indent in self._INDENT_RE.findall(s)]
+ if len(indents) > 0:
+ return min(indents)
+ else:
+ return 0
+
+ def _check_prompt_blank(self, lines, indent, name, lineno):
+ """
+ Given the lines of a source string (including prompts and
+ leading indentation), check to make sure that every prompt is
+ followed by a space character. If any line is not followed by
+ a space character, then raise ValueError.
+ """
+ for i, line in enumerate(lines):
+ if len(line) >= indent+4 and line[indent+3] != ' ':
+ raise ValueError('line %r of the docstring for %s '
+ 'lacks blank after %s: %r' %
+ (lineno+i+1, name,
+ line[indent:indent+3], line))
+
+ def _check_prefix(self, lines, prefix, name, lineno):
+ """
+ Check that every line in the given list starts with the given
+ prefix; if any line does not, then raise a ValueError.
+ """
+ for i, line in enumerate(lines):
+ if line and not line.startswith(prefix):
+ raise ValueError('line %r of the docstring for %s has '
+ 'inconsistent leading whitespace: %r' %
+ (lineno+i+1, name, line))
+
+
+######################################################################
+## 4. DocTest Finder
+######################################################################
+
+class DocTestFinder:
+ """
+ A class used to extract the DocTests that are relevant to a given
+ object, from its docstring and the docstrings of its contained
+ objects. Doctests can currently be extracted from the following
+ object types: modules, functions, classes, methods, staticmethods,
+ classmethods, and properties.
+ """
+
+ def __init__(self, verbose=False, parser=DocTestParser(),
+ recurse=True, exclude_empty=True):
+ """
+ Create a new doctest finder.
+
+ The optional argument `parser` specifies a class or
+ function that should be used to create new DocTest objects (or
+ objects that implement the same interface as DocTest). The
+ signature for this factory function should match the signature
+ of the DocTest constructor.
+
+ If the optional argument `recurse` is false, then `find` will
+ only examine the given object, and not any contained objects.
+
+ If the optional argument `exclude_empty` is false, then `find`
+ will include tests for objects with empty docstrings.
+ """
+ self._parser = parser
+ self._verbose = verbose
+ self._recurse = recurse
+ self._exclude_empty = exclude_empty
+
+ def find(self, obj, name=None, module=None, globs=None, extraglobs=None):
+ """
+ Return a list of the DocTests that are defined by the given
+ object's docstring, or by any of its contained objects'
+ docstrings.
+
+ The optional parameter `module` is the module that contains
+ the given object. If the module is not specified or is None, then
+ the test finder will attempt to automatically determine the
+ correct module. The object's module is used:
+
+ - As a default namespace, if `globs` is not specified.
+ - To prevent the DocTestFinder from extracting DocTests
+ from objects that are imported from other modules.
+ - To find the name of the file containing the object.
+ - To help find the line number of the object within its
+ file.
+
+ Contained objects whose module does not match `module` are ignored.
+
+ If `module` is False, no attempt to find the module will be made.
+ This is obscure, of use mostly in tests: if `module` is False, or
+ is None but cannot be found automatically, then all objects are
+ considered to belong to the (non-existent) module, so all contained
+ objects will (recursively) be searched for doctests.
+
+ The globals for each DocTest is formed by combining `globs`
+ and `extraglobs` (bindings in `extraglobs` override bindings
+ in `globs`). A new copy of the globals dictionary is created
+ for each DocTest. If `globs` is not specified, then it
+ defaults to the module's `__dict__`, if specified, or {}
+ otherwise. If `extraglobs` is not specified, then it defaults
+ to {}.
+
+ """
+ # If name was not specified, then extract it from the object.
+ if name is None:
+ name = getattr(obj, '__name__', None)
+ if name is None:
+ raise ValueError("DocTestFinder.find: name must be given "
+ "when obj.__name__ doesn't exist: %r" %
+ (type(obj),))
+
+ # Find the module that contains the given object (if obj is
+ # a module, then module=obj.). Note: this may fail, in which
+ # case module will be None.
+ if module is False:
+ module = None
+ elif module is None:
+ module = inspect.getmodule(obj)
+
+ # Read the module's source code. This is used by
+ # DocTestFinder._find_lineno to find the line number for a
+ # given object's docstring.
+ try:
+ file = inspect.getsourcefile(obj) or inspect.getfile(obj)
+ source_lines = linecache.getlines(file)
+ if not source_lines:
+ source_lines = None
+ except TypeError:
+ source_lines = None
+
+ # Initialize globals, and merge in extraglobs.
+ if globs is None:
+ if module is None:
+ globs = {}
+ else:
+ globs = module.__dict__.copy()
+ else:
+ globs = globs.copy()
+ if extraglobs is not None:
+ globs.update(extraglobs)
+
+ # Recursively explore `obj`, extracting DocTests.
+ tests = []
+ self._find(tests, obj, name, module, source_lines, globs, {})
+ return tests
+
+ def _from_module(self, module, object):
+ """
+ Return true if the given object is defined in the given
+ module.
+ """
+ if module is None:
+ return True
+ elif inspect.isfunction(object):
+ return module.__dict__ is six.get_function_globals(object)
+ elif inspect.isclass(object):
+ return module.__name__ == object.__module__
+ elif inspect.getmodule(object) is not None:
+ return module is inspect.getmodule(object)
+ elif hasattr(object, '__module__'):
+ return module.__name__ == object.__module__
+ elif isinstance(object, property):
+ return True # [XX] no way not be sure.
+ else:
+ raise ValueError("object must be a class or function")
+
+ def _find(self, tests, obj, name, module, source_lines, globs, seen):
+ """
+ Find tests for the given object and any contained objects, and
+ add them to `tests`.
+ """
+ if self._verbose:
+ print('Finding tests in %s' % name)
+
+ # If we've already processed this object, then ignore it.
+ if id(obj) in seen:
+ return
+ seen[id(obj)] = 1
+
+ # Find a test for this object, and add it to the list of tests.
+ test = self._get_test(obj, name, module, globs, source_lines)
+ if test is not None:
+ tests.append(test)
+
+ # Look for tests in a module's contained objects.
+ if inspect.ismodule(obj) and self._recurse:
+ for valname, val in obj.__dict__.items():
+ valname = '%s.%s' % (name, valname)
+ # Recurse to functions & classes.
+ if ((inspect.isfunction(val) or inspect.isclass(val)) and
+ self._from_module(module, val)):
+ self._find(tests, val, valname, module, source_lines,
+ globs, seen)
+
+ # Look for tests in a module's __test__ dictionary.
+ if inspect.ismodule(obj) and self._recurse:
+ for valname, val in getattr(obj, '__test__', {}).items():
+ if not isinstance(valname, six.string_types):
+ raise ValueError("DocTestFinder.find: __test__ keys "
+ "must be strings: %r" %
+ (type(valname),))
+ if not (inspect.isfunction(val) or inspect.isclass(val) or
+ inspect.ismethod(val) or inspect.ismodule(val) or
+ isinstance(val, six.string_types)):
+ raise ValueError("DocTestFinder.find: __test__ values "
+ "must be strings, functions, methods, "
+ "classes, or modules: %r" %
+ (type(val),))
+ valname = '%s.__test__.%s' % (name, valname)
+ self._find(tests, val, valname, module, source_lines,
+ globs, seen)
+
+ # Look for tests in a class's contained objects.
+ if inspect.isclass(obj) and self._recurse:
+ for valname, val in obj.__dict__.items():
+ # Special handling for staticmethod/classmethod.
+ if isinstance(val, staticmethod):
+ val = getattr(obj, valname)
+ if isinstance(val, classmethod):
+ val = getattr(obj, valname).__func__
+
+ # Recurse to methods, properties, and nested classes.
+ if ((inspect.isfunction(val) or inspect.isclass(val) or
+ isinstance(val, property)) and
+ self._from_module(module, val)):
+ valname = '%s.%s' % (name, valname)
+ self._find(tests, val, valname, module, source_lines,
+ globs, seen)
+
+ def _get_test(self, obj, name, module, globs, source_lines):
+ """
+ Return a DocTest for the given object, if it defines a docstring;
+ otherwise, return None.
+ """
+ # Extract the object's docstring. If it doesn't have one,
+ # then return None (no test for this object).
+ if isinstance(obj, six.string_types):
+ docstring = obj
+ else:
+ try:
+ if obj.__doc__ is None:
+ docstring = ''
+ else:
+ docstring = obj.__doc__
+ if not isinstance(docstring, six.string_types):
+ docstring = str(docstring)
+ except (TypeError, AttributeError):
+ docstring = ''
+
+ # Find the docstring's location in the file.
+ lineno = self._find_lineno(obj, source_lines)
+
+ # Don't bother if the docstring is empty.
+ if self._exclude_empty and not docstring:
+ return None
+
+ # Return a DocTest for this object.
+ if module is None:
+ filename = None
+ else:
+ filename = getattr(module, '__file__', module.__name__)
+ if filename[-4:] in (".pyc", ".pyo"):
+ filename = filename[:-1]
+ return self._parser.get_doctest(docstring, globs, name,
+ filename, lineno)
+
+ def _find_lineno(self, obj, source_lines):
+ """
+ Return a line number of the given object's docstring. Note:
+ this method assumes that the object has a docstring.
+ """
+ lineno = None
+
+ # Find the line number for modules.
+ if inspect.ismodule(obj):
+ lineno = 0
+
+ # Find the line number for classes.
+ # Note: this could be fooled if a class is defined multiple
+ # times in a single file.
+ if inspect.isclass(obj):
+ if source_lines is None:
+ return None
+ pat = re.compile(r'^\s*class\s*%s\b' %
+ getattr(obj, '__name__', '-'))
+ for i, line in enumerate(source_lines):
+ if pat.match(line):
+ lineno = i
+ break
+
+ # Find the line number for functions & methods.
+ if inspect.ismethod(obj): obj = obj.__func__
+ if inspect.isfunction(obj): obj = six.get_function_code(obj)
+ if inspect.istraceback(obj): obj = obj.tb_frame
+ if inspect.isframe(obj): obj = obj.f_code
+ if inspect.iscode(obj):
+ lineno = getattr(obj, 'co_firstlineno', None)-1
+
+ # Find the line number where the docstring starts. Assume
+ # that it's the first line that begins with a quote mark.
+ # Note: this could be fooled by a multiline function
+ # signature, where a continuation line begins with a quote
+ # mark.
+ if lineno is not None:
+ if source_lines is None:
+ return lineno+1
+ pat = re.compile('(^|.*:)\s*\w*("|\')')
+ for lineno in range(lineno, len(source_lines)):
+ if pat.match(source_lines[lineno]):
+ return lineno
+
+ # We couldn't find the line number.
+ return None
+
+######################################################################
+## 5. DocTest Runner
+######################################################################
+
+class DocTestRunner:
+ """
+ A class used to run DocTest test cases, and accumulate statistics.
+ The `run` method is used to process a single DocTest case. It
+ returns a tuple `(f, t)`, where `t` is the number of test cases
+ tried, and `f` is the number of test cases that failed.
+
+ >>> tests = DocTestFinder().find(_TestClass)
+ >>> runner = DocTestRunner(verbose=False)
+ >>> for test in tests:
+ ... print(runner.run(test))
+ (0, 2)
+ (0, 1)
+ (0, 2)
+ (0, 2)
+
+ The `summarize` method prints a summary of all the test cases that
+ have been run by the runner, and returns an aggregated `(f, t)`
+ tuple:
+
+ >>> runner.summarize(verbose=1)
+ 4 items passed all tests:
+ 2 tests in _TestClass
+ 2 tests in _TestClass.__init__
+ 2 tests in _TestClass.get
+ 1 tests in _TestClass.square
+ 7 tests in 4 items.
+ 7 passed and 0 failed.
+ Test passed.
+ (0, 7)
+
+ The aggregated number of tried examples and failed examples is
+ also available via the `tries` and `failures` attributes:
+
+ >>> runner.tries
+ 7
+ >>> runner.failures
+ 0
+
+ The comparison between expected outputs and actual outputs is done
+ by an `OutputChecker`. This comparison may be customized with a
+ number of option flags; see the documentation for `testmod` for
+ more information. If the option flags are insufficient, then the
+ comparison may also be customized by passing a subclass of
+ `OutputChecker` to the constructor.
+
+ The test runner's display output can be controlled in two ways.
+ First, an output function (`out) can be passed to
+ `TestRunner.run`; this function will be called with strings that
+ should be displayed. It defaults to `sys.stdout.write`. If
+ capturing the output is not sufficient, then the display output
+ can be also customized by subclassing DocTestRunner, and
+ overriding the methods `report_start`, `report_success`,
+ `report_unexpected_exception`, and `report_failure`.
+ """
+ # This divider string is used to separate failure messages, and to
+ # separate sections of the summary.
+ DIVIDER = "*" * 70
+
+ def __init__(self, checker=None, verbose=None, optionflags=0):
+ """
+ Create a new test runner.
+
+ Optional keyword arg `checker` is the `OutputChecker` that
+ should be used to compare the expected outputs and actual
+ outputs of doctest examples.
+
+ Optional keyword arg 'verbose' prints lots of stuff if true,
+ only failures if false; by default, it's true iff '-v' is in
+ sys.argv.
+
+ Optional argument `optionflags` can be used to control how the
+ test runner compares expected output to actual output, and how
+ it displays failures. See the documentation for `testmod` for
+ more information.
+ """
+ self._checker = checker or OutputChecker()
+ if verbose is None:
+ verbose = '-v' in sys.argv
+ self._verbose = verbose
+ self.optionflags = optionflags
+ self.original_optionflags = optionflags
+
+ # Keep track of the examples we've run.
+ self.tries = 0
+ self.failures = 0
+ self._name2ft = {}
+
+ # Create a fake output target for capturing doctest output.
+ self._fakeout = _SpoofOut()
+
+ #/////////////////////////////////////////////////////////////////
+ # Reporting methods
+ #/////////////////////////////////////////////////////////////////
+
+ def report_start(self, out, test, example):
+ """
+ Report that the test runner is about to process the given
+ example. (Only displays a message if verbose=True)
+ """
+ if self._verbose:
+ if example.want:
+ out('Trying:\n' + _indent(example.source) +
+ 'Expecting:\n' + _indent(example.want))
+ else:
+ out('Trying:\n' + _indent(example.source) +
+ 'Expecting nothing\n')
+
+ def report_success(self, out, test, example, got):
+ """
+ Report that the given example ran successfully. (Only
+ displays a message if verbose=True)
+ """
+ if self._verbose:
+ out("ok\n")
+
+ def report_failure(self, out, test, example, got):
+ """
+ Report that the given example failed.
+ """
+ out(self._failure_header(test, example) +
+ self._checker.output_difference(example, got, self.optionflags))
+
+ def report_unexpected_exception(self, out, test, example, exc_info):
+ """
+ Report that the given example raised an unexpected exception.
+ """
+ out(self._failure_header(test, example) +
+ 'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
+
+ def _failure_header(self, test, example):
+ out = [self.DIVIDER]
+ if test.filename:
+ if test.lineno is not None and example.lineno is not None:
+ lineno = test.lineno + example.lineno + 1
+ else:
+ lineno = '?'
+ out.append('File "%s", line %s, in %s' %
+ (test.filename, lineno, test.name))
+ else:
+ out.append('Line %s, in %s' % (example.lineno+1, test.name))
+ out.append('Failed example:')
+ source = example.source
+ out.append(_indent(source))
+ return '\n'.join(out)
+
+ #/////////////////////////////////////////////////////////////////
+ # DocTest Running
+ #/////////////////////////////////////////////////////////////////
+
+ def __run(self, test, compileflags, out):
+ """
+ Run the examples in `test`. Write the outcome of each example
+ with one of the `DocTestRunner.report_*` methods, using the
+ writer function `out`. `compileflags` is the set of compiler
+ flags that should be used to execute examples. Return a tuple
+ `(f, t)`, where `t` is the number of examples tried, and `f`
+ is the number of examples that failed. The examples are run
+ in the namespace `test.globs`.
+ """
+ # Keep track of the number of failures and tries.
+ failures = tries = 0
+
+ # Save the option flags (since option directives can be used
+ # to modify them).
+ original_optionflags = self.optionflags
+
+ SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
+
+ check = self._checker.check_output
+
+ # Process each example.
+ for examplenum, example in enumerate(test.examples):
+
+ # If REPORT_ONLY_FIRST_FAILURE is set, then suppress
+ # reporting after the first failure.
+ quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
+ failures > 0)
+
+ # Merge in the example's options.
+ self.optionflags = original_optionflags
+ if example.options:
+ for (optionflag, val) in example.options.items():
+ if val:
+ self.optionflags |= optionflag
+ else:
+ self.optionflags &= ~optionflag
+
+ # If 'SKIP' is set, then skip this example.
+ if self.optionflags & SKIP:
+ continue
+
+ # Record that we started this example.
+ tries += 1
+ if not quiet:
+ self.report_start(out, test, example)
+
+ # Use a special filename for compile(), so we can retrieve
+ # the source code during interactive debugging (see
+ # __patched_linecache_getlines).
+ filename = '<doctest %s[%d]>' % (test.name, examplenum)
+
+ # Doctest and Py3 issue:
+ # If the current example that we wish to run is going to fail
+ # because it expects a leading u"", then use an alternate displayhook
+ original_displayhook = sys.displayhook
+
+ if six.PY3:
+ # only set alternate displayhook if Python 3.x or after
+ lines = []
+ def py3_displayhook(value):
+ if value is None:
+ # None should not be considered at all
+ return original_displayhook(value)
+
+ # Collect the repr output in one variable
+ s = repr(value)
+ # Strip b"" and u"" prefixes from the repr and expected output
+ # TODO: better way of stripping the prefixes?
+ expected = example.want
+ expected = expected.strip() # be wary of newlines
+ s = s.replace("u", "")
+ s = s.replace("b", "")
+ expected = expected.replace("u", "")
+ expected = expected.replace("b", "")
+ # single quote vs. double quote should not matter
+ # default all quote marks to double quote
+ s = s.replace("'", '"')
+ expected = expected.replace("'", '"')
+
+ # In case of multi-line expected result
+ lines.append(s)
+
+ # let them match
+ if s == expected: # be wary of false positives here
+ # they should be the same, print expected value
+ sys.stdout.write("%s\n" % example.want.strip())
+
+ # multi-line expected output, doctest uses loop
+ elif len(expected.split("\n")) == len(lines):
+ if "\n".join(lines) == expected:
+ sys.stdout.write("%s\n" % example.want.strip())
+ else:
+ sys.stdout.write("%s\n" % repr(value))
+ elif len(expected.split("\n")) != len(lines):
+ # we are not done looping yet, do not print anything!
+ pass
+
+ else:
+ sys.stdout.write("%s\n" % repr(value))
+
+ sys.displayhook = py3_displayhook
+
+ # Run the example in the given context (globs), and record
+ # any exception that gets raised. (But don't intercept
+ # keyboard interrupts.)
+ try:
+ # Don't blink! This is where the user's code gets run.
+ six.exec_(compile(example.source, filename, "single",
+ compileflags, 1), test.globs)
+ self.debugger.set_continue() # ==== Example Finished ====
+ exception = None
+ except KeyboardInterrupt:
+ raise
+ except:
+ exception = sys.exc_info()
+ self.debugger.set_continue() # ==== Example Finished ====
+ finally:
+ # restore the original displayhook
+ sys.displayhook = original_displayhook
+
+ got = self._fakeout.getvalue() # the actual output
+ self._fakeout.truncate(0)
+ # Python 3.1 requires seek after truncate
+ self._fakeout.seek(0)
+ outcome = FAILURE # guilty until proved innocent or insane
+
+ # If the example executed without raising any exceptions,
+ # verify its output.
+ if exception is None:
+ if check(example.want, got, self.optionflags):
+ outcome = SUCCESS
+
+ # The example raised an exception: check if it was expected.
+ else:
+ exc_msg = traceback.format_exception_only(*exception[:2])[-1]
+ if six.PY3:
+ # module name will be in group(1) and the expected
+ # exception message will be in group(2)
+ m = re.match(r'(.*)\.(\w+:.+\s)', exc_msg)
+ # make sure there's a match
+ if m != None:
+ f_name = m.group(1)
+ # check to see if m.group(1) contains the module name
+ if f_name == exception[0].__module__:
+ # strip the module name from exc_msg
+ exc_msg = m.group(2)
+
+ if not quiet:
+ got += _exception_traceback(exception)
+
+ # If `example.exc_msg` is None, then we weren't expecting
+ # an exception.
+ if example.exc_msg is None:
+ outcome = BOOM
+
+ # We expected an exception: see whether it matches.
+ elif check(example.exc_msg, exc_msg, self.optionflags):
+ outcome = SUCCESS
+
+ # Another chance if they didn't care about the detail.
+ elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
+ m1 = re.match(r'[^:]*:', example.exc_msg)
+ m2 = re.match(r'[^:]*:', exc_msg)
+ if m1 and m2 and check(m1.group(0), m2.group(0),
+ self.optionflags):
+ outcome = SUCCESS
+
+ # Report the outcome.
+ if outcome is SUCCESS:
+ if not quiet:
+ self.report_success(out, test, example, got)
+ elif outcome is FAILURE:
+ if not quiet:
+ self.report_failure(out, test, example, got)
+ failures += 1
+ elif outcome is BOOM:
+ if not quiet:
+ self.report_unexpected_exception(out, test, example,
+ exception)
+ failures += 1
+ else:
+ assert False, ("unknown outcome", outcome)
+
+ # Restore the option flags (in case they were modified)
+ self.optionflags = original_optionflags
+
+ # Record and return the number of failures and tries.
+ self.__record_outcome(test, failures, tries)
+ return failures, tries
+
+ def __record_outcome(self, test, f, t):
+ """
+ Record the fact that the given DocTest (`test`) generated `f`
+ failures out of `t` tried examples.
+ """
+ f2, t2 = self._name2ft.get(test.name, (0,0))
+ self._name2ft[test.name] = (f+f2, t+t2)
+ self.failures += f
+ self.tries += t
+
+ __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
+ r'(?P<name>[\w\.]+)'
+ r'\[(?P<examplenum>\d+)\]>$')
+ def __patched_linecache_getlines(self, filename, module_globals=None):
+ m = self.__LINECACHE_FILENAME_RE.match(filename)
+ if m and m.group('name') == self.test.name:
+ example = self.test.examples[int(m.group('examplenum'))]
+ return example.source.splitlines(True)
+ else:
+ return self.save_linecache_getlines(filename, module_globals)
+
+ def run(self, test, compileflags=None, out=None, clear_globs=True):
+ """
+ Run the examples in `test`, and display the results using the
+ writer function `out`.
+
+ The examples are run in the namespace `test.globs`. If
+ `clear_globs` is true (the default), then this namespace will
+ be cleared after the test runs, to help with garbage
+ collection. If you would like to examine the namespace after
+ the test completes, then use `clear_globs=False`.
+
+ `compileflags` gives the set of flags that should be used by
+ the Python compiler when running the examples. If not
+ specified, then it will default to the set of future-import
+ flags that apply to `globs`.
+
+ The output of each example is checked using
+ `DocTestRunner.check_output`, and the results are formatted by
+ the `DocTestRunner.report_*` methods.
+ """
+ self.test = test
+
+ if compileflags is None:
+ compileflags = _extract_future_flags(test.globs)
+
+ save_stdout = sys.stdout
+ if out is None:
+ out = save_stdout.write
+ sys.stdout = self._fakeout
+
+ # Patch pdb.set_trace to restore sys.stdout during interactive
+ # debugging (so it's not still redirected to self._fakeout).
+ # Note that the interactive output will go to *our*
+ # save_stdout, even if that's not the real sys.stdout; this
+ # allows us to write test cases for the set_trace behavior.
+ save_set_trace = pdb.set_trace
+ self.debugger = _OutputRedirectingPdb(save_stdout)
+ self.debugger.reset()
+ pdb.set_trace = self.debugger.set_trace
+
+ # Patch linecache.getlines, so we can see the example's source
+ # when we're inside the debugger.
+ self.save_linecache_getlines = linecache.getlines
+ linecache.getlines = self.__patched_linecache_getlines
+
+ try:
+ return self.__run(test, compileflags, out)
+ finally:
+ sys.stdout = save_stdout
+ pdb.set_trace = save_set_trace
+ linecache.getlines = self.save_linecache_getlines
+ if clear_globs:
+ test.globs.clear()
+
+ #/////////////////////////////////////////////////////////////////
+ # Summarization
+ #/////////////////////////////////////////////////////////////////
+ def summarize(self, verbose=None):
+ """
+ Print a summary of all the test cases that have been run by
+ this DocTestRunner, and return a tuple `(f, t)`, where `f` is
+ the total number of failed examples, and `t` is the total
+ number of tried examples.
+
+ The optional `verbose` argument controls how detailed the
+ summary is. If the verbosity is not specified, then the
+ DocTestRunner's verbosity is used.
+ """
+ if verbose is None:
+ verbose = self._verbose
+ notests = []
+ passed = []
+ failed = []
+ totalt = totalf = 0
+ for x in self._name2ft.items():
+ name, (f, t) = x
+ assert f <= t
+ totalt += t
+ totalf += f
+ if t == 0:
+ notests.append(name)
+ elif f == 0:
+ passed.append( (name, t) )
+ else:
+ failed.append(x)
+ if verbose:
+ if notests:
+ print("%d items had no tests:" % len(notests))
+ notests.sort()
+ for thing in notests:
+ print(" %s" % thing)
+ if passed:
+ print("%d items passed all tests:" % len(passed))
+ passed.sort()
+ for thing, count in passed:
+ print(" %3d tests in %s" % (count, thing))
+ if failed:
+ print(self.DIVIDER)
+ print("%d items had failures:" % len(failed))
+ failed.sort()
+ for thing, (f, t) in failed:
+ print(" %3d of %3d in %s" % (f, t, thing))
+ if verbose:
+ print("%d tests in % d items" % (len(self._name2ft), totalt))
+ print("%d passed and %d failed." % (totalt - totalf, totalf))
+ if totalf:
+ print("***Test Failed*** %d failures." % totalf)
+ elif verbose:
+ print("Test passed.")
+ return totalf, totalt
+
+ #/////////////////////////////////////////////////////////////////
+ # Backward compatibility cruft to maintain doctest.master.
+ #/////////////////////////////////////////////////////////////////
+ def merge(self, other):
+ d = self._name2ft
+ for name, (f, t) in other._name2ft.items():
+ if name in d:
+ print("*** DocTestRunner.merge: '" + name + "' in both" \
+ " testers; summing outcomes.")
+ f2, t2 = d[name]
+ f = f + f2
+ t = t + t2
+ d[name] = f, t
+
+class OutputChecker:
+ """
+ A class used to check the whether the actual output from a doctest
+ example matches the expected output. `OutputChecker` defines two
+ methods: `check_output`, which compares a given pair of outputs,
+ and returns true if they match; and `output_difference`, which
+ returns a string describing the differences between two outputs.
+ """
+ def check_output(self, want, got, optionflags):
+ """
+ Return True iff the actual output from an example (`got`)
+ matches the expected output (`want`). These strings are
+ always considered to match if they are identical; but
+ depending on what option flags the test runner is using,
+ several non-exact match types are also possible. See the
+ documentation for `TestRunner` for more information about
+ option flags.
+ """
+ # Handle the common case first, for efficiency:
+ # if they're string-identical, always return true.
+ if got == want:
+ return True
+
+ # The values True and False replaced 1 and 0 as the return
+ # value for boolean comparisons in Python 2.3.
+ if not (optionflags & DONT_ACCEPT_TRUE_FOR_1):
+ if (got,want) == ("True\n", "1\n"):
+ return True
+ if (got,want) == ("False\n", "0\n"):
+ return True
+
+ # <BLANKLINE> can be used as a special sequence to signify a
+ # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used.
+ if not (optionflags & DONT_ACCEPT_BLANKLINE):
+ # Replace <BLANKLINE> in want with a blank line.
+ want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER),
+ '', want)
+ # If a line in got contains only spaces, then remove the
+ # spaces.
+ got = re.sub('(?m)^\s*?$', '', got)
+ if got == want:
+ return True
+
+ # This flag causes doctest to ignore any differences in the
+ # contents of whitespace strings. Note that this can be used
+ # in conjunction with the ELLIPSIS flag.
+ if optionflags & NORMALIZE_WHITESPACE:
+ got = ' '.join(got.split())
+ want = ' '.join(want.split())
+ if got == want:
+ return True
+
+ # The ELLIPSIS flag says to let the sequence "..." in `want`
+ # match any substring in `got`.
+ if optionflags & ELLIPSIS:
+ if _ellipsis_match(want, got):
+ return True
+
+ # We didn't find any match; return false.
+ return False
+
+ # Should we do a fancy diff?
+ def _do_a_fancy_diff(self, want, got, optionflags):
+ # Not unless they asked for a fancy diff.
+ if not optionflags & (REPORT_UDIFF |
+ REPORT_CDIFF |
+ REPORT_NDIFF):
+ return False
+
+ # If expected output uses ellipsis, a meaningful fancy diff is
+ # too hard ... or maybe not. In two real-life failures Tim saw,
+ # a diff was a major help anyway, so this is commented out.
+ # [todo] _ellipsis_match() knows which pieces do and don't match,
+ # and could be the basis for a kick-ass diff in this case.
+ ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want:
+ ## return False
+
+ # ndiff does intraline difference marking, so can be useful even
+ # for 1-line differences.
+ if optionflags & REPORT_NDIFF:
+ return True
+
+ # The other diff types need at least a few lines to be helpful.
+ return want.count('\n') > 2 and got.count('\n') > 2
+
+ def output_difference(self, example, got, optionflags):
+ """
+ Return a string describing the differences between the
+ expected output for a given example (`example`) and the actual
+ output (`got`). `optionflags` is the set of option flags used
+ to compare `want` and `got`.
+ """
+ want = example.want
+ # If <BLANKLINE>s are being used, then replace blank lines
+ # with <BLANKLINE> in the actual output string.
+ if not (optionflags & DONT_ACCEPT_BLANKLINE):
+ got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got)
+
+ # Check if we should use diff.
+ if self._do_a_fancy_diff(want, got, optionflags):
+ # Split want & got into lines.
+ want_lines = want.splitlines(True) # True == keep line ends
+ got_lines = got.splitlines(True)
+ # Use difflib to find their differences.
+ if optionflags & REPORT_UDIFF:
+ diff = difflib.unified_diff(want_lines, got_lines, n=2)
+ diff = list(diff)[2:] # strip the diff header
+ kind = 'unified diff with -expected +actual'
+ elif optionflags & REPORT_CDIFF:
+ diff = difflib.context_diff(want_lines, got_lines, n=2)
+ diff = list(diff)[2:] # strip the diff header
+ kind = 'context diff with expected followed by actual'
+ elif optionflags & REPORT_NDIFF:
+ engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
+ diff = list(engine.compare(want_lines, got_lines))
+ kind = 'ndiff with -expected +actual'
+ else:
+ assert 0, 'Bad diff option'
+ # Remove trailing whitespace on diff output.
+ diff = [line.rstrip() + '\n' for line in diff]
+ return 'Differences (%s):\n' % kind + _indent(''.join(diff))
+
+ # If we're not using diff, then simply list the expected
+ # output followed by the actual output.
+ if want and got:
+ return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got))
+ elif want:
+ return 'Expected:\n%sGot nothing\n' % _indent(want)
+ elif got:
+ return 'Expected nothing\nGot:\n%s' % _indent(got)
+ else:
+ return 'Expected nothing\nGot nothing\n'
+
+class DocTestFailure(Exception):
+ """A DocTest example has failed in debugging mode.
+
+ The exception instance has variables:
+
+ - test: the DocTest object being run
+
+ - example: the Example object that failed
+
+ - got: the actual output
+ """
+ def __init__(self, test, example, got):
+ self.test = test
+ self.example = example
+ self.got = got
+
+ def __str__(self):
+ return str(self.test)
+
+class UnexpectedException(Exception):
+ """A DocTest example has encountered an unexpected exception
+
+ The exception instance has variables:
+
+ - test: the DocTest object being run
+
+ - example: the Example object that failed
+
+ - exc_info: the exception info
+ """
+ def __init__(self, test, example, exc_info):
+ self.test = test
+ self.example = example
+ self.exc_info = exc_info
+
+ def __str__(self):
+ return str(self.test)
+
+class DebugRunner(DocTestRunner):
+ r"""Run doc tests but raise an exception as soon as there is a failure.
+
+ If an unexpected exception occurs, an UnexpectedException is raised.
+ It contains the test, the example, and the original exception:
+
+ >>> runner = DebugRunner(verbose=False)
+ >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+ ... {}, 'foo', 'foo.py', 0)
+ >>> try:
+ ... runner.run(test)
+ ... except UnexpectedException as e:
+ ... failure = e
+
+ >>> failure.test is test
+ True
+
+ >>> failure.example.want
+ '42\n'
+
+ >>> exc_info = failure.exc_info
+ >>> raise exc_info[0], exc_info[1], exc_info[2]
+ Traceback (most recent call last):
+ ...
+ KeyError
+
+ We wrap the original exception to give the calling application
+ access to the test and example information.
+
+ If the output doesn't match, then a DocTestFailure is raised:
+
+ >>> test = DocTestParser().get_doctest('''
+ ... >>> x = 1
+ ... >>> x
+ ... 2
+ ... ''', {}, 'foo', 'foo.py', 0)
+
+ >>> try:
+ ... runner.run(test)
+ ... except DocTestFailure as e:
+ ... failure = e
+
+ DocTestFailure objects provide access to the test:
+
+ >>> failure.test is test
+ True
+
+ As well as to the example:
+
+ >>> failure.example.want
+ '2\n'
+
+ and the actual output:
+
+ >>> failure.got
+ '1\n'
+
+ If a failure or error occurs, the globals are left intact:
+
+ >>> del test.globs['__builtins__']
+ >>> test.globs
+ {'x': 1}
+
+ >>> test = DocTestParser().get_doctest('''
+ ... >>> x = 2
+ ... >>> raise KeyError
+ ... ''', {}, 'foo', 'foo.py', 0)
+
+ >>> runner.run(test)
+ Traceback (most recent call last):
+ ...
+ UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
+
+ >>> del test.globs['__builtins__']
+ >>> test.globs
+ {'x': 2}
+
+ But the globals are cleared if there is no error:
+
+ >>> test = DocTestParser().get_doctest('''
+ ... >>> x = 2
+ ... ''', {}, 'foo', 'foo.py', 0)
+
+ >>> runner.run(test)
+ (0, 1)
+
+ >>> test.globs
+ {}
+
+ """
+
+ def run(self, test, compileflags=None, out=None, clear_globs=True):
+ r = DocTestRunner.run(self, test, compileflags, out, False)
+ if clear_globs:
+ test.globs.clear()
+ return r
+
+ def report_unexpected_exception(self, out, test, example, exc_info):
+ raise UnexpectedException(test, example, exc_info)
+
+ def report_failure(self, out, test, example, got):
+ raise DocTestFailure(test, example, got)
+
+######################################################################
+## 6. Test Functions
+######################################################################
+# These should be backwards compatible.
+
+# For backward compatibility, a global instance of a DocTestRunner
+# class, updated by testmod.
+master = None
+
+def testmod(m=None, name=None, globs=None, verbose=None,
+ report=True, optionflags=0, extraglobs=None,
+ raise_on_error=False, exclude_empty=False):
+ """m=None, name=None, globs=None, verbose=None, report=True,
+ optionflags=0, extraglobs=None, raise_on_error=False,
+ exclude_empty=False
+
+ Test examples in docstrings in functions and classes reachable
+ from module m (or the current module if m is not supplied), starting
+ with m.__doc__.
+
+ Also test examples reachable from dict m.__test__ if it exists and is
+ not None. m.__test__ maps names to functions, classes and strings;
+ function and class docstrings are tested even if the name is private;
+ strings are tested directly, as if they were docstrings.
+
+ Return (#failures, #tests).
+
+ See doctest.__doc__ for an overview.
+
+ Optional keyword arg "name" gives the name of the module; by default
+ use m.__name__.
+
+ Optional keyword arg "globs" gives a dict to be used as the globals
+ when executing examples; by default, use m.__dict__. A copy of this
+ dict is actually used for each docstring, so that each docstring's
+ examples start with a clean slate.
+
+ Optional keyword arg "extraglobs" gives a dictionary that should be
+ merged into the globals that are used to execute examples. By
+ default, no extra globals are used. This is new in 2.4.
+
+ Optional keyword arg "verbose" prints lots of stuff if true, prints
+ only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+ Optional keyword arg "report" prints a summary at the end when true,
+ else prints nothing at the end. In verbose mode, the summary is
+ detailed, else very brief (in fact, empty if all tests passed).
+
+ Optional keyword arg "optionflags" or's together module constants,
+ and defaults to 0. This is new in 2.3. Possible values (see the
+ docs for details):
+
+ DONT_ACCEPT_TRUE_FOR_1
+ DONT_ACCEPT_BLANKLINE
+ NORMALIZE_WHITESPACE
+ ELLIPSIS
+ SKIP
+ IGNORE_EXCEPTION_DETAIL
+ REPORT_UDIFF
+ REPORT_CDIFF
+ REPORT_NDIFF
+ REPORT_ONLY_FIRST_FAILURE
+
+ Optional keyword arg "raise_on_error" raises an exception on the
+ first unexpected exception or failure. This allows failures to be
+ post-mortem debugged.
+
+ Advanced tomfoolery: testmod runs methods of a local instance of
+ class doctest.Tester, then merges the results into (or creates)
+ global Tester instance doctest.master. Methods of doctest.master
+ can be called directly too, if you want to do something unusual.
+ Passing report=0 to testmod is especially useful then, to delay
+ displaying a summary. Invoke doctest.master.summarize(verbose)
+ when you're done fiddling.
+ """
+ global master
+
+ # If no module was given, then use __main__.
+ if m is None:
+ # DWA - m will still be None if this wasn't invoked from the command
+ # line, in which case the following TypeError is about as good an error
+ # as we should expect
+ m = sys.modules.get('__main__')
+
+ # Check that we were actually given a module.
+ if not inspect.ismodule(m):
+ raise TypeError("testmod: module required; %r" % (m,))
+
+ # If no name was given, then use the module's name.
+ if name is None:
+ name = m.__name__
+
+ # Find, parse, and run all tests in the given module.
+ finder = DocTestFinder(exclude_empty=exclude_empty)
+
+ if raise_on_error:
+ runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+ else:
+ runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+ for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
+ runner.run(test)
+
+ if report:
+ runner.summarize()
+
+ if master is None:
+ master = runner
+ else:
+ master.merge(runner)
+
+ return runner.failures, runner.tries
+
+def testfile(filename, module_relative=True, name=None, package=None,
+ globs=None, verbose=None, report=True, optionflags=0,
+ extraglobs=None, raise_on_error=False, parser=DocTestParser(),
+ encoding=None):
+ """
+ Test examples in the given file. Return (#failures, #tests).
+
+ Optional keyword arg "module_relative" specifies how filenames
+ should be interpreted:
+
+ - If "module_relative" is True (the default), then "filename"
+ specifies a module-relative path. By default, this path is
+ relative to the calling module's directory; but if the
+ "package" argument is specified, then it is relative to that
+ package. To ensure os-independence, "filename" should use
+ "/" characters to separate path segments, and should not
+ be an absolute path (i.e., it may not begin with "/").
+
+ - If "module_relative" is False, then "filename" specifies an
+ os-specific path. The path may be absolute or relative (to
+ the current working directory).
+
+ Optional keyword arg "name" gives the name of the test; by default
+ use the file's basename.
+
+ Optional keyword argument "package" is a Python package or the
+ name of a Python package whose directory should be used as the
+ base directory for a module relative filename. If no package is
+ specified, then the calling module's directory is used as the base
+ directory for module relative filenames. It is an error to
+ specify "package" if "module_relative" is False.
+
+ Optional keyword arg "globs" gives a dict to be used as the globals
+ when executing examples; by default, use {}. A copy of this dict
+ is actually used for each docstring, so that each docstring's
+ examples start with a clean slate.
+
+ Optional keyword arg "extraglobs" gives a dictionary that should be
+ merged into the globals that are used to execute examples. By
+ default, no extra globals are used.
+
+ Optional keyword arg "verbose" prints lots of stuff if true, prints
+ only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+ Optional keyword arg "report" prints a summary at the end when true,
+ else prints nothing at the end. In verbose mode, the summary is
+ detailed, else very brief (in fact, empty if all tests passed).
+
+ Optional keyword arg "optionflags" or's together module constants,
+ and defaults to 0. Possible values (see the docs for details):
+
+ DONT_ACCEPT_TRUE_FOR_1
+ DONT_ACCEPT_BLANKLINE
+ NORMALIZE_WHITESPACE
+ ELLIPSIS
+ SKIP
+ IGNORE_EXCEPTION_DETAIL
+ REPORT_UDIFF
+ REPORT_CDIFF
+ REPORT_NDIFF
+ REPORT_ONLY_FIRST_FAILURE
+
+ Optional keyword arg "raise_on_error" raises an exception on the
+ first unexpected exception or failure. This allows failures to be
+ post-mortem debugged.
+
+ Optional keyword arg "parser" specifies a DocTestParser (or
+ subclass) that should be used to extract tests from the files.
+
+ Optional keyword arg "encoding" specifies an encoding that should
+ be used to convert the file to unicode.
+
+ Advanced tomfoolery: testmod runs methods of a local instance of
+ class doctest.Tester, then merges the results into (or creates)
+ global Tester instance doctest.master. Methods of doctest.master
+ can be called directly too, if you want to do something unusual.
+ Passing report=0 to testmod is especially useful then, to delay
+ displaying a summary. Invoke doctest.master.summarize(verbose)
+ when you're done fiddling.
+ """
+ global master
+
+ if package and not module_relative:
+ raise ValueError("Package may only be specified for module-"
+ "relative paths.")
+
+ # Relativize the path
+ text, filename = _load_testfile(filename, package, module_relative)
+
+ # If no name was given, then use the file's name.
+ if name is None:
+ name = os.path.basename(filename)
+
+ # Assemble the globals.
+ if globs is None:
+ globs = {}
+ else:
+ globs = globs.copy()
+ if extraglobs is not None:
+ globs.update(extraglobs)
+
+ if raise_on_error:
+ runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+ else:
+ runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+ if encoding is not None:
+ text = text.decode(encoding)
+
+ # Read the file, convert it to a test, and run it.
+ test = parser.get_doctest(text, globs, name, filename, 0)
+ runner.run(test)
+
+ if report:
+ runner.summarize()
+
+ if master is None:
+ master = runner
+ else:
+ master.merge(runner)
+
+ return runner.failures, runner.tries
+
+def run_docstring_examples(f, globs, verbose=False, name="NoName",
+ compileflags=None, optionflags=0):
+ """
+ Test examples in the given object's docstring (`f`), using `globs`
+ as globals. Optional argument `name` is used in failure messages.
+ If the optional argument `verbose` is true, then generate output
+ even if there are no failures.
+
+ `compileflags` gives the set of flags that should be used by the
+ Python compiler when running the examples. If not specified, then
+ it will default to the set of future-import flags that apply to
+ `globs`.
+
+ Optional keyword arg `optionflags` specifies options for the
+ testing and output. See the documentation for `testmod` for more
+ information.
+ """
+ # Find, parse, and run all tests in the given module.
+ finder = DocTestFinder(verbose=verbose, recurse=False)
+ runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+ for test in finder.find(f, name, globs=globs):
+ runner.run(test, compileflags=compileflags)
+
+######################################################################
+## 7. Tester
+######################################################################
+# This is provided only for backwards compatibility. It's not
+# actually used in any way.
+
+class Tester:
+ def __init__(self, mod=None, globs=None, verbose=None, optionflags=0):
+
+ warnings.warn("class Tester is deprecated; "
+ "use class doctest.DocTestRunner instead",
+ DeprecationWarning, stacklevel=2)
+ if mod is None and globs is None:
+ raise TypeError("Tester.__init__: must specify mod or globs")
+ if mod is not None and not inspect.ismodule(mod):
+ raise TypeError("Tester.__init__: mod must be a module; %r" %
+ (mod,))
+ if globs is None:
+ globs = mod.__dict__
+ self.globs = globs
+
+ self.verbose = verbose
+ self.optionflags = optionflags
+ self.testfinder = DocTestFinder()
+ self.testrunner = DocTestRunner(verbose=verbose,
+ optionflags=optionflags)
+
+ def runstring(self, s, name):
+ test = DocTestParser().get_doctest(s, self.globs, name, None, None)
+ if self.verbose:
+ print("Running string %s" % name)
+ (f,t) = self.testrunner.run(test)
+ if self.verbose:
+ print("%s of %s examples failed in string %s" % (f, t, name))
+ return (f,t)
+
+ def rundoc(self, object, name=None, module=None):
+ f = t = 0
+ tests = self.testfinder.find(object, name, module=module,
+ globs=self.globs)
+ for test in tests:
+ (f2, t2) = self.testrunner.run(test)
+ (f,t) = (f+f2, t+t2)
+ return (f,t)
+
+ def rundict(self, d, name, module=None):
+ import new
+ m = new.module(name)
+ m.__dict__.update(d)
+ if module is None:
+ module = False
+ return self.rundoc(m, name, module)
+
+ def run__test__(self, d, name):
+ import new
+ m = new.module(name)
+ m.__test__ = d
+ return self.rundoc(m, name)
+
+ def summarize(self, verbose=None):
+ return self.testrunner.summarize(verbose)
+
+ def merge(self, other):
+ self.testrunner.merge(other.testrunner)
+
+######################################################################
+## 8. Unittest Support
+######################################################################
+
+_unittest_reportflags = 0
+
+def set_unittest_reportflags(flags):
+ """Sets the unittest option flags.
+
+ The old flag is returned so that a runner could restore the old
+ value if it wished to:
+
+ >>> old = _unittest_reportflags
+ >>> set_unittest_reportflags(REPORT_NDIFF |
+ ... REPORT_ONLY_FIRST_FAILURE) == old
+ True
+
+ >>> import doctest
+ >>> doctest._unittest_reportflags == (REPORT_NDIFF |
+ ... REPORT_ONLY_FIRST_FAILURE)
+ True
+
+ Only reporting flags can be set:
+
+ >>> set_unittest_reportflags(ELLIPSIS)
+ Traceback (most recent call last):
+ ...
+ ValueError: ('Only reporting flags allowed', 8)
+
+ >>> set_unittest_reportflags(old) == (REPORT_NDIFF |
+ ... REPORT_ONLY_FIRST_FAILURE)
+ True
+ """
+ global _unittest_reportflags
+
+ if (flags & REPORTING_FLAGS) != flags:
+ raise ValueError("Only reporting flags allowed", flags)
+ old = _unittest_reportflags
+ _unittest_reportflags = flags
+ return old
+
+
+class DocTestCase(unittest.TestCase):
+
+ def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
+ checker=None, runner=DocTestRunner):
+
+ unittest.TestCase.__init__(self)
+ self._dt_optionflags = optionflags
+ self._dt_checker = checker
+ self._dt_test = test
+ self._dt_setUp = setUp
+ self._dt_tearDown = tearDown
+ self._dt_runner = runner
+
+ def setUp(self):
+ test = self._dt_test
+
+ if self._dt_setUp is not None:
+ self._dt_setUp(test)
+
+ def tearDown(self):
+ test = self._dt_test
+
+ if self._dt_tearDown is not None:
+ self._dt_tearDown(test)
+
+ test.globs.clear()
+
+ def runTest(self):
+ test = self._dt_test
+ old = sys.stdout
+ new = StringIO()
+ optionflags = self._dt_optionflags
+
+ if not (optionflags & REPORTING_FLAGS):
+ # The option flags don't include any reporting flags,
+ # so add the default reporting flags
+ optionflags |= _unittest_reportflags
+
+ runner = self._dt_runner(optionflags=optionflags,
+ checker=self._dt_checker, verbose=False)
+
+ try:
+ runner.DIVIDER = "-"*70
+ failures, tries = runner.run(
+ test, out=new.write, clear_globs=False)
+ finally:
+ sys.stdout = old
+
+ if failures:
+ raise self.failureException(self.format_failure(new.getvalue()))
+
+ def format_failure(self, err):
+ test = self._dt_test
+ if test.lineno is None:
+ lineno = 'unknown line number'
+ else:
+ lineno = '%s' % test.lineno
+ lname = '.'.join(test.name.split('.')[-1:])
+ return ('Failed doctest test for %s\n'
+ ' File "%s", line %s, in %s\n\n%s'
+ % (test.name, test.filename, lineno, lname, err)
+ )
+
+ def debug(self):
+ r"""Run the test case without results and without catching exceptions
+
+ The unit test framework includes a debug method on test cases
+ and test suites to support post-mortem debugging. The test code
+ is run in such a way that errors are not caught. This way a
+ caller can catch the errors and initiate post-mortem debugging.
+
+ The DocTestCase provides a debug method that raises
+ UnexpectedException errors if there is an unexepcted
+ exception:
+
+ >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+ ... {}, 'foo', 'foo.py', 0)
+ >>> case = DocTestCase(test)
+ >>> try:
+ ... case.debug()
+ ... except UnexpectedException as e:
+ ... failure = e
+
+ The UnexpectedException contains the test, the example, and
+ the original exception:
+
+ >>> failure.test is test
+ True
+
+ >>> failure.example.want
+ '42\n'
+
+ >>> exc_info = failure.exc_info
+ >>> raise exc_info[0], exc_info[1], exc_info[2]
+ Traceback (most recent call last):
+ ...
+ KeyError
+
+ If the output doesn't match, then a DocTestFailure is raised:
+
+ >>> test = DocTestParser().get_doctest('''
+ ... >>> x = 1
+ ... >>> x
+ ... 2
+ ... ''', {}, 'foo', 'foo.py', 0)
+ >>> case = DocTestCase(test)
+
+ >>> try:
+ ... case.debug()
+ ... except DocTestFailure as e:
+ ... failure = e
+
+ DocTestFailure objects provide access to the test:
+
+ >>> failure.test is test
+ True
+
+ As well as to the example:
+
+ >>> failure.example.want
+ '2\n'
+
+ and the actual output:
+
+ >>> failure.got
+ '1\n'
+
+ """
+
+ self.setUp()
+ runner = DebugRunner(optionflags=self._dt_optionflags,
+ checker=self._dt_checker, verbose=False)
+ runner.run(self._dt_test)
+ self.tearDown()
+
+ def id(self):
+ return self._dt_test.name
+
+ def __repr__(self):
+ name = self._dt_test.name.split('.')
+ return "%s (%s)" % (name[-1], '.'.join(name[:-1]))
+
+ __str__ = __repr__
+
+ def shortDescription(self):
+ return "Doctest: " + self._dt_test.name
+
+def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
+ test_class=DocTestCase, **options):
+ """
+ Convert doctest tests for a module to a unittest test suite.
+
+ This converts each documentation string in a module that
+ contains doctest tests to a unittest test case. If any of the
+ tests in a doc string fail, then the test case fails. An exception
+ is raised showing the name of the file containing the test and a
+ (sometimes approximate) line number.
+
+ The `module` argument provides the module to be tested. The argument
+ can be either a module or a module name.
+
+ If no argument is given, the calling module is used.
+
+ A number of options may be provided as keyword arguments:
+
+ setUp
+ A set-up function. This is called before running the
+ tests in each file. The setUp function will be passed a DocTest
+ object. The setUp function can access the test globals as the
+ globs attribute of the test passed.
+
+ tearDown
+ A tear-down function. This is called after running the
+ tests in each file. The tearDown function will be passed a DocTest
+ object. The tearDown function can access the test globals as the
+ globs attribute of the test passed.
+
+ globs
+ A dictionary containing initial global variables for the tests.
+
+ optionflags
+ A set of doctest option flags expressed as an integer.
+ """
+
+ if test_finder is None:
+ test_finder = DocTestFinder()
+
+ module = _normalize_module(module)
+ tests = test_finder.find(module, globs=globs, extraglobs=extraglobs)
+ if globs is None:
+ globs = module.__dict__
+ if not tests:
+ # Why do we want to do this? Because it reveals a bug that might
+ # otherwise be hidden.
+ raise ValueError(module, "has no tests")
+
+ tests.sort()
+ suite = unittest.TestSuite()
+ for test in tests:
+ if len(test.examples) == 0:
+ continue
+ if not test.filename:
+ filename = module.__file__
+ if filename[-4:] in (".pyc", ".pyo"):
+ filename = filename[:-1]
+ test.filename = filename
+ suite.addTest(test_class(test, **options))
+
+ return suite
+
+class DocFileCase(DocTestCase):
+
+ def id(self):
+ return '_'.join(self._dt_test.name.split('.'))
+
+ def __repr__(self):
+ return self._dt_test.filename
+ __str__ = __repr__
+
+ def format_failure(self, err):
+ return ('Failed doctest test for %s\n File "%s", line 0\n\n%s'
+ % (self._dt_test.name, self._dt_test.filename, err)
+ )
+
+def DocFileTest(path, module_relative=True, package=None,
+ globs=None, parser=DocTestParser(),
+ encoding=None, **options):
+ if globs is None:
+ globs = {}
+ else:
+ globs = globs.copy()
+
+ if package and not module_relative:
+ raise ValueError("Package may only be specified for module-"
+ "relative paths.")
+
+ # Relativize the path.
+ doc, path = _load_testfile(path, package, module_relative)
+
+ if "__file__" not in globs:
+ globs["__file__"] = path
+
+ # Find the file and read it.
+ name = os.path.basename(path)
+
+ # If an encoding is specified, use it to convert the file to unicode
+ if encoding is not None:
+ doc = doc.decode(encoding)
+
+ # Convert it to a test, and wrap it in a DocFileCase.
+ test = parser.get_doctest(doc, globs, name, path, 0)
+ return DocFileCase(test, **options)
+
+def DocFileSuite(*paths, **kw):
+ """A unittest suite for one or more doctest files.
+
+ The path to each doctest file is given as a string; the
+ interpretation of that string depends on the keyword argument
+ "module_relative".
+
+ A number of options may be provided as keyword arguments:
+
+ module_relative
+ If "module_relative" is True, then the given file paths are
+ interpreted as os-independent module-relative paths. By
+ default, these paths are relative to the calling module's
+ directory; but if the "package" argument is specified, then
+ they are relative to that package. To ensure os-independence,
+ "filename" should use "/" characters to separate path
+ segments, and may not be an absolute path (i.e., it may not
+ begin with "/").
+
+ If "module_relative" is False, then the given file paths are
+ interpreted as os-specific paths. These paths may be absolute
+ or relative (to the current working directory).
+
+ package
+ A Python package or the name of a Python package whose directory
+ should be used as the base directory for module relative paths.
+ If "package" is not specified, then the calling module's
+ directory is used as the base directory for module relative
+ filenames. It is an error to specify "package" if
+ "module_relative" is False.
+
+ setUp
+ A set-up function. This is called before running the
+ tests in each file. The setUp function will be passed a DocTest
+ object. The setUp function can access the test globals as the
+ globs attribute of the test passed.
+
+ tearDown
+ A tear-down function. This is called after running the
+ tests in each file. The tearDown function will be passed a DocTest
+ object. The tearDown function can access the test globals as the
+ globs attribute of the test passed.
+
+ globs
+ A dictionary containing initial global variables for the tests.
+
+ optionflags
+ A set of doctest option flags expressed as an integer.
+
+ parser
+ A DocTestParser (or subclass) that should be used to extract
+ tests from the files.
+
+ encoding
+ An encoding that will be used to convert the files to unicode.
+ """
+ suite = unittest.TestSuite()
+
+ # We do this here so that _normalize_module is called at the right
+ # level. If it were called in DocFileTest, then this function
+ # would be the caller and we might guess the package incorrectly.
+ if kw.get('module_relative', True):
+ kw['package'] = _normalize_module(kw.get('package'))
+
+ for path in paths:
+ suite.addTest(DocFileTest(path, **kw))
+
+ return suite
+
+######################################################################
+## 9. Debugging Support
+######################################################################
+
+def script_from_examples(s):
+ r"""Extract script from text with examples.
+
+ Converts text with examples to a Python script. Example input is
+ converted to regular code. Example output and all other words
+ are converted to comments:
+
+ >>> text = '''
+ ... Here are examples of simple math.
+ ...
+ ... Python has super accurate integer addition
+ ...
+ ... >>> 2 + 2
+ ... 5
+ ...
+ ... And very friendly error messages:
+ ...
+ ... >>> 1/0
+ ... To Infinity
+ ... And
+ ... Beyond
+ ...
+ ... You can use logic if you want:
+ ...
+ ... >>> if 0:
+ ... ... blah
+ ... ... blah
+ ... ...
+ ...
+ ... Ho hum
+ ... '''
+
+ >>> print(script_from_examples(text))
+ # Here are examples of simple math.
+ #
+ # Python has super accurate integer addition
+ #
+ 2 + 2
+ # Expected:
+ ## 5
+ #
+ # And very friendly error messages:
+ #
+ 1/0
+ # Expected:
+ ## To Infinity
+ ## And
+ ## Beyond
+ #
+ # You can use logic if you want:
+ #
+ if 0:
+ blah
+ blah
+ #
+ # Ho hum
+ """
+ output = []
+ for piece in DocTestParser().parse(s):
+ if isinstance(piece, Example):
+ # Add the example's source code (strip trailing NL)
+ output.append(piece.source[:-1])
+ # Add the expected output:
+ want = piece.want
+ if want:
+ output.append('# Expected:')
+ output += ['## '+l for l in want.split('\n')[:-1]]
+ else:
+ # Add non-example text.
+ output += [_comment_line(l)
+ for l in piece.split('\n')[:-1]]
+
+ # Trim junk on both ends.
+ while output and output[-1] == '#':
+ output.pop()
+ while output and output[0] == '#':
+ output.pop(0)
+ # Combine the output, and return it.
+ return '\n'.join(output)
+
+def testsource(module, name):
+ """Extract the test sources from a doctest docstring as a script.
+
+ Provide the module (or dotted name of the module) containing the
+ test to be debugged and the name (within the module) of the object
+ with the doc string with tests to be debugged.
+ """
+ module = _normalize_module(module)
+ tests = DocTestFinder().find(module)
+ test = [t for t in tests if t.name == name]
+ if not test:
+ raise ValueError(name, "not found in tests")
+ test = test[0]
+ testsrc = script_from_examples(test.docstring)
+ return testsrc
+
+def debug_src(src, pm=False, globs=None):
+ """Debug a single doctest docstring, in argument `src`'"""
+ testsrc = script_from_examples(src)
+ debug_script(testsrc, pm, globs)
+
+def debug_script(src, pm=False, globs=None):
+ "Debug a test script. `src` is the script, as a string."
+ import pdb
+
+ # Note that tempfile.NameTemporaryFile() cannot be used. As the
+ # docs say, a file so created cannot be opened by name a second time
+ # on modern Windows boxes, and execfile() needs to open it.
+ srcfilename = tempfile.mktemp(".py", "doctestdebug")
+ with open(srcfilename, 'w') as fp:
+ fp.write(src)
+
+ try:
+ if globs:
+ globs = globs.copy()
+ else:
+ globs = {}
+
+ if pm:
+ try:
+ execfile(srcfilename, globs, globs)
+ except:
+ print(sys.exc_info()[1])
+ pdb.post_mortem(sys.exc_info()[2])
+ else:
+ # Note that %r is vital here. '%s' instead can, e.g., cause
+ # backslashes to get treated as metacharacters on Windows.
+ pdb.run("execfile(%r)" % srcfilename, globs, globs)
+
+ finally:
+ os.remove(srcfilename)
+
+def debug(module, name, pm=False):
+ """Debug a single doctest docstring.
+
+ Provide the module (or dotted name of the module) containing the
+ test to be debugged and the name (within the module) of the object
+ with the docstring with tests to be debugged.
+ """
+ module = _normalize_module(module)
+ testsrc = testsource(module, name)
+ debug_script(testsrc, pm, module.__dict__)
+
+######################################################################
+## 10. Example Usage
+######################################################################
+class _TestClass:
+ """
+ A pointless class, for sanity-checking of docstring testing.
+
+ Methods:
+ square()
+ get()
+
+ >>> _TestClass(13).get() + _TestClass(-12).get()
+ 1
+ >>> hex(_TestClass(13).square().get())
+ '0xa9'
+ """
+
+ def __init__(self, val):
+ """val -> _TestClass object with associated value val.
+
+ >>> t = _TestClass(123)
+ >>> print(t.get())
+ 123
+ """
+
+ self.val = val
+
+ def square(self):
+ """square() -> square TestClass's associated value
+
+ >>> _TestClass(13).square().get()
+ 169
+ """
+
+ self.val = self.val ** 2
+ return self
+
+ def get(self):
+ """get() -> return TestClass's associated value.
+
+ >>> x = _TestClass(-42)
+ >>> print(x.get())
+ -42
+ """
+
+ return self.val
+
+__test__ = {"_TestClass": _TestClass,
+ "string": r"""
+ Example of a string object, searched as-is.
+ >>> x = 1; y = 2
+ >>> x + y, x * y
+ (3, 2)
+ """,
+
+ "bool-int equivalence": r"""
+ In 2.2, boolean expressions displayed
+ 0 or 1. By default, we still accept
+ them. This can be disabled by passing
+ DONT_ACCEPT_TRUE_FOR_1 to the new
+ optionflags argument.
+ >>> 4 == 4
+ 1
+ >>> 4 == 4
+ True
+ >>> 4 > 4
+ 0
+ >>> 4 > 4
+ False
+ """,
+
+ "blank lines": r"""
+ Blank lines can be marked with <BLANKLINE>:
+ >>> print('foo\n\nbar\n')
+ foo
+ <BLANKLINE>
+ bar
+ <BLANKLINE>
+ """,
+
+ "ellipsis": r"""
+ If the ellipsis flag is used, then '...' can be used to
+ elide substrings in the desired output:
+ >>> print(range(1000)) #doctest: +ELLIPSIS
+ [0, 1, 2, ..., 999]
+ """,
+
+ "whitespace normalization": r"""
+ If the whitespace normalization flag is used, then
+ differences in whitespace are ignored.
+ >>> print(list(xrange(30))) #doctest: +NORMALIZE_WHITESPACE
+ [0, 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]
+ """,
+ }
+
+def _test():
+ r = unittest.TextTestRunner()
+ r.run(DocTestSuite())
+
+if __name__ == "__main__":
+ _test()
diff --git a/lib/python2.7/site-packages/django/test/client.py b/lib/python2.7/site-packages/django/test/client.py
new file mode 100644
index 0000000..6ea8119
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/client.py
@@ -0,0 +1,623 @@
+from __future__ import unicode_literals
+
+import sys
+import os
+import re
+import mimetypes
+from copy import copy
+from io import BytesIO
+
+from django.conf import settings
+from django.contrib.auth import authenticate, login, logout, get_user_model
+from django.core.handlers.base import BaseHandler
+from django.core.handlers.wsgi import WSGIRequest
+from django.core.signals import (request_started, request_finished,
+ got_request_exception)
+from django.db import close_old_connections
+from django.http import SimpleCookie, HttpRequest, QueryDict
+from django.template import TemplateDoesNotExist
+from django.test import signals
+from django.utils.functional import curry
+from django.utils.encoding import force_bytes, force_str
+from django.utils.http import urlencode
+from django.utils.importlib import import_module
+from django.utils.itercompat import is_iterable
+from django.utils import six
+from django.utils.six.moves.urllib.parse import unquote, urlparse, urlsplit
+from django.test.utils import ContextList
+
+__all__ = ('Client', 'RequestFactory', 'encode_file', 'encode_multipart')
+
+
+BOUNDARY = 'BoUnDaRyStRiNg'
+MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
+CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
+
+class FakePayload(object):
+ """
+ A wrapper around BytesIO that restricts what can be read since data from
+ the network can't be seeked and cannot be read outside of its content
+ length. This makes sure that views can't do anything under the test client
+ that wouldn't work in Real Life.
+ """
+ def __init__(self, content=None):
+ self.__content = BytesIO()
+ self.__len = 0
+ self.read_started = False
+ if content is not None:
+ self.write(content)
+
+ def __len__(self):
+ return self.__len
+
+ def read(self, num_bytes=None):
+ if not self.read_started:
+ self.__content.seek(0)
+ self.read_started = True
+ if num_bytes is None:
+ num_bytes = self.__len or 0
+ assert self.__len >= num_bytes, "Cannot read more than the available bytes from the HTTP incoming data."
+ content = self.__content.read(num_bytes)
+ self.__len -= num_bytes
+ return content
+
+ def write(self, content):
+ if self.read_started:
+ raise ValueError("Unable to write a payload after he's been read")
+ content = force_bytes(content)
+ self.__content.write(content)
+ self.__len += len(content)
+
+
+def closing_iterator_wrapper(iterable, close):
+ try:
+ for item in iterable:
+ yield item
+ finally:
+ request_finished.disconnect(close_old_connections)
+ close() # will fire request_finished
+ request_finished.connect(close_old_connections)
+
+
+class ClientHandler(BaseHandler):
+ """
+ A HTTP Handler that can be used for testing purposes.
+ Uses the WSGI interface to compose requests, but returns
+ the raw HttpResponse object
+ """
+ def __init__(self, enforce_csrf_checks=True, *args, **kwargs):
+ self.enforce_csrf_checks = enforce_csrf_checks
+ super(ClientHandler, self).__init__(*args, **kwargs)
+
+ def __call__(self, environ):
+ from django.conf import settings
+
+ # Set up middleware if needed. We couldn't do this earlier, because
+ # settings weren't available.
+ if self._request_middleware is None:
+ self.load_middleware()
+
+ request_started.disconnect(close_old_connections)
+ request_started.send(sender=self.__class__)
+ request_started.connect(close_old_connections)
+ request = WSGIRequest(environ)
+ # sneaky little hack so that we can easily get round
+ # CsrfViewMiddleware. This makes life easier, and is probably
+ # required for backwards compatibility with external tests against
+ # admin views.
+ request._dont_enforce_csrf_checks = not self.enforce_csrf_checks
+ response = self.get_response(request)
+ # We're emulating a WSGI server; we must call the close method
+ # on completion.
+ if response.streaming:
+ response.streaming_content = closing_iterator_wrapper(
+ response.streaming_content, response.close)
+ else:
+ request_finished.disconnect(close_old_connections)
+ response.close() # will fire request_finished
+ request_finished.connect(close_old_connections)
+
+ return response
+
+def store_rendered_templates(store, signal, sender, template, context, **kwargs):
+ """
+ Stores templates and contexts that are rendered.
+
+ The context is copied so that it is an accurate representation at the time
+ of rendering.
+ """
+ store.setdefault('templates', []).append(template)
+ store.setdefault('context', ContextList()).append(copy(context))
+
+def encode_multipart(boundary, data):
+ """
+ Encodes multipart POST data from a dictionary of form values.
+
+ The key will be used as the form data name; the value will be transmitted
+ as content. If the value is a file, the contents of the file will be sent
+ as an application/octet-stream; otherwise, str(value) will be sent.
+ """
+ lines = []
+ to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
+
+ # Not by any means perfect, but good enough for our purposes.
+ is_file = lambda thing: hasattr(thing, "read") and callable(thing.read)
+
+ # Each bit of the multipart form data could be either a form value or a
+ # file, or a *list* of form values and/or files. Remember that HTTP field
+ # names can be duplicated!
+ for (key, value) in data.items():
+ if is_file(value):
+ lines.extend(encode_file(boundary, key, value))
+ elif not isinstance(value, six.string_types) and is_iterable(value):
+ for item in value:
+ if is_file(item):
+ lines.extend(encode_file(boundary, key, item))
+ else:
+ lines.extend([to_bytes(val) for val in [
+ '--%s' % boundary,
+ 'Content-Disposition: form-data; name="%s"' % key,
+ '',
+ item
+ ]])
+ else:
+ lines.extend([to_bytes(val) for val in [
+ '--%s' % boundary,
+ 'Content-Disposition: form-data; name="%s"' % key,
+ '',
+ value
+ ]])
+
+ lines.extend([
+ to_bytes('--%s--' % boundary),
+ b'',
+ ])
+ return b'\r\n'.join(lines)
+
+def encode_file(boundary, key, file):
+ to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
+ content_type = mimetypes.guess_type(file.name)[0]
+ if content_type is None:
+ content_type = 'application/octet-stream'
+ return [
+ to_bytes('--%s' % boundary),
+ to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"' \
+ % (key, os.path.basename(file.name))),
+ to_bytes('Content-Type: %s' % content_type),
+ b'',
+ file.read()
+ ]
+
+
+class RequestFactory(object):
+ """
+ Class that lets you create mock Request objects for use in testing.
+
+ Usage:
+
+ rf = RequestFactory()
+ get_request = rf.get('/hello/')
+ post_request = rf.post('/submit/', {'foo': 'bar'})
+
+ Once you have a request object you can pass it to any view function,
+ just as if that view had been hooked up using a URLconf.
+ """
+ def __init__(self, **defaults):
+ self.defaults = defaults
+ self.cookies = SimpleCookie()
+ self.errors = BytesIO()
+
+ def _base_environ(self, **request):
+ """
+ The base environment for a request.
+ """
+ # This is a minimal valid WSGI environ dictionary, plus:
+ # - HTTP_COOKIE: for cookie support,
+ # - REMOTE_ADDR: often useful, see #8551.
+ # See http://www.python.org/dev/peps/pep-3333/#environ-variables
+ environ = {
+ 'HTTP_COOKIE': self.cookies.output(header='', sep='; '),
+ 'PATH_INFO': str('/'),
+ 'REMOTE_ADDR': str('127.0.0.1'),
+ 'REQUEST_METHOD': str('GET'),
+ 'SCRIPT_NAME': str(''),
+ 'SERVER_NAME': str('testserver'),
+ 'SERVER_PORT': str('80'),
+ 'SERVER_PROTOCOL': str('HTTP/1.1'),
+ 'wsgi.version': (1, 0),
+ 'wsgi.url_scheme': str('http'),
+ 'wsgi.input': FakePayload(b''),
+ 'wsgi.errors': self.errors,
+ 'wsgi.multiprocess': True,
+ 'wsgi.multithread': False,
+ 'wsgi.run_once': False,
+ }
+ environ.update(self.defaults)
+ environ.update(request)
+ return environ
+
+ def request(self, **request):
+ "Construct a generic request object."
+ return WSGIRequest(self._base_environ(**request))
+
+ def _encode_data(self, data, content_type, ):
+ if content_type is MULTIPART_CONTENT:
+ return encode_multipart(BOUNDARY, data)
+ else:
+ # Encode the content so that the byte representation is correct.
+ match = CONTENT_TYPE_RE.match(content_type)
+ if match:
+ charset = match.group(1)
+ else:
+ charset = settings.DEFAULT_CHARSET
+ return force_bytes(data, encoding=charset)
+
+ def _get_path(self, parsed):
+ path = force_str(parsed[2])
+ # If there are parameters, add them
+ if parsed[3]:
+ path += str(";") + force_str(parsed[3])
+ path = unquote(path)
+ # WSGI requires latin-1 encoded strings. See get_path_info().
+ if six.PY3:
+ path = path.encode('utf-8').decode('iso-8859-1')
+ return path
+
+ def get(self, path, data={}, **extra):
+ "Construct a GET request."
+
+ parsed = urlparse(path)
+ query_string = urlencode(data, doseq=True) or force_str(parsed[4])
+ if six.PY3:
+ query_string = query_string.encode('utf-8').decode('iso-8859-1')
+
+ r = {
+ 'PATH_INFO': self._get_path(parsed),
+ 'QUERY_STRING': query_string,
+ 'REQUEST_METHOD': str('GET'),
+ }
+ r.update(extra)
+ return self.request(**r)
+
+ def post(self, path, data={}, content_type=MULTIPART_CONTENT,
+ **extra):
+ "Construct a POST request."
+
+ post_data = self._encode_data(data, content_type)
+
+ parsed = urlparse(path)
+ query_string = force_str(parsed[4])
+ if six.PY3:
+ query_string = query_string.encode('utf-8').decode('iso-8859-1')
+
+ r = {
+ 'CONTENT_LENGTH': len(post_data),
+ 'CONTENT_TYPE': content_type,
+ 'PATH_INFO': self._get_path(parsed),
+ 'QUERY_STRING': query_string,
+ 'REQUEST_METHOD': str('POST'),
+ 'wsgi.input': FakePayload(post_data),
+ }
+ r.update(extra)
+ return self.request(**r)
+
+ def head(self, path, data={}, **extra):
+ "Construct a HEAD request."
+
+ parsed = urlparse(path)
+ query_string = urlencode(data, doseq=True) or force_str(parsed[4])
+ if six.PY3:
+ query_string = query_string.encode('utf-8').decode('iso-8859-1')
+
+ r = {
+ 'PATH_INFO': self._get_path(parsed),
+ 'QUERY_STRING': query_string,
+ 'REQUEST_METHOD': str('HEAD'),
+ }
+ r.update(extra)
+ return self.request(**r)
+
+ def options(self, path, data='', content_type='application/octet-stream',
+ **extra):
+ "Construct an OPTIONS request."
+ return self.generic('OPTIONS', path, data, content_type, **extra)
+
+ def put(self, path, data='', content_type='application/octet-stream',
+ **extra):
+ "Construct a PUT request."
+ return self.generic('PUT', path, data, content_type, **extra)
+
+ def patch(self, path, data='', content_type='application/octet-stream',
+ **extra):
+ "Construct a PATCH request."
+ return self.generic('PATCH', path, data, content_type, **extra)
+
+ def delete(self, path, data='', content_type='application/octet-stream',
+ **extra):
+ "Construct a DELETE request."
+ return self.generic('DELETE', path, data, content_type, **extra)
+
+ def generic(self, method, path,
+ data='', content_type='application/octet-stream', **extra):
+ parsed = urlparse(path)
+ data = force_bytes(data, settings.DEFAULT_CHARSET)
+ r = {
+ 'PATH_INFO': self._get_path(parsed),
+ 'REQUEST_METHOD': str(method),
+ }
+ if data:
+ r.update({
+ 'CONTENT_LENGTH': len(data),
+ 'CONTENT_TYPE': str(content_type),
+ 'wsgi.input': FakePayload(data),
+ })
+ r.update(extra)
+ # If QUERY_STRING is absent or empty, we want to extract it from the URL.
+ if not r.get('QUERY_STRING'):
+ query_string = force_bytes(parsed[4])
+ # WSGI requires latin-1 encoded strings. See get_path_info().
+ if six.PY3:
+ query_string = query_string.decode('iso-8859-1')
+ r['QUERY_STRING'] = query_string
+ return self.request(**r)
+
+
+class Client(RequestFactory):
+ """
+ A class that can act as a client for testing purposes.
+
+ It allows the user to compose GET and POST requests, and
+ obtain the response that the server gave to those requests.
+ The server Response objects are annotated with the details
+ of the contexts and templates that were rendered during the
+ process of serving the request.
+
+ Client objects are stateful - they will retain cookie (and
+ thus session) details for the lifetime of the Client instance.
+
+ This is not intended as a replacement for Twill/Selenium or
+ the like - it is here to allow testing against the
+ contexts and templates produced by a view, rather than the
+ HTML rendered to the end-user.
+ """
+ def __init__(self, enforce_csrf_checks=False, **defaults):
+ super(Client, self).__init__(**defaults)
+ self.handler = ClientHandler(enforce_csrf_checks)
+ self.exc_info = None
+
+ def store_exc_info(self, **kwargs):
+ """
+ Stores exceptions when they are generated by a view.
+ """
+ self.exc_info = sys.exc_info()
+
+ def _session(self):
+ """
+ Obtains the current session variables.
+ """
+ if 'django.contrib.sessions' in settings.INSTALLED_APPS:
+ engine = import_module(settings.SESSION_ENGINE)
+ cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
+ if cookie:
+ return engine.SessionStore(cookie.value)
+ return {}
+ session = property(_session)
+
+
+ def request(self, **request):
+ """
+ The master request method. Composes the environment dictionary
+ and passes to the handler, returning the result of the handler.
+ Assumes defaults for the query environment, which can be overridden
+ using the arguments to the request.
+ """
+ environ = self._base_environ(**request)
+
+ # Curry a data dictionary into an instance of the template renderer
+ # callback function.
+ data = {}
+ on_template_render = curry(store_rendered_templates, data)
+ signals.template_rendered.connect(on_template_render, dispatch_uid="template-render")
+ # Capture exceptions created by the handler.
+ got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
+ try:
+
+ try:
+ response = self.handler(environ)
+ except TemplateDoesNotExist as e:
+ # If the view raises an exception, Django will attempt to show
+ # the 500.html template. If that template is not available,
+ # we should ignore the error in favor of re-raising the
+ # underlying exception that caused the 500 error. Any other
+ # template found to be missing during view error handling
+ # should be reported as-is.
+ if e.args != ('500.html',):
+ raise
+
+ # Look for a signalled exception, clear the current context
+ # exception data, then re-raise the signalled exception.
+ # Also make sure that the signalled exception is cleared from
+ # the local cache!
+ if self.exc_info:
+ exc_info = self.exc_info
+ self.exc_info = None
+ six.reraise(*exc_info)
+
+ # Save the client and request that stimulated the response.
+ response.client = self
+ response.request = request
+
+ # Add any rendered template detail to the response.
+ response.templates = data.get("templates", [])
+ response.context = data.get("context")
+
+ # Flatten a single context. Not really necessary anymore thanks to
+ # the __getattr__ flattening in ContextList, but has some edge-case
+ # backwards-compatibility implications.
+ if response.context and len(response.context) == 1:
+ response.context = response.context[0]
+
+ # Update persistent cookie data.
+ if response.cookies:
+ self.cookies.update(response.cookies)
+
+ return response
+ finally:
+ signals.template_rendered.disconnect(dispatch_uid="template-render")
+ got_request_exception.disconnect(dispatch_uid="request-exception")
+
+ def get(self, path, data={}, follow=False, **extra):
+ """
+ Requests a response from the server using GET.
+ """
+ response = super(Client, self).get(path, data=data, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def post(self, path, data={}, content_type=MULTIPART_CONTENT,
+ follow=False, **extra):
+ """
+ Requests a response from the server using POST.
+ """
+ response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def head(self, path, data={}, follow=False, **extra):
+ """
+ Request a response from the server using HEAD.
+ """
+ response = super(Client, self).head(path, data=data, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def options(self, path, data='', content_type='application/octet-stream',
+ follow=False, **extra):
+ """
+ Request a response from the server using OPTIONS.
+ """
+ response = super(Client, self).options(path,
+ data=data, content_type=content_type, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def put(self, path, data='', content_type='application/octet-stream',
+ follow=False, **extra):
+ """
+ Send a resource to the server using PUT.
+ """
+ response = super(Client, self).put(path,
+ data=data, content_type=content_type, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def patch(self, path, data='', content_type='application/octet-stream',
+ follow=False, **extra):
+ """
+ Send a resource to the server using PATCH.
+ """
+ response = super(Client, self).patch(
+ path, data=data, content_type=content_type, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def delete(self, path, data='', content_type='application/octet-stream',
+ follow=False, **extra):
+ """
+ Send a DELETE request to the server.
+ """
+ response = super(Client, self).delete(path,
+ data=data, content_type=content_type, **extra)
+ if follow:
+ response = self._handle_redirects(response, **extra)
+ return response
+
+ def login(self, **credentials):
+ """
+ Sets the Factory to appear as if it has successfully logged into a site.
+
+ Returns True if login is possible; False if the provided credentials
+ are incorrect, or the user is inactive, or if the sessions framework is
+ not available.
+ """
+ user = authenticate(**credentials)
+ if user and user.is_active \
+ and 'django.contrib.sessions' in settings.INSTALLED_APPS:
+ engine = import_module(settings.SESSION_ENGINE)
+
+ # Create a fake request to store login details.
+ request = HttpRequest()
+ if self.session:
+ request.session = self.session
+ else:
+ request.session = engine.SessionStore()
+ login(request, user)
+
+ # Save the session values.
+ request.session.save()
+
+ # Set the cookie to represent the session.
+ session_cookie = settings.SESSION_COOKIE_NAME
+ self.cookies[session_cookie] = request.session.session_key
+ cookie_data = {
+ 'max-age': None,
+ 'path': '/',
+ 'domain': settings.SESSION_COOKIE_DOMAIN,
+ 'secure': settings.SESSION_COOKIE_SECURE or None,
+ 'expires': None,
+ }
+ self.cookies[session_cookie].update(cookie_data)
+
+ return True
+ else:
+ return False
+
+ def logout(self):
+ """
+ Removes the authenticated user's cookies and session object.
+
+ Causes the authenticated user to be logged out.
+ """
+ request = HttpRequest()
+ engine = import_module(settings.SESSION_ENGINE)
+ UserModel = get_user_model()
+ if self.session:
+ request.session = self.session
+ uid = self.session.get("_auth_user_id")
+ if uid:
+ request.user = UserModel._default_manager.get(pk=uid)
+ else:
+ request.session = engine.SessionStore()
+ logout(request)
+ self.cookies = SimpleCookie()
+
+ def _handle_redirects(self, response, **extra):
+ "Follows any redirects by requesting responses from the server using GET."
+
+ response.redirect_chain = []
+ while response.status_code in (301, 302, 303, 307):
+ url = response.url
+ redirect_chain = response.redirect_chain
+ redirect_chain.append((url, response.status_code))
+
+ url = urlsplit(url)
+ if url.scheme:
+ extra['wsgi.url_scheme'] = url.scheme
+ if url.hostname:
+ extra['SERVER_NAME'] = url.hostname
+ if url.port:
+ extra['SERVER_PORT'] = str(url.port)
+
+ response = self.get(url.path, QueryDict(url.query), follow=False, **extra)
+ response.redirect_chain = redirect_chain
+
+ # Prevent loops
+ if response.redirect_chain[-1] in response.redirect_chain[0:-1]:
+ break
+ return response
diff --git a/lib/python2.7/site-packages/django/test/html.py b/lib/python2.7/site-packages/django/test/html.py
new file mode 100644
index 0000000..0d30bd2
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/html.py
@@ -0,0 +1,238 @@
+"""
+Comparing two html documents.
+"""
+
+from __future__ import unicode_literals
+
+import re
+from django.utils.encoding import force_text
+from django.utils.html_parser import HTMLParser, HTMLParseError
+from django.utils import six
+from django.utils.encoding import python_2_unicode_compatible
+
+
+WHITESPACE = re.compile('\s+')
+
+
+def normalize_whitespace(string):
+ return WHITESPACE.sub(' ', string)
+
+
+@python_2_unicode_compatible
+class Element(object):
+ def __init__(self, name, attributes):
+ self.name = name
+ self.attributes = sorted(attributes)
+ self.children = []
+
+ def append(self, element):
+ if isinstance(element, six.string_types):
+ element = force_text(element)
+ element = normalize_whitespace(element)
+ if self.children:
+ if isinstance(self.children[-1], six.string_types):
+ self.children[-1] += element
+ self.children[-1] = normalize_whitespace(self.children[-1])
+ return
+ elif self.children:
+ # removing last children if it is only whitespace
+ # this can result in incorrect dom representations since
+ # whitespace between inline tags like <span> is significant
+ if isinstance(self.children[-1], six.string_types):
+ if self.children[-1].isspace():
+ self.children.pop()
+ if element:
+ self.children.append(element)
+
+ def finalize(self):
+ def rstrip_last_element(children):
+ if children:
+ if isinstance(children[-1], six.string_types):
+ children[-1] = children[-1].rstrip()
+ if not children[-1]:
+ children.pop()
+ children = rstrip_last_element(children)
+ return children
+
+ rstrip_last_element(self.children)
+ for i, child in enumerate(self.children):
+ if isinstance(child, six.string_types):
+ self.children[i] = child.strip()
+ elif hasattr(child, 'finalize'):
+ child.finalize()
+
+ def __eq__(self, element):
+ if not hasattr(element, 'name'):
+ return False
+ if hasattr(element, 'name') and self.name != element.name:
+ return False
+ if len(self.attributes) != len(element.attributes):
+ return False
+ if self.attributes != element.attributes:
+ # attributes without a value is same as attribute with value that
+ # equals the attributes name:
+ # <input checked> == <input checked="checked">
+ for i in range(len(self.attributes)):
+ attr, value = self.attributes[i]
+ other_attr, other_value = element.attributes[i]
+ if value is None:
+ value = attr
+ if other_value is None:
+ other_value = other_attr
+ if attr != other_attr or value != other_value:
+ return False
+ if self.children != element.children:
+ return False
+ return True
+
+ def __hash__(self):
+ return hash((self.name,) + tuple(a for a in self.attributes))
+
+ def __ne__(self, element):
+ return not self.__eq__(element)
+
+ def _count(self, element, count=True):
+ if not isinstance(element, six.string_types):
+ if self == element:
+ return 1
+ i = 0
+ for child in self.children:
+ # child is text content and element is also text content, then
+ # make a simple "text" in "text"
+ if isinstance(child, six.string_types):
+ if isinstance(element, six.string_types):
+ if count:
+ i += child.count(element)
+ elif element in child:
+ return 1
+ else:
+ i += child._count(element, count=count)
+ if not count and i:
+ return i
+ return i
+
+ def __contains__(self, element):
+ return self._count(element, count=False) > 0
+
+ def count(self, element):
+ return self._count(element, count=True)
+
+ def __getitem__(self, key):
+ return self.children[key]
+
+ def __str__(self):
+ output = '<%s' % self.name
+ for key, value in self.attributes:
+ if value:
+ output += ' %s="%s"' % (key, value)
+ else:
+ output += ' %s' % key
+ if self.children:
+ output += '>\n'
+ output += ''.join(six.text_type(c) for c in self.children)
+ output += '\n</%s>' % self.name
+ else:
+ output += ' />'
+ return output
+
+ def __repr__(self):
+ return six.text_type(self)
+
+
+@python_2_unicode_compatible
+class RootElement(Element):
+ def __init__(self):
+ super(RootElement, self).__init__(None, ())
+
+ def __str__(self):
+ return ''.join(six.text_type(c) for c in self.children)
+
+
+class Parser(HTMLParser):
+ SELF_CLOSING_TAGS = ('br' , 'hr', 'input', 'img', 'meta', 'spacer',
+ 'link', 'frame', 'base', 'col')
+
+ def __init__(self):
+ HTMLParser.__init__(self)
+ self.root = RootElement()
+ self.open_tags = []
+ self.element_positions = {}
+
+ def error(self, msg):
+ raise HTMLParseError(msg, self.getpos())
+
+ def format_position(self, position=None, element=None):
+ if not position and element:
+ position = self.element_positions[element]
+ if position is None:
+ position = self.getpos()
+ if hasattr(position, 'lineno'):
+ position = position.lineno, position.offset
+ return 'Line %d, Column %d' % position
+
+ @property
+ def current(self):
+ if self.open_tags:
+ return self.open_tags[-1]
+ else:
+ return self.root
+
+ def handle_startendtag(self, tag, attrs):
+ self.handle_starttag(tag, attrs)
+ if tag not in self.SELF_CLOSING_TAGS:
+ self.handle_endtag(tag)
+
+ def handle_starttag(self, tag, attrs):
+ # Special case handling of 'class' attribute, so that comparisons of DOM
+ # instances are not sensitive to ordering of classes.
+ attrs = [
+ (name, " ".join(sorted(value.split(" "))))
+ if name == "class"
+ else (name, value)
+ for name, value in attrs
+ ]
+ element = Element(tag, attrs)
+ self.current.append(element)
+ if tag not in self.SELF_CLOSING_TAGS:
+ self.open_tags.append(element)
+ self.element_positions[element] = self.getpos()
+
+ def handle_endtag(self, tag):
+ if not self.open_tags:
+ self.error("Unexpected end tag `%s` (%s)" % (
+ tag, self.format_position()))
+ element = self.open_tags.pop()
+ while element.name != tag:
+ if not self.open_tags:
+ self.error("Unexpected end tag `%s` (%s)" % (
+ tag, self.format_position()))
+ element = self.open_tags.pop()
+
+ def handle_data(self, data):
+ self.current.append(data)
+
+ def handle_charref(self, name):
+ self.current.append('&%s;' % name)
+
+ def handle_entityref(self, name):
+ self.current.append('&%s;' % name)
+
+
+def parse_html(html):
+ """
+ Takes a string that contains *valid* HTML and turns it into a Python object
+ structure that can be easily compared against other HTML on semantic
+ equivalence. Syntactical differences like which quotation is used on
+ arguments will be ignored.
+
+ """
+ parser = Parser()
+ parser.feed(html)
+ parser.close()
+ document = parser.root
+ document.finalize()
+ # Removing ROOT element if it's not necessary
+ if len(document.children) == 1:
+ if not isinstance(document.children[0], six.string_types):
+ document = document.children[0]
+ return document
diff --git a/lib/python2.7/site-packages/django/test/runner.py b/lib/python2.7/site-packages/django/test/runner.py
new file mode 100644
index 0000000..d8db8da
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/runner.py
@@ -0,0 +1,291 @@
+import os
+from optparse import make_option
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.test import TestCase
+from django.test.utils import setup_test_environment, teardown_test_environment
+from django.utils import unittest
+from django.utils.unittest import TestSuite, defaultTestLoader
+
+
+class DiscoverRunner(object):
+ """
+ A Django test runner that uses unittest2 test discovery.
+ """
+
+ test_loader = defaultTestLoader
+ reorder_by = (TestCase, )
+ option_list = (
+ make_option('-t', '--top-level-directory',
+ action='store', dest='top_level', default=None,
+ help='Top level of project for unittest discovery.'),
+ make_option('-p', '--pattern', action='store', dest='pattern',
+ default="test*.py",
+ help='The test matching pattern. Defaults to test*.py.'),
+ )
+
+ def __init__(self, pattern=None, top_level=None,
+ verbosity=1, interactive=True, failfast=False,
+ **kwargs):
+
+ self.pattern = pattern
+ self.top_level = top_level
+
+ self.verbosity = verbosity
+ self.interactive = interactive
+ self.failfast = failfast
+
+ def setup_test_environment(self, **kwargs):
+ setup_test_environment()
+ settings.DEBUG = False
+ unittest.installHandler()
+
+ def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
+ suite = TestSuite()
+ test_labels = test_labels or ['.']
+ extra_tests = extra_tests or []
+
+ discover_kwargs = {}
+ if self.pattern is not None:
+ discover_kwargs['pattern'] = self.pattern
+ if self.top_level is not None:
+ discover_kwargs['top_level_dir'] = self.top_level
+
+ for label in test_labels:
+ kwargs = discover_kwargs.copy()
+ tests = None
+
+ label_as_path = os.path.abspath(label)
+
+ # if a module, or "module.ClassName[.method_name]", just run those
+ if not os.path.exists(label_as_path):
+ tests = self.test_loader.loadTestsFromName(label)
+ elif os.path.isdir(label_as_path) and not self.top_level:
+ # Try to be a bit smarter than unittest about finding the
+ # default top-level for a given directory path, to avoid
+ # breaking relative imports. (Unittest's default is to set
+ # top-level equal to the path, which means relative imports
+ # will result in "Attempted relative import in non-package.").
+
+ # We'd be happy to skip this and require dotted module paths
+ # (which don't cause this problem) instead of file paths (which
+ # do), but in the case of a directory in the cwd, which would
+ # be equally valid if considered as a top-level module or as a
+ # directory path, unittest unfortunately prefers the latter.
+
+ top_level = label_as_path
+ while True:
+ init_py = os.path.join(top_level, '__init__.py')
+ if os.path.exists(init_py):
+ try_next = os.path.dirname(top_level)
+ if try_next == top_level:
+ # __init__.py all the way down? give up.
+ break
+ top_level = try_next
+ continue
+ break
+ kwargs['top_level_dir'] = top_level
+
+
+ if not (tests and tests.countTestCases()):
+ # if no tests found, it's probably a package; try discovery
+ tests = self.test_loader.discover(start_dir=label, **kwargs)
+
+ # make unittest forget the top-level dir it calculated from this
+ # run, to support running tests from two different top-levels.
+ self.test_loader._top_level_dir = None
+
+ suite.addTests(tests)
+
+ for test in extra_tests:
+ suite.addTest(test)
+
+ return reorder_suite(suite, self.reorder_by)
+
+ def setup_databases(self, **kwargs):
+ return setup_databases(self.verbosity, self.interactive, **kwargs)
+
+ def run_suite(self, suite, **kwargs):
+ return unittest.TextTestRunner(
+ verbosity=self.verbosity,
+ failfast=self.failfast,
+ ).run(suite)
+
+ def teardown_databases(self, old_config, **kwargs):
+ """
+ Destroys all the non-mirror databases.
+ """
+ old_names, mirrors = old_config
+ for connection, old_name, destroy in old_names:
+ if destroy:
+ connection.creation.destroy_test_db(old_name, self.verbosity)
+
+ def teardown_test_environment(self, **kwargs):
+ unittest.removeHandler()
+ teardown_test_environment()
+
+ def suite_result(self, suite, result, **kwargs):
+ return len(result.failures) + len(result.errors)
+
+ def run_tests(self, test_labels, extra_tests=None, **kwargs):
+ """
+ Run the unit tests for all the test labels in the provided list.
+
+ Test labels should be dotted Python paths to test modules, test
+ classes, or test methods.
+
+ A list of 'extra' tests may also be provided; these tests
+ will be added to the test suite.
+
+ Returns the number of tests that failed.
+ """
+ self.setup_test_environment()
+ suite = self.build_suite(test_labels, extra_tests)
+ old_config = self.setup_databases()
+ result = self.run_suite(suite)
+ self.teardown_databases(old_config)
+ self.teardown_test_environment()
+ return self.suite_result(suite, result)
+
+
+def dependency_ordered(test_databases, dependencies):
+ """
+ Reorder test_databases into an order that honors the dependencies
+ described in TEST_DEPENDENCIES.
+ """
+ ordered_test_databases = []
+ resolved_databases = set()
+
+ # Maps db signature to dependencies of all it's aliases
+ dependencies_map = {}
+
+ # sanity check - no DB can depend on it's own alias
+ for sig, (_, aliases) in test_databases:
+ all_deps = set()
+ for alias in aliases:
+ all_deps.update(dependencies.get(alias, []))
+ if not all_deps.isdisjoint(aliases):
+ raise ImproperlyConfigured(
+ "Circular dependency: databases %r depend on each other, "
+ "but are aliases." % aliases)
+ dependencies_map[sig] = all_deps
+
+ while test_databases:
+ changed = False
+ deferred = []
+
+ # Try to find a DB that has all it's dependencies met
+ for signature, (db_name, aliases) in test_databases:
+ if dependencies_map[signature].issubset(resolved_databases):
+ resolved_databases.update(aliases)
+ ordered_test_databases.append((signature, (db_name, aliases)))
+ changed = True
+ else:
+ deferred.append((signature, (db_name, aliases)))
+
+ if not changed:
+ raise ImproperlyConfigured(
+ "Circular dependency in TEST_DEPENDENCIES")
+ test_databases = deferred
+ return ordered_test_databases
+
+
+def reorder_suite(suite, classes):
+ """
+ Reorders a test suite by test type.
+
+ `classes` is a sequence of types
+
+ All tests of type classes[0] are placed first, then tests of type
+ classes[1], etc. Tests with no match in classes are placed last.
+ """
+ class_count = len(classes)
+ bins = [unittest.TestSuite() for i in range(class_count+1)]
+ partition_suite(suite, classes, bins)
+ for i in range(class_count):
+ bins[0].addTests(bins[i+1])
+ return bins[0]
+
+
+def partition_suite(suite, classes, bins):
+ """
+ Partitions a test suite by test type.
+
+ classes is a sequence of types
+ bins is a sequence of TestSuites, one more than classes
+
+ Tests of type classes[i] are added to bins[i],
+ tests with no match found in classes are place in bins[-1]
+ """
+ for test in suite:
+ if isinstance(test, unittest.TestSuite):
+ partition_suite(test, classes, bins)
+ else:
+ for i in range(len(classes)):
+ if isinstance(test, classes[i]):
+ bins[i].addTest(test)
+ break
+ else:
+ bins[-1].addTest(test)
+
+
+def setup_databases(verbosity, interactive, **kwargs):
+ from django.db import connections, DEFAULT_DB_ALIAS
+
+ # First pass -- work out which databases actually need to be created,
+ # and which ones are test mirrors or duplicate entries in DATABASES
+ mirrored_aliases = {}
+ test_databases = {}
+ dependencies = {}
+ default_sig = connections[DEFAULT_DB_ALIAS].creation.test_db_signature()
+ for alias in connections:
+ connection = connections[alias]
+ if connection.settings_dict['TEST_MIRROR']:
+ # If the database is marked as a test mirror, save
+ # the alias.
+ mirrored_aliases[alias] = (
+ connection.settings_dict['TEST_MIRROR'])
+ else:
+ # Store a tuple with DB parameters that uniquely identify it.
+ # If we have two aliases with the same values for that tuple,
+ # we only need to create the test database once.
+ item = test_databases.setdefault(
+ connection.creation.test_db_signature(),
+ (connection.settings_dict['NAME'], set())
+ )
+ item[1].add(alias)
+
+ if 'TEST_DEPENDENCIES' in connection.settings_dict:
+ dependencies[alias] = (
+ connection.settings_dict['TEST_DEPENDENCIES'])
+ else:
+ if alias != DEFAULT_DB_ALIAS and connection.creation.test_db_signature() != default_sig:
+ dependencies[alias] = connection.settings_dict.get(
+ 'TEST_DEPENDENCIES', [DEFAULT_DB_ALIAS])
+
+ # Second pass -- actually create the databases.
+ old_names = []
+ mirrors = []
+
+ for signature, (db_name, aliases) in dependency_ordered(
+ test_databases.items(), dependencies):
+ test_db_name = None
+ # Actually create the database for the first connection
+ for alias in aliases:
+ connection = connections[alias]
+ if test_db_name is None:
+ test_db_name = connection.creation.create_test_db(
+ verbosity, autoclobber=not interactive)
+ destroy = True
+ else:
+ connection.settings_dict['NAME'] = test_db_name
+ destroy = False
+ old_names.append((connection, db_name, destroy))
+
+ for alias, mirror_alias in mirrored_aliases.items():
+ mirrors.append((alias, connections[alias].settings_dict['NAME']))
+ connections[alias].settings_dict['NAME'] = (
+ connections[mirror_alias].settings_dict['NAME'])
+
+ return old_names, mirrors
diff --git a/lib/python2.7/site-packages/django/test/signals.py b/lib/python2.7/site-packages/django/test/signals.py
new file mode 100644
index 0000000..a96bdff
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/signals.py
@@ -0,0 +1,81 @@
+import os
+import time
+
+from django.conf import settings
+from django.db import connections
+from django.dispatch import receiver, Signal
+from django.utils import timezone
+from django.utils.functional import empty
+
+template_rendered = Signal(providing_args=["template", "context"])
+
+setting_changed = Signal(providing_args=["setting", "value"])
+
+# Most setting_changed receivers are supposed to be added below,
+# except for cases where the receiver is related to a contrib app.
+
+
+@receiver(setting_changed)
+def update_connections_time_zone(**kwargs):
+ if kwargs['setting'] == 'TIME_ZONE':
+ # Reset process time zone
+ if hasattr(time, 'tzset'):
+ if kwargs['value']:
+ os.environ['TZ'] = kwargs['value']
+ else:
+ os.environ.pop('TZ', None)
+ time.tzset()
+
+ # Reset local time zone cache
+ timezone._localtime = None
+
+ # Reset the database connections' time zone
+ if kwargs['setting'] == 'USE_TZ' and settings.TIME_ZONE != 'UTC':
+ USE_TZ, TIME_ZONE = kwargs['value'], settings.TIME_ZONE
+ elif kwargs['setting'] == 'TIME_ZONE' and not settings.USE_TZ:
+ USE_TZ, TIME_ZONE = settings.USE_TZ, kwargs['value']
+ else:
+ # no need to change the database connnections' time zones
+ return
+ tz = 'UTC' if USE_TZ else TIME_ZONE
+ for conn in connections.all():
+ conn.settings_dict['TIME_ZONE'] = tz
+ tz_sql = conn.ops.set_time_zone_sql()
+ if tz_sql:
+ conn.cursor().execute(tz_sql, [tz])
+
+
+@receiver(setting_changed)
+def clear_context_processors_cache(**kwargs):
+ if kwargs['setting'] == 'TEMPLATE_CONTEXT_PROCESSORS':
+ from django.template import context
+ context._standard_context_processors = None
+
+
+@receiver(setting_changed)
+def clear_template_loaders_cache(**kwargs):
+ if kwargs['setting'] == 'TEMPLATE_LOADERS':
+ from django.template import loader
+ loader.template_source_loaders = None
+
+
+@receiver(setting_changed)
+def clear_serializers_cache(**kwargs):
+ if kwargs['setting'] == 'SERIALIZATION_MODULES':
+ from django.core import serializers
+ serializers._serializers = {}
+
+
+@receiver(setting_changed)
+def language_changed(**kwargs):
+ if kwargs['setting'] in ('LOCALE_PATHS', 'LANGUAGE_CODE'):
+ from django.utils.translation import trans_real
+ trans_real._default = None
+ if kwargs['setting'] == 'LOCALE_PATHS':
+ trans_real._translations = {}
+
+@receiver(setting_changed)
+def file_storage_changed(**kwargs):
+ if kwargs['setting'] in ('MEDIA_ROOT', 'DEFAULT_FILE_STORAGE'):
+ from django.core.files.storage import default_storage
+ default_storage._wrapped = empty
diff --git a/lib/python2.7/site-packages/django/test/simple.py b/lib/python2.7/site-packages/django/test/simple.py
new file mode 100644
index 0000000..f28b8a2
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/simple.py
@@ -0,0 +1,253 @@
+"""
+This module is pending deprecation as of Django 1.6 and will be removed in
+version 1.8.
+
+"""
+import json
+import re
+import unittest as real_unittest
+import warnings
+
+from django.db.models import get_app, get_apps
+from django.test import _doctest as doctest
+from django.test import runner
+from django.test.utils import compare_xml, strip_quotes
+from django.utils import unittest
+from django.utils.importlib import import_module
+from django.utils.module_loading import module_has_submodule
+
+__all__ = ('DjangoTestSuiteRunner',)
+
+warnings.warn(
+ "The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
+ "use django.test.runner.DiscoverRunner instead.",
+ PendingDeprecationWarning)
+
+# The module name for tests outside models.py
+TEST_MODULE = 'tests'
+
+
+normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
+normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)",
+ lambda m: "Decimal(\"%s\")" % m.groups()[0], s)
+
+
+class OutputChecker(doctest.OutputChecker):
+ def check_output(self, want, got, optionflags):
+ """
+ The entry method for doctest output checking. Defers to a sequence of
+ child checkers
+ """
+ checks = (self.check_output_default,
+ self.check_output_numeric,
+ self.check_output_xml,
+ self.check_output_json)
+ for check in checks:
+ if check(want, got, optionflags):
+ return True
+ return False
+
+ def check_output_default(self, want, got, optionflags):
+ """
+ The default comparator provided by doctest - not perfect, but good for
+ most purposes
+ """
+ return doctest.OutputChecker.check_output(self, want, got, optionflags)
+
+ def check_output_numeric(self, want, got, optionflags):
+ """Doctest does an exact string comparison of output, which means that
+ some numerically equivalent values aren't equal. This check normalizes
+ * long integers (22L) so that they equal normal integers. (22)
+ * Decimals so that they are comparable, regardless of the change
+ made to __repr__ in Python 2.6.
+ """
+ return doctest.OutputChecker.check_output(self,
+ normalize_decimals(normalize_long_ints(want)),
+ normalize_decimals(normalize_long_ints(got)),
+ optionflags)
+
+ def check_output_xml(self, want, got, optionsflags):
+ try:
+ return compare_xml(want, got)
+ except Exception:
+ return False
+
+ def check_output_json(self, want, got, optionsflags):
+ """
+ Tries to compare want and got as if they were JSON-encoded data
+ """
+ want, got = strip_quotes(want, got)
+ try:
+ want_json = json.loads(want)
+ got_json = json.loads(got)
+ except Exception:
+ return False
+ return want_json == got_json
+
+
+class DocTestRunner(doctest.DocTestRunner):
+ def __init__(self, *args, **kwargs):
+ doctest.DocTestRunner.__init__(self, *args, **kwargs)
+ self.optionflags = doctest.ELLIPSIS
+
+
+doctestOutputChecker = OutputChecker()
+
+
+def get_tests(app_module):
+ parts = app_module.__name__.split('.')
+ prefix, last = parts[:-1], parts[-1]
+ try:
+ test_module = import_module('.'.join(prefix + [TEST_MODULE]))
+ except ImportError:
+ # Couldn't import tests.py. Was it due to a missing file, or
+ # due to an import error in a tests.py that actually exists?
+ # app_module either points to a models.py file, or models/__init__.py
+ # Tests are therefore either in same directory, or one level up
+ if last == 'models':
+ app_root = import_module('.'.join(prefix))
+ else:
+ app_root = app_module
+
+ if not module_has_submodule(app_root, TEST_MODULE):
+ test_module = None
+ else:
+ # The module exists, so there must be an import error in the test
+ # module itself.
+ raise
+ return test_module
+
+
+def make_doctest(module):
+ return doctest.DocTestSuite(module,
+ checker=doctestOutputChecker,
+ runner=DocTestRunner,
+ )
+
+
+def build_suite(app_module):
+ """
+ Create a complete Django test suite for the provided application module.
+ """
+ suite = unittest.TestSuite()
+
+ # Load unit and doctests in the models.py module. If module has
+ # a suite() method, use it. Otherwise build the test suite ourselves.
+ if hasattr(app_module, 'suite'):
+ suite.addTest(app_module.suite())
+ else:
+ suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(
+ app_module))
+ try:
+ suite.addTest(make_doctest(app_module))
+ except ValueError:
+ # No doc tests in models.py
+ pass
+
+ # Check to see if a separate 'tests' module exists parallel to the
+ # models module
+ test_module = get_tests(app_module)
+ if test_module:
+ # Load unit and doctests in the tests.py module. If module has
+ # a suite() method, use it. Otherwise build the test suite ourselves.
+ if hasattr(test_module, 'suite'):
+ suite.addTest(test_module.suite())
+ else:
+ suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(
+ test_module))
+ try:
+ suite.addTest(make_doctest(test_module))
+ except ValueError:
+ # No doc tests in tests.py
+ pass
+ return suite
+
+
+def build_test(label):
+ """
+ Construct a test case with the specified label. Label should be of the
+ form model.TestClass or model.TestClass.test_method. Returns an
+ instantiated test or test suite corresponding to the label provided.
+
+ """
+ parts = label.split('.')
+ if len(parts) < 2 or len(parts) > 3:
+ raise ValueError("Test label '%s' should be of the form app.TestCase "
+ "or app.TestCase.test_method" % label)
+
+ #
+ # First, look for TestCase instances with a name that matches
+ #
+ app_module = get_app(parts[0])
+ test_module = get_tests(app_module)
+ TestClass = getattr(app_module, parts[1], None)
+
+ # Couldn't find the test class in models.py; look in tests.py
+ if TestClass is None:
+ if test_module:
+ TestClass = getattr(test_module, parts[1], None)
+
+ try:
+ if issubclass(TestClass, (unittest.TestCase, real_unittest.TestCase)):
+ if len(parts) == 2: # label is app.TestClass
+ try:
+ return unittest.TestLoader().loadTestsFromTestCase(
+ TestClass)
+ except TypeError:
+ raise ValueError(
+ "Test label '%s' does not refer to a test class"
+ % label)
+ else: # label is app.TestClass.test_method
+ return TestClass(parts[2])
+ except TypeError:
+ # TestClass isn't a TestClass - it must be a method or normal class
+ pass
+
+ #
+ # If there isn't a TestCase, look for a doctest that matches
+ #
+ tests = []
+ for module in app_module, test_module:
+ try:
+ doctests = make_doctest(module)
+ # Now iterate over the suite, looking for doctests whose name
+ # matches the pattern that was given
+ for test in doctests:
+ if test._dt_test.name in (
+ '%s.%s' % (module.__name__, '.'.join(parts[1:])),
+ '%s.__test__.%s' % (
+ module.__name__, '.'.join(parts[1:]))):
+ tests.append(test)
+ except ValueError:
+ # No doctests found.
+ pass
+
+ # If no tests were found, then we were given a bad test label.
+ if not tests:
+ raise ValueError("Test label '%s' does not refer to a test" % label)
+
+ # Construct a suite out of the tests that matched.
+ return unittest.TestSuite(tests)
+
+
+class DjangoTestSuiteRunner(runner.DiscoverRunner):
+
+ def build_suite(self, test_labels, extra_tests=None, **kwargs):
+ suite = unittest.TestSuite()
+
+ if test_labels:
+ for label in test_labels:
+ if '.' in label:
+ suite.addTest(build_test(label))
+ else:
+ app = get_app(label)
+ suite.addTest(build_suite(app))
+ else:
+ for app in get_apps():
+ suite.addTest(build_suite(app))
+
+ if extra_tests:
+ for test in extra_tests:
+ suite.addTest(test)
+
+ return runner.reorder_suite(suite, (unittest.TestCase,))
diff --git a/lib/python2.7/site-packages/django/test/testcases.py b/lib/python2.7/site-packages/django/test/testcases.py
new file mode 100644
index 0000000..85ff66a
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/testcases.py
@@ -0,0 +1,1208 @@
+from __future__ import unicode_literals
+
+from copy import copy
+import difflib
+import errno
+from functools import wraps
+import json
+import os
+import re
+import socket
+import sys
+import select
+import socket
+import threading
+import warnings
+
+from django.conf import settings
+from django.contrib.staticfiles.handlers import StaticFilesHandler
+from django.core import mail
+from django.core.exceptions import ValidationError, ImproperlyConfigured
+from django.core.handlers.wsgi import WSGIHandler
+from django.core.management import call_command
+from django.core.management.color import no_style
+from django.core.management.commands import flush
+from django.core.servers.basehttp import WSGIRequestHandler, WSGIServer
+from django.core.urlresolvers import clear_url_caches, set_urlconf
+from django.db import connection, connections, DEFAULT_DB_ALIAS, transaction
+from django.db.models.loading import cache
+from django.forms.fields import CharField
+from django.http import QueryDict
+from django.test.client import Client
+from django.test.html import HTMLParseError, parse_html
+from django.test.signals import template_rendered
+from django.test.utils import (CaptureQueriesContext, ContextList,
+ override_settings, compare_xml)
+from django.utils import six, unittest as ut2
+from django.utils.encoding import force_text
+from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
+from django.utils.unittest import skipIf # Imported here for backward compatibility
+from django.utils.unittest.util import safe_repr
+from django.views.static import serve
+
+
+__all__ = ('TestCase', 'TransactionTestCase',
+ 'SimpleTestCase', 'skipIfDBFeature', 'skipUnlessDBFeature')
+
+
+def to_list(value):
+ """
+ Puts value into a list if it's not already one.
+ Returns an empty list if value is None.
+ """
+ if value is None:
+ value = []
+ elif not isinstance(value, list):
+ value = [value]
+ return value
+
+real_commit = transaction.commit
+real_rollback = transaction.rollback
+real_enter_transaction_management = transaction.enter_transaction_management
+real_leave_transaction_management = transaction.leave_transaction_management
+real_abort = transaction.abort
+
+def nop(*args, **kwargs):
+ return
+
+def disable_transaction_methods():
+ transaction.commit = nop
+ transaction.rollback = nop
+ transaction.enter_transaction_management = nop
+ transaction.leave_transaction_management = nop
+ transaction.abort = nop
+
+def restore_transaction_methods():
+ transaction.commit = real_commit
+ transaction.rollback = real_rollback
+ transaction.enter_transaction_management = real_enter_transaction_management
+ transaction.leave_transaction_management = real_leave_transaction_management
+ transaction.abort = real_abort
+
+
+def assert_and_parse_html(self, html, user_msg, msg):
+ try:
+ dom = parse_html(html)
+ except HTMLParseError as e:
+ standardMsg = '%s\n%s' % (msg, e.msg)
+ self.fail(self._formatMessage(user_msg, standardMsg))
+ return dom
+
+
+class _AssertNumQueriesContext(CaptureQueriesContext):
+ def __init__(self, test_case, num, connection):
+ self.test_case = test_case
+ self.num = num
+ super(_AssertNumQueriesContext, self).__init__(connection)
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ super(_AssertNumQueriesContext, self).__exit__(exc_type, exc_value, traceback)
+ if exc_type is not None:
+ return
+ executed = len(self)
+ self.test_case.assertEqual(
+ executed, self.num, "%d queries executed, %d expected" % (
+ executed, self.num
+ )
+ )
+
+
+class _AssertTemplateUsedContext(object):
+ def __init__(self, test_case, template_name):
+ self.test_case = test_case
+ self.template_name = template_name
+ self.rendered_templates = []
+ self.rendered_template_names = []
+ self.context = ContextList()
+
+ def on_template_render(self, sender, signal, template, context, **kwargs):
+ self.rendered_templates.append(template)
+ self.rendered_template_names.append(template.name)
+ self.context.append(copy(context))
+
+ def test(self):
+ return self.template_name in self.rendered_template_names
+
+ def message(self):
+ return '%s was not rendered.' % self.template_name
+
+ def __enter__(self):
+ template_rendered.connect(self.on_template_render)
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ template_rendered.disconnect(self.on_template_render)
+ if exc_type is not None:
+ return
+
+ if not self.test():
+ message = self.message()
+ if len(self.rendered_templates) == 0:
+ message += ' No template was rendered.'
+ else:
+ message += ' Following templates were rendered: %s' % (
+ ', '.join(self.rendered_template_names))
+ self.test_case.fail(message)
+
+
+class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext):
+ def test(self):
+ return self.template_name not in self.rendered_template_names
+
+ def message(self):
+ return '%s was rendered.' % self.template_name
+
+
+class SimpleTestCase(ut2.TestCase):
+
+ # The class we'll use for the test client self.client.
+ # Can be overridden in derived classes.
+ client_class = Client
+
+ _warn_txt = ("save_warnings_state/restore_warnings_state "
+ "django.test.*TestCase methods are deprecated. Use Python's "
+ "warnings.catch_warnings context manager instead.")
+
+ def __call__(self, result=None):
+ """
+ Wrapper around default __call__ method to perform common Django test
+ set up. This means that user-defined Test Cases aren't required to
+ include a call to super().setUp().
+ """
+ testMethod = getattr(self, self._testMethodName)
+ skipped = (getattr(self.__class__, "__unittest_skip__", False) or
+ getattr(testMethod, "__unittest_skip__", False))
+
+ if not skipped:
+ try:
+ self._pre_setup()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except Exception:
+ result.addError(self, sys.exc_info())
+ return
+ super(SimpleTestCase, self).__call__(result)
+ if not skipped:
+ try:
+ self._post_teardown()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except Exception:
+ result.addError(self, sys.exc_info())
+ return
+
+ def _pre_setup(self):
+ """Performs any pre-test setup. This includes:
+
+ * Creating a test client.
+ * If the class has a 'urls' attribute, replace ROOT_URLCONF with it.
+ * Clearing the mail test outbox.
+ """
+ self.client = self.client_class()
+ self._urlconf_setup()
+ mail.outbox = []
+
+ def _urlconf_setup(self):
+ set_urlconf(None)
+ if hasattr(self, 'urls'):
+ self._old_root_urlconf = settings.ROOT_URLCONF
+ settings.ROOT_URLCONF = self.urls
+ clear_url_caches()
+
+ def _post_teardown(self):
+ """Performs any post-test things. This includes:
+
+ * Putting back the original ROOT_URLCONF if it was changed.
+ """
+ self._urlconf_teardown()
+
+ def _urlconf_teardown(self):
+ set_urlconf(None)
+ if hasattr(self, '_old_root_urlconf'):
+ settings.ROOT_URLCONF = self._old_root_urlconf
+ clear_url_caches()
+
+ def save_warnings_state(self):
+ """
+ Saves the state of the warnings module
+ """
+ warnings.warn(self._warn_txt, DeprecationWarning, stacklevel=2)
+ self._warnings_state = warnings.filters[:]
+
+ def restore_warnings_state(self):
+ """
+ Restores the state of the warnings module to the state
+ saved by save_warnings_state()
+ """
+ warnings.warn(self._warn_txt, DeprecationWarning, stacklevel=2)
+ warnings.filters = self._warnings_state[:]
+
+ def settings(self, **kwargs):
+ """
+ A context manager that temporarily sets a setting and reverts
+ back to the original value when exiting the context.
+ """
+ return override_settings(**kwargs)
+
+ def assertRedirects(self, response, expected_url, status_code=302,
+ target_status_code=200, host=None, msg_prefix=''):
+ """Asserts that a response redirected to a specific URL, and that the
+ redirect URL can be loaded.
+
+ Note that assertRedirects won't work for external links since it uses
+ TestClient to do a request.
+ """
+ if msg_prefix:
+ msg_prefix += ": "
+
+ if hasattr(response, 'redirect_chain'):
+ # The request was a followed redirect
+ self.assertTrue(len(response.redirect_chain) > 0,
+ msg_prefix + "Response didn't redirect as expected: Response"
+ " code was %d (expected %d)" %
+ (response.status_code, status_code))
+
+ self.assertEqual(response.redirect_chain[0][1], status_code,
+ msg_prefix + "Initial response didn't redirect as expected:"
+ " Response code was %d (expected %d)" %
+ (response.redirect_chain[0][1], status_code))
+
+ url, status_code = response.redirect_chain[-1]
+
+ self.assertEqual(response.status_code, target_status_code,
+ msg_prefix + "Response didn't redirect as expected: Final"
+ " Response code was %d (expected %d)" %
+ (response.status_code, target_status_code))
+
+ else:
+ # Not a followed redirect
+ self.assertEqual(response.status_code, status_code,
+ msg_prefix + "Response didn't redirect as expected: Response"
+ " code was %d (expected %d)" %
+ (response.status_code, status_code))
+
+ url = response.url
+ scheme, netloc, path, query, fragment = urlsplit(url)
+
+ redirect_response = response.client.get(path, QueryDict(query))
+
+ # Get the redirection page, using the same client that was used
+ # to obtain the original response.
+ self.assertEqual(redirect_response.status_code, target_status_code,
+ msg_prefix + "Couldn't retrieve redirection page '%s':"
+ " response code was %d (expected %d)" %
+ (path, redirect_response.status_code, target_status_code))
+
+ e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(
+ expected_url)
+ if not (e_scheme or e_netloc):
+ expected_url = urlunsplit(('http', host or 'testserver', e_path,
+ e_query, e_fragment))
+
+ self.assertEqual(url, expected_url,
+ msg_prefix + "Response redirected to '%s', expected '%s'" %
+ (url, expected_url))
+
+ def assertContains(self, response, text, count=None, status_code=200,
+ msg_prefix='', html=False):
+ """
+ Asserts that a response indicates that some content was retrieved
+ successfully, (i.e., the HTTP status code was as expected), and that
+ ``text`` occurs ``count`` times in the content of the response.
+ If ``count`` is None, the count doesn't matter - the assertion is true
+ if the text occurs at least once in the response.
+ """
+
+ # If the response supports deferred rendering and hasn't been rendered
+ # yet, then ensure that it does get rendered before proceeding further.
+ if (hasattr(response, 'render') and callable(response.render)
+ and not response.is_rendered):
+ response.render()
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ self.assertEqual(response.status_code, status_code,
+ msg_prefix + "Couldn't retrieve content: Response code was %d"
+ " (expected %d)" % (response.status_code, status_code))
+
+ if response.streaming:
+ content = b''.join(response.streaming_content)
+ else:
+ content = response.content
+ if not isinstance(text, bytes) or html:
+ text = force_text(text, encoding=response._charset)
+ content = content.decode(response._charset)
+ text_repr = "'%s'" % text
+ else:
+ text_repr = repr(text)
+ if html:
+ content = assert_and_parse_html(self, content, None,
+ "Response's content is not valid HTML:")
+ text = assert_and_parse_html(self, text, None,
+ "Second argument is not valid HTML:")
+ real_count = content.count(text)
+ if count is not None:
+ self.assertEqual(real_count, count,
+ msg_prefix + "Found %d instances of %s in response"
+ " (expected %d)" % (real_count, text_repr, count))
+ else:
+ self.assertTrue(real_count != 0,
+ msg_prefix + "Couldn't find %s in response" % text_repr)
+
+ def assertNotContains(self, response, text, status_code=200,
+ msg_prefix='', html=False):
+ """
+ Asserts that a response indicates that some content was retrieved
+ successfully, (i.e., the HTTP status code was as expected), and that
+ ``text`` doesn't occurs in the content of the response.
+ """
+
+ # If the response supports deferred rendering and hasn't been rendered
+ # yet, then ensure that it does get rendered before proceeding further.
+ if (hasattr(response, 'render') and callable(response.render)
+ and not response.is_rendered):
+ response.render()
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ self.assertEqual(response.status_code, status_code,
+ msg_prefix + "Couldn't retrieve content: Response code was %d"
+ " (expected %d)" % (response.status_code, status_code))
+
+ content = response.content
+ if not isinstance(text, bytes) or html:
+ text = force_text(text, encoding=response._charset)
+ content = content.decode(response._charset)
+ text_repr = "'%s'" % text
+ else:
+ text_repr = repr(text)
+ if html:
+ content = assert_and_parse_html(self, content, None,
+ 'Response\'s content is not valid HTML:')
+ text = assert_and_parse_html(self, text, None,
+ 'Second argument is not valid HTML:')
+ self.assertEqual(content.count(text), 0,
+ msg_prefix + "Response should not contain %s" % text_repr)
+
+ def assertFormError(self, response, form, field, errors, msg_prefix=''):
+ """
+ Asserts that a form used to render the response has a specific field
+ error.
+ """
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Put context(s) into a list to simplify processing.
+ contexts = to_list(response.context)
+ if not contexts:
+ self.fail(msg_prefix + "Response did not use any contexts to "
+ "render the response")
+
+ # Put error(s) into a list to simplify processing.
+ errors = to_list(errors)
+
+ # Search all contexts for the error.
+ found_form = False
+ for i,context in enumerate(contexts):
+ if form not in context:
+ continue
+ found_form = True
+ for err in errors:
+ if field:
+ if field in context[form].errors:
+ field_errors = context[form].errors[field]
+ self.assertTrue(err in field_errors,
+ msg_prefix + "The field '%s' on form '%s' in"
+ " context %d does not contain the error '%s'"
+ " (actual errors: %s)" %
+ (field, form, i, err, repr(field_errors)))
+ elif field in context[form].fields:
+ self.fail(msg_prefix + "The field '%s' on form '%s'"
+ " in context %d contains no errors" %
+ (field, form, i))
+ else:
+ self.fail(msg_prefix + "The form '%s' in context %d"
+ " does not contain the field '%s'" %
+ (form, i, field))
+ else:
+ non_field_errors = context[form].non_field_errors()
+ self.assertTrue(err in non_field_errors,
+ msg_prefix + "The form '%s' in context %d does not"
+ " contain the non-field error '%s'"
+ " (actual errors: %s)" %
+ (form, i, err, non_field_errors))
+ if not found_form:
+ self.fail(msg_prefix + "The form '%s' was not used to render the"
+ " response" % form)
+
+ def assertFormsetError(self, response, formset, form_index, field, errors,
+ msg_prefix=''):
+ """
+ Asserts that a formset used to render the response has a specific error.
+
+ For field errors, specify the ``form_index`` and the ``field``.
+ For non-field errors, specify the ``form_index`` and the ``field`` as
+ None.
+ For non-form errors, specify ``form_index`` as None and the ``field``
+ as None.
+ """
+ # Add punctuation to msg_prefix
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Put context(s) into a list to simplify processing.
+ contexts = to_list(response.context)
+ if not contexts:
+ self.fail(msg_prefix + 'Response did not use any contexts to '
+ 'render the response')
+
+ # Put error(s) into a list to simplify processing.
+ errors = to_list(errors)
+
+ # Search all contexts for the error.
+ found_formset = False
+ for i, context in enumerate(contexts):
+ if formset not in context:
+ continue
+ found_formset = True
+ for err in errors:
+ if field is not None:
+ if field in context[formset].forms[form_index].errors:
+ field_errors = context[formset].forms[form_index].errors[field]
+ self.assertTrue(err in field_errors,
+ msg_prefix + "The field '%s' on formset '%s', "
+ "form %d in context %d does not contain the "
+ "error '%s' (actual errors: %s)" %
+ (field, formset, form_index, i, err,
+ repr(field_errors)))
+ elif field in context[formset].forms[form_index].fields:
+ self.fail(msg_prefix + "The field '%s' "
+ "on formset '%s', form %d in "
+ "context %d contains no errors" %
+ (field, formset, form_index, i))
+ else:
+ self.fail(msg_prefix + "The formset '%s', form %d in "
+ "context %d does not contain the field '%s'" %
+ (formset, form_index, i, field))
+ elif form_index is not None:
+ non_field_errors = context[formset].forms[form_index].non_field_errors()
+ self.assertFalse(len(non_field_errors) == 0,
+ msg_prefix + "The formset '%s', form %d in "
+ "context %d does not contain any non-field "
+ "errors." % (formset, form_index, i))
+ self.assertTrue(err in non_field_errors,
+ msg_prefix + "The formset '%s', form %d "
+ "in context %d does not contain the "
+ "non-field error '%s' "
+ "(actual errors: %s)" %
+ (formset, form_index, i, err,
+ repr(non_field_errors)))
+ else:
+ non_form_errors = context[formset].non_form_errors()
+ self.assertFalse(len(non_form_errors) == 0,
+ msg_prefix + "The formset '%s' in "
+ "context %d does not contain any "
+ "non-form errors." % (formset, i))
+ self.assertTrue(err in non_form_errors,
+ msg_prefix + "The formset '%s' in context "
+ "%d does not contain the "
+ "non-form error '%s' (actual errors: %s)" %
+ (formset, i, err, repr(non_form_errors)))
+ if not found_formset:
+ self.fail(msg_prefix + "The formset '%s' was not used to render "
+ "the response" % formset)
+
+ def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''):
+ """
+ Asserts that the template with the provided name was used in rendering
+ the response. Also usable as context manager.
+ """
+ if response is None and template_name is None:
+ raise TypeError('response and/or template_name argument must be provided')
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Use assertTemplateUsed as context manager.
+ if not hasattr(response, 'templates') or (response is None and template_name):
+ if response:
+ template_name = response
+ response = None
+ context = _AssertTemplateUsedContext(self, template_name)
+ return context
+
+ template_names = [t.name for t in response.templates]
+ if not template_names:
+ self.fail(msg_prefix + "No templates used to render the response")
+ self.assertTrue(template_name in template_names,
+ msg_prefix + "Template '%s' was not a template used to render"
+ " the response. Actual template(s) used: %s" %
+ (template_name, ', '.join(template_names)))
+
+ def assertTemplateNotUsed(self, response=None, template_name=None, msg_prefix=''):
+ """
+ Asserts that the template with the provided name was NOT used in
+ rendering the response. Also usable as context manager.
+ """
+ if response is None and template_name is None:
+ raise TypeError('response and/or template_name argument must be provided')
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Use assertTemplateUsed as context manager.
+ if not hasattr(response, 'templates') or (response is None and template_name):
+ if response:
+ template_name = response
+ response = None
+ context = _AssertTemplateNotUsedContext(self, template_name)
+ return context
+
+ template_names = [t.name for t in response.templates]
+ self.assertFalse(template_name in template_names,
+ msg_prefix + "Template '%s' was used unexpectedly in rendering"
+ " the response" % template_name)
+
+ def assertRaisesMessage(self, expected_exception, expected_message,
+ callable_obj=None, *args, **kwargs):
+ """
+ Asserts that the message in a raised exception matches the passed
+ value.
+
+ Args:
+ expected_exception: Exception class expected to be raised.
+ expected_message: expected error message string value.
+ callable_obj: Function to be called.
+ args: Extra args.
+ kwargs: Extra kwargs.
+ """
+ return six.assertRaisesRegex(self, expected_exception,
+ re.escape(expected_message), callable_obj, *args, **kwargs)
+
+ def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None,
+ field_kwargs=None, empty_value=''):
+ """
+ Asserts that a form field behaves correctly with various inputs.
+
+ Args:
+ fieldclass: the class of the field to be tested.
+ valid: a dictionary mapping valid inputs to their expected
+ cleaned values.
+ invalid: a dictionary mapping invalid inputs to one or more
+ raised error messages.
+ field_args: the args passed to instantiate the field
+ field_kwargs: the kwargs passed to instantiate the field
+ empty_value: the expected clean output for inputs in empty_values
+
+ """
+ if field_args is None:
+ field_args = []
+ if field_kwargs is None:
+ field_kwargs = {}
+ required = fieldclass(*field_args, **field_kwargs)
+ optional = fieldclass(*field_args,
+ **dict(field_kwargs, required=False))
+ # test valid inputs
+ for input, output in valid.items():
+ self.assertEqual(required.clean(input), output)
+ self.assertEqual(optional.clean(input), output)
+ # test invalid inputs
+ for input, errors in invalid.items():
+ with self.assertRaises(ValidationError) as context_manager:
+ required.clean(input)
+ self.assertEqual(context_manager.exception.messages, errors)
+
+ with self.assertRaises(ValidationError) as context_manager:
+ optional.clean(input)
+ self.assertEqual(context_manager.exception.messages, errors)
+ # test required inputs
+ error_required = [force_text(required.error_messages['required'])]
+ for e in required.empty_values:
+ with self.assertRaises(ValidationError) as context_manager:
+ required.clean(e)
+ self.assertEqual(context_manager.exception.messages,
+ error_required)
+ self.assertEqual(optional.clean(e), empty_value)
+ # test that max_length and min_length are always accepted
+ if issubclass(fieldclass, CharField):
+ field_kwargs.update({'min_length':2, 'max_length':20})
+ self.assertTrue(isinstance(fieldclass(*field_args, **field_kwargs),
+ fieldclass))
+
+ def assertHTMLEqual(self, html1, html2, msg=None):
+ """
+ Asserts that two HTML snippets are semantically the same.
+ Whitespace in most cases is ignored, and attribute ordering is not
+ significant. The passed-in arguments must be valid HTML.
+ """
+ dom1 = assert_and_parse_html(self, html1, msg,
+ 'First argument is not valid HTML:')
+ dom2 = assert_and_parse_html(self, html2, msg,
+ 'Second argument is not valid HTML:')
+
+ if dom1 != dom2:
+ standardMsg = '%s != %s' % (
+ safe_repr(dom1, True), safe_repr(dom2, True))
+ diff = ('\n' + '\n'.join(difflib.ndiff(
+ six.text_type(dom1).splitlines(),
+ six.text_type(dom2).splitlines())))
+ standardMsg = self._truncateMessage(standardMsg, diff)
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertHTMLNotEqual(self, html1, html2, msg=None):
+ """Asserts that two HTML snippets are not semantically equivalent."""
+ dom1 = assert_and_parse_html(self, html1, msg,
+ 'First argument is not valid HTML:')
+ dom2 = assert_and_parse_html(self, html2, msg,
+ 'Second argument is not valid HTML:')
+
+ if dom1 == dom2:
+ standardMsg = '%s == %s' % (
+ safe_repr(dom1, True), safe_repr(dom2, True))
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertInHTML(self, needle, haystack, count=None, msg_prefix=''):
+ needle = assert_and_parse_html(self, needle, None,
+ 'First argument is not valid HTML:')
+ haystack = assert_and_parse_html(self, haystack, None,
+ 'Second argument is not valid HTML:')
+ real_count = haystack.count(needle)
+ if count is not None:
+ self.assertEqual(real_count, count,
+ msg_prefix + "Found %d instances of '%s' in response"
+ " (expected %d)" % (real_count, needle, count))
+ else:
+ self.assertTrue(real_count != 0,
+ msg_prefix + "Couldn't find '%s' in response" % needle)
+
+ def assertJSONEqual(self, raw, expected_data, msg=None):
+ try:
+ data = json.loads(raw)
+ except ValueError:
+ self.fail("First argument is not valid JSON: %r" % raw)
+ if isinstance(expected_data, six.string_types):
+ try:
+ expected_data = json.loads(expected_data)
+ except ValueError:
+ self.fail("Second argument is not valid JSON: %r" % expected_data)
+ self.assertEqual(data, expected_data, msg=msg)
+
+ def assertXMLEqual(self, xml1, xml2, msg=None):
+ """
+ Asserts that two XML snippets are semantically the same.
+ Whitespace in most cases is ignored, and attribute ordering is not
+ significant. The passed-in arguments must be valid XML.
+ """
+ try:
+ result = compare_xml(xml1, xml2)
+ except Exception as e:
+ standardMsg = 'First or second argument is not valid XML\n%s' % e
+ self.fail(self._formatMessage(msg, standardMsg))
+ else:
+ if not result:
+ standardMsg = '%s != %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertXMLNotEqual(self, xml1, xml2, msg=None):
+ """
+ Asserts that two XML snippets are not semantically equivalent.
+ Whitespace in most cases is ignored, and attribute ordering is not
+ significant. The passed-in arguments must be valid XML.
+ """
+ try:
+ result = compare_xml(xml1, xml2)
+ except Exception as e:
+ standardMsg = 'First or second argument is not valid XML\n%s' % e
+ self.fail(self._formatMessage(msg, standardMsg))
+ else:
+ if result:
+ standardMsg = '%s == %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
+ self.fail(self._formatMessage(msg, standardMsg))
+
+
+class TransactionTestCase(SimpleTestCase):
+
+ # Subclasses can ask for resetting of auto increment sequence before each
+ # test case
+ reset_sequences = False
+
+ # Subclasses can enable only a subset of apps for faster tests
+ available_apps = None
+
+ def _pre_setup(self):
+ """Performs any pre-test setup. This includes:
+
+ * If the class has an 'available_apps' attribute, restricting the app
+ cache to these applications, then firing post_syncdb -- it must run
+ with the correct set of applications for the test case.
+ * If the class has a 'fixtures' attribute, installing these fixtures.
+ """
+ super(TransactionTestCase, self)._pre_setup()
+ if self.available_apps is not None:
+ cache.set_available_apps(self.available_apps)
+ for db_name in self._databases_names(include_mirrors=False):
+ flush.Command.emit_post_syncdb(
+ verbosity=0, interactive=False, database=db_name)
+ try:
+ self._fixture_setup()
+ except Exception:
+ if self.available_apps is not None:
+ cache.unset_available_apps()
+ raise
+
+ def _databases_names(self, include_mirrors=True):
+ # If the test case has a multi_db=True flag, act on all databases,
+ # including mirrors or not. Otherwise, just on the default DB.
+ if getattr(self, 'multi_db', False):
+ return [alias for alias in connections
+ if include_mirrors or not connections[alias].settings_dict['TEST_MIRROR']]
+ else:
+ return [DEFAULT_DB_ALIAS]
+
+ def _reset_sequences(self, db_name):
+ conn = connections[db_name]
+ if conn.features.supports_sequence_reset:
+ sql_list = \
+ conn.ops.sequence_reset_by_name_sql(no_style(),
+ conn.introspection.sequence_list())
+ if sql_list:
+ with transaction.commit_on_success_unless_managed(using=db_name):
+ cursor = conn.cursor()
+ for sql in sql_list:
+ cursor.execute(sql)
+
+ def _fixture_setup(self):
+ for db_name in self._databases_names(include_mirrors=False):
+ # Reset sequences
+ if self.reset_sequences:
+ self._reset_sequences(db_name)
+
+ if hasattr(self, 'fixtures'):
+ # We have to use this slightly awkward syntax due to the fact
+ # that we're using *args and **kwargs together.
+ call_command('loaddata', *self.fixtures,
+ **{'verbosity': 0, 'database': db_name, 'skip_validation': True})
+
+ def _post_teardown(self):
+ """Performs any post-test things. This includes:
+
+ * Flushing the contents of the database, to leave a clean slate. If
+ the class has an 'available_apps' attribute, post_syncdb isn't fired.
+ * Force-closing the connection, so the next test gets a clean cursor.
+ """
+ try:
+ self._fixture_teardown()
+ super(TransactionTestCase, self)._post_teardown()
+ # Some DB cursors include SQL statements as part of cursor
+ # creation. If you have a test that does rollback, the effect of
+ # these statements is lost, which can effect the operation of
+ # tests (e.g., losing a timezone setting causing objects to be
+ # created with the wrong time). To make sure this doesn't happen,
+ # get a clean connection at the start of every test.
+ for conn in connections.all():
+ conn.close()
+ finally:
+ cache.unset_available_apps()
+
+ def _fixture_teardown(self):
+ # Allow TRUNCATE ... CASCADE and don't emit the post_syncdb signal
+ # when flushing only a subset of the apps
+ for db_name in self._databases_names(include_mirrors=False):
+ call_command('flush', verbosity=0, interactive=False,
+ database=db_name, skip_validation=True,
+ reset_sequences=False,
+ allow_cascade=self.available_apps is not None,
+ inhibit_post_syncdb=self.available_apps is not None)
+
+ def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True):
+ items = six.moves.map(transform, qs)
+ if not ordered:
+ return self.assertEqual(set(items), set(values))
+ values = list(values)
+ # For example qs.iterator() could be passed as qs, but it does not
+ # have 'ordered' attribute.
+ if len(values) > 1 and hasattr(qs, 'ordered') and not qs.ordered:
+ raise ValueError("Trying to compare non-ordered queryset "
+ "against more than one ordered values")
+ return self.assertEqual(list(items), values)
+
+ def assertNumQueries(self, num, func=None, *args, **kwargs):
+ using = kwargs.pop("using", DEFAULT_DB_ALIAS)
+ conn = connections[using]
+
+ context = _AssertNumQueriesContext(self, num, conn)
+ if func is None:
+ return context
+
+ with context:
+ func(*args, **kwargs)
+
+
+def connections_support_transactions():
+ """
+ Returns True if all connections support transactions.
+ """
+ return all(conn.features.supports_transactions
+ for conn in connections.all())
+
+
+class TestCase(TransactionTestCase):
+ """
+ Does basically the same as TransactionTestCase, but surrounds every test
+ with a transaction, monkey-patches the real transaction management routines
+ to do nothing, and rollsback the test transaction at the end of the test.
+ You have to use TransactionTestCase, if you need transaction management
+ inside a test.
+ """
+
+ def _fixture_setup(self):
+ if not connections_support_transactions():
+ return super(TestCase, self)._fixture_setup()
+
+ assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
+
+ self.atomics = {}
+ for db_name in self._databases_names():
+ self.atomics[db_name] = transaction.atomic(using=db_name)
+ self.atomics[db_name].__enter__()
+ # Remove this when the legacy transaction management goes away.
+ disable_transaction_methods()
+
+ for db_name in self._databases_names(include_mirrors=False):
+ if hasattr(self, 'fixtures'):
+ try:
+ call_command('loaddata', *self.fixtures,
+ **{
+ 'verbosity': 0,
+ 'commit': False,
+ 'database': db_name,
+ 'skip_validation': True,
+ })
+ except Exception:
+ self._fixture_teardown()
+ raise
+
+ def _fixture_teardown(self):
+ if not connections_support_transactions():
+ return super(TestCase, self)._fixture_teardown()
+
+ # Remove this when the legacy transaction management goes away.
+ restore_transaction_methods()
+ for db_name in reversed(self._databases_names()):
+ # Hack to force a rollback
+ connections[db_name].needs_rollback = True
+ self.atomics[db_name].__exit__(None, None, None)
+
+
+def _deferredSkip(condition, reason):
+ def decorator(test_func):
+ if not (isinstance(test_func, type) and
+ issubclass(test_func, TestCase)):
+ @wraps(test_func)
+ def skip_wrapper(*args, **kwargs):
+ if condition():
+ raise ut2.SkipTest(reason)
+ return test_func(*args, **kwargs)
+ test_item = skip_wrapper
+ else:
+ test_item = test_func
+ test_item.__unittest_skip_why__ = reason
+ return test_item
+ return decorator
+
+
+def skipIfDBFeature(feature):
+ """
+ Skip a test if a database has the named feature
+ """
+ return _deferredSkip(lambda: getattr(connection.features, feature),
+ "Database has feature %s" % feature)
+
+
+def skipUnlessDBFeature(feature):
+ """
+ Skip a test unless a database has the named feature
+ """
+ return _deferredSkip(lambda: not getattr(connection.features, feature),
+ "Database doesn't support feature %s" % feature)
+
+
+class QuietWSGIRequestHandler(WSGIRequestHandler):
+ """
+ Just a regular WSGIRequestHandler except it doesn't log to the standard
+ output any of the requests received, so as to not clutter the output for
+ the tests' results.
+ """
+
+ def log_message(*args):
+ pass
+
+
+if sys.version_info >= (3, 3, 0):
+ _ImprovedEvent = threading.Event
+elif sys.version_info >= (2, 7, 0):
+ _ImprovedEvent = threading._Event
+else:
+ class _ImprovedEvent(threading._Event):
+ """
+ Does the same as `threading.Event` except it overrides the wait() method
+ with some code borrowed from Python 2.7 to return the set state of the
+ event (see: http://hg.python.org/cpython/rev/b5aa8aa78c0f/). This allows
+ to know whether the wait() method exited normally or because of the
+ timeout. This class can be removed when Django supports only Python >= 2.7.
+ """
+
+ def wait(self, timeout=None):
+ self._Event__cond.acquire()
+ try:
+ if not self._Event__flag:
+ self._Event__cond.wait(timeout)
+ return self._Event__flag
+ finally:
+ self._Event__cond.release()
+
+
+class StoppableWSGIServer(WSGIServer):
+ """
+ The code in this class is borrowed from the `SocketServer.BaseServer` class
+ in Python 2.6. The important functionality here is that the server is non-
+ blocking and that it can be shut down at any moment. This is made possible
+ by the server regularly polling the socket and checking if it has been
+ asked to stop.
+ Note for the future: Once Django stops supporting Python 2.6, this class
+ can be removed as `WSGIServer` will have this ability to shutdown on
+ demand and will not require the use of the _ImprovedEvent class whose code
+ is borrowed from Python 2.7.
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(StoppableWSGIServer, self).__init__(*args, **kwargs)
+ self.__is_shut_down = _ImprovedEvent()
+ self.__serving = False
+
+ def serve_forever(self, poll_interval=0.5):
+ """
+ Handle one request at a time until shutdown.
+
+ Polls for shutdown every poll_interval seconds.
+ """
+ self.__serving = True
+ self.__is_shut_down.clear()
+ while self.__serving:
+ r, w, e = select.select([self], [], [], poll_interval)
+ if r:
+ self._handle_request_noblock()
+ self.__is_shut_down.set()
+
+ def shutdown(self):
+ """
+ Stops the serve_forever loop.
+
+ Blocks until the loop has finished. This must be called while
+ serve_forever() is running in another thread, or it will
+ deadlock.
+ """
+ self.__serving = False
+ if not self.__is_shut_down.wait(2):
+ raise RuntimeError(
+ "Failed to shutdown the live test server in 2 seconds. The "
+ "server might be stuck or generating a slow response.")
+
+ def handle_request(self):
+ """Handle one request, possibly blocking.
+ """
+ fd_sets = select.select([self], [], [], None)
+ if not fd_sets[0]:
+ return
+ self._handle_request_noblock()
+
+ def _handle_request_noblock(self):
+ """
+ Handle one request, without blocking.
+
+ I assume that select.select has returned that the socket is
+ readable before this function was called, so there should be
+ no risk of blocking in get_request().
+ """
+ try:
+ request, client_address = self.get_request()
+ except socket.error:
+ return
+ if self.verify_request(request, client_address):
+ try:
+ self.process_request(request, client_address)
+ except Exception:
+ self.handle_error(request, client_address)
+ self.close_request(request)
+
+
+class _MediaFilesHandler(StaticFilesHandler):
+ """
+ Handler for serving the media files. This is a private class that is
+ meant to be used solely as a convenience by LiveServerThread.
+ """
+
+ def get_base_dir(self):
+ return settings.MEDIA_ROOT
+
+ def get_base_url(self):
+ return settings.MEDIA_URL
+
+ def serve(self, request):
+ relative_url = request.path[len(self.base_url[2]):]
+ return serve(request, relative_url, document_root=self.get_base_dir())
+
+
+class LiveServerThread(threading.Thread):
+ """
+ Thread for running a live http server while the tests are running.
+ """
+
+ def __init__(self, host, possible_ports, connections_override=None):
+ self.host = host
+ self.port = None
+ self.possible_ports = possible_ports
+ self.is_ready = threading.Event()
+ self.error = None
+ self.connections_override = connections_override
+ super(LiveServerThread, self).__init__()
+
+ def run(self):
+ """
+ Sets up the live server and databases, and then loops over handling
+ http requests.
+ """
+ if self.connections_override:
+ # Override this thread's database connections with the ones
+ # provided by the main thread.
+ for alias, conn in self.connections_override.items():
+ connections[alias] = conn
+ try:
+ # Create the handler for serving static and media files
+ handler = StaticFilesHandler(_MediaFilesHandler(WSGIHandler()))
+
+ # Go through the list of possible ports, hoping that we can find
+ # one that is free to use for the WSGI server.
+ for index, port in enumerate(self.possible_ports):
+ try:
+ self.httpd = StoppableWSGIServer(
+ (self.host, port), QuietWSGIRequestHandler)
+ except socket.error as e:
+ if (index + 1 < len(self.possible_ports) and
+ e.errno == errno.EADDRINUSE):
+ # This port is already in use, so we go on and try with
+ # the next one in the list.
+ continue
+ else:
+ # Either none of the given ports are free or the error
+ # is something else than "Address already in use". So
+ # we let that error bubble up to the main thread.
+ raise
+ else:
+ # A free port was found.
+ self.port = port
+ break
+
+ self.httpd.set_app(handler)
+ self.is_ready.set()
+ self.httpd.serve_forever()
+ except Exception as e:
+ self.error = e
+ self.is_ready.set()
+
+ def join(self, timeout=None):
+ if hasattr(self, 'httpd'):
+ # Stop the WSGI server
+ self.httpd.shutdown()
+ self.httpd.server_close()
+ super(LiveServerThread, self).join(timeout)
+
+
+class LiveServerTestCase(TransactionTestCase):
+ """
+ Does basically the same as TransactionTestCase but also launches a live
+ http server in a separate thread so that the tests may use another testing
+ framework, such as Selenium for example, instead of the built-in dummy
+ client.
+ Note that it inherits from TransactionTestCase instead of TestCase because
+ the threads do not share the same transactions (unless if using in-memory
+ sqlite) and each thread needs to commit all their transactions so that the
+ other thread can see the changes.
+ """
+
+ @property
+ def live_server_url(self):
+ return 'http://%s:%s' % (
+ self.server_thread.host, self.server_thread.port)
+
+ @classmethod
+ def setUpClass(cls):
+ connections_override = {}
+ for conn in connections.all():
+ # If using in-memory sqlite databases, pass the connections to
+ # the server thread.
+ if (conn.settings_dict['ENGINE'].rsplit('.', 1)[-1] in ('sqlite3', 'spatialite')
+ and conn.settings_dict['NAME'] == ':memory:'):
+ # Explicitly enable thread-shareability for this connection
+ conn.allow_thread_sharing = True
+ connections_override[conn.alias] = conn
+
+ # Launch the live server's thread
+ specified_address = os.environ.get(
+ 'DJANGO_LIVE_TEST_SERVER_ADDRESS', 'localhost:8081')
+
+ # The specified ports may be of the form '8000-8010,8080,9200-9300'
+ # i.e. a comma-separated list of ports or ranges of ports, so we break
+ # it down into a detailed list of all possible ports.
+ possible_ports = []
+ try:
+ host, port_ranges = specified_address.split(':')
+ for port_range in port_ranges.split(','):
+ # A port range can be of either form: '8000' or '8000-8010'.
+ extremes = list(map(int, port_range.split('-')))
+ assert len(extremes) in [1, 2]
+ if len(extremes) == 1:
+ # Port range of the form '8000'
+ possible_ports.append(extremes[0])
+ else:
+ # Port range of the form '8000-8010'
+ for port in range(extremes[0], extremes[1] + 1):
+ possible_ports.append(port)
+ except Exception:
+ msg = 'Invalid address ("%s") for live server.' % specified_address
+ six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg), sys.exc_info()[2])
+ cls.server_thread = LiveServerThread(
+ host, possible_ports, connections_override)
+ cls.server_thread.daemon = True
+ cls.server_thread.start()
+
+ # Wait for the live server to be ready
+ cls.server_thread.is_ready.wait()
+ if cls.server_thread.error:
+ # Clean up behind ourselves, since tearDownClass won't get called in
+ # case of errors.
+ cls._tearDownClassInternal()
+ raise cls.server_thread.error
+
+ super(LiveServerTestCase, cls).setUpClass()
+
+ @classmethod
+ def _tearDownClassInternal(cls):
+ # There may not be a 'server_thread' attribute if setUpClass() for some
+ # reasons has raised an exception.
+ if hasattr(cls, 'server_thread'):
+ # Terminate the live server's thread
+ cls.server_thread.join()
+
+ # Restore sqlite connections' non-sharability
+ for conn in connections.all():
+ if (conn.settings_dict['ENGINE'].rsplit('.', 1)[-1] in ('sqlite3', 'spatialite')
+ and conn.settings_dict['NAME'] == ':memory:'):
+ conn.allow_thread_sharing = False
+
+ @classmethod
+ def tearDownClass(cls):
+ cls._tearDownClassInternal()
+ super(LiveServerTestCase, cls).tearDownClass()
diff --git a/lib/python2.7/site-packages/django/test/utils.py b/lib/python2.7/site-packages/django/test/utils.py
new file mode 100644
index 0000000..818ccaf
--- /dev/null
+++ b/lib/python2.7/site-packages/django/test/utils.py
@@ -0,0 +1,469 @@
+from contextlib import contextmanager
+import logging
+import re
+import sys
+from threading import local
+import time
+import warnings
+from functools import wraps
+from xml.dom.minidom import parseString, Node
+
+from django.conf import settings, UserSettingsHolder
+from django.core import mail
+from django.core.signals import request_started
+from django.db import reset_queries
+from django.http import request
+from django.template import Template, loader, TemplateDoesNotExist
+from django.template.loaders import cached
+from django.test.signals import template_rendered, setting_changed
+from django.utils.encoding import force_str
+from django.utils import six
+from django.utils.translation import deactivate
+from django.utils.unittest import skipUnless
+
+
+__all__ = (
+ 'Approximate', 'ContextList', 'get_runner', 'override_settings',
+ 'requires_tz_support', 'setup_test_environment', 'teardown_test_environment',
+)
+
+RESTORE_LOADERS_ATTR = '_original_template_source_loaders'
+TZ_SUPPORT = hasattr(time, 'tzset')
+
+
+class Approximate(object):
+ def __init__(self, val, places=7):
+ self.val = val
+ self.places = places
+
+ def __repr__(self):
+ return repr(self.val)
+
+ def __eq__(self, other):
+ if self.val == other:
+ return True
+ return round(abs(self.val - other), self.places) == 0
+
+
+class ContextList(list):
+ """A wrapper that provides direct key access to context items contained
+ in a list of context objects.
+ """
+ def __getitem__(self, key):
+ if isinstance(key, six.string_types):
+ for subcontext in self:
+ if key in subcontext:
+ return subcontext[key]
+ raise KeyError(key)
+ else:
+ return super(ContextList, self).__getitem__(key)
+
+ def __contains__(self, key):
+ try:
+ self[key]
+ except KeyError:
+ return False
+ return True
+
+ def keys(self):
+ """
+ Flattened keys of subcontexts.
+ """
+ keys = set()
+ for subcontext in self:
+ for dict in subcontext:
+ keys |= set(dict.keys())
+ return keys
+
+
+def instrumented_test_render(self, context):
+ """
+ An instrumented Template render method, providing a signal
+ that can be intercepted by the test system Client
+ """
+ template_rendered.send(sender=self, template=self, context=context)
+ return self.nodelist.render(context)
+
+
+def setup_test_environment():
+ """Perform any global pre-test setup. This involves:
+
+ - Installing the instrumented test renderer
+ - Set the email backend to the locmem email backend.
+ - Setting the active locale to match the LANGUAGE_CODE setting.
+ """
+ Template._original_render = Template._render
+ Template._render = instrumented_test_render
+
+ # Storing previous values in the settings module itself is problematic.
+ # Store them in arbitrary (but related) modules instead. See #20636.
+
+ mail._original_email_backend = settings.EMAIL_BACKEND
+ settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
+
+ request._original_allowed_hosts = settings.ALLOWED_HOSTS
+ settings.ALLOWED_HOSTS = ['*']
+
+ mail.outbox = []
+
+ deactivate()
+
+
+def teardown_test_environment():
+ """Perform any global post-test teardown. This involves:
+
+ - Restoring the original test renderer
+ - Restoring the email sending functions
+
+ """
+ Template._render = Template._original_render
+ del Template._original_render
+
+ settings.EMAIL_BACKEND = mail._original_email_backend
+ del mail._original_email_backend
+
+ settings.ALLOWED_HOSTS = request._original_allowed_hosts
+ del request._original_allowed_hosts
+
+ del mail.outbox
+
+
+warn_txt = ("get_warnings_state/restore_warnings_state functions from "
+ "django.test.utils are deprecated. Use Python's warnings.catch_warnings() "
+ "context manager instead.")
+
+
+def get_warnings_state():
+ """
+ Returns an object containing the state of the warnings module
+ """
+ # There is no public interface for doing this, but this implementation of
+ # get_warnings_state and restore_warnings_state appears to work on Python
+ # 2.4 to 2.7.
+ warnings.warn(warn_txt, DeprecationWarning, stacklevel=2)
+ return warnings.filters[:]
+
+
+def restore_warnings_state(state):
+ """
+ Restores the state of the warnings module when passed an object that was
+ returned by get_warnings_state()
+ """
+ warnings.warn(warn_txt, DeprecationWarning, stacklevel=2)
+ warnings.filters = state[:]
+
+
+def get_runner(settings, test_runner_class=None):
+ if not test_runner_class:
+ test_runner_class = settings.TEST_RUNNER
+
+ test_path = test_runner_class.split('.')
+ # Allow for Python 2.5 relative paths
+ if len(test_path) > 1:
+ test_module_name = '.'.join(test_path[:-1])
+ else:
+ test_module_name = '.'
+ test_module = __import__(test_module_name, {}, {}, force_str(test_path[-1]))
+ test_runner = getattr(test_module, test_path[-1])
+ return test_runner
+
+
+def setup_test_template_loader(templates_dict, use_cached_loader=False):
+ """
+ Changes Django to only find templates from within a dictionary (where each
+ key is the template name and each value is the corresponding template
+ content to return).
+
+ Use meth:`restore_template_loaders` to restore the original loaders.
+ """
+ if hasattr(loader, RESTORE_LOADERS_ATTR):
+ raise Exception("loader.%s already exists" % RESTORE_LOADERS_ATTR)
+
+ def test_template_loader(template_name, template_dirs=None):
+ "A custom template loader that loads templates from a dictionary."
+ try:
+ return (templates_dict[template_name], "test:%s" % template_name)
+ except KeyError:
+ raise TemplateDoesNotExist(template_name)
+
+ if use_cached_loader:
+ template_loader = cached.Loader(('test_template_loader',))
+ template_loader._cached_loaders = (test_template_loader,)
+ else:
+ template_loader = test_template_loader
+
+ setattr(loader, RESTORE_LOADERS_ATTR, loader.template_source_loaders)
+ loader.template_source_loaders = (template_loader,)
+ return template_loader
+
+
+def restore_template_loaders():
+ """
+ Restores the original template loaders after
+ :meth:`setup_test_template_loader` has been run.
+ """
+ loader.template_source_loaders = getattr(loader, RESTORE_LOADERS_ATTR)
+ delattr(loader, RESTORE_LOADERS_ATTR)
+
+
+class override_settings(object):
+ """
+ Acts as either a decorator, or a context manager. If it's a decorator it
+ takes a function and returns a wrapped function. If it's a contextmanager
+ it's used with the ``with`` statement. In either event entering/exiting
+ are called before and after, respectively, the function/block is executed.
+ """
+ def __init__(self, **kwargs):
+ self.options = kwargs
+
+ def __enter__(self):
+ self.enable()
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.disable()
+
+ def __call__(self, test_func):
+ from django.test import SimpleTestCase
+ if isinstance(test_func, type):
+ if not issubclass(test_func, SimpleTestCase):
+ raise Exception(
+ "Only subclasses of Django SimpleTestCase can be decorated "
+ "with override_settings")
+ original_pre_setup = test_func._pre_setup
+ original_post_teardown = test_func._post_teardown
+
+ def _pre_setup(innerself):
+ self.enable()
+ original_pre_setup(innerself)
+
+ def _post_teardown(innerself):
+ original_post_teardown(innerself)
+ self.disable()
+ test_func._pre_setup = _pre_setup
+ test_func._post_teardown = _post_teardown
+ return test_func
+ else:
+ @wraps(test_func)
+ def inner(*args, **kwargs):
+ with self:
+ return test_func(*args, **kwargs)
+ return inner
+
+ def enable(self):
+ override = UserSettingsHolder(settings._wrapped)
+ for key, new_value in self.options.items():
+ setattr(override, key, new_value)
+ self.wrapped = settings._wrapped
+ settings._wrapped = override
+ for key, new_value in self.options.items():
+ setting_changed.send(sender=settings._wrapped.__class__,
+ setting=key, value=new_value)
+
+ def disable(self):
+ settings._wrapped = self.wrapped
+ del self.wrapped
+ for key in self.options:
+ new_value = getattr(settings, key, None)
+ setting_changed.send(sender=settings._wrapped.__class__,
+ setting=key, value=new_value)
+
+
+def compare_xml(want, got):
+ """Tries to do a 'xml-comparison' of want and got. Plain string
+ comparison doesn't always work because, for example, attribute
+ ordering should not be important. Comment nodes are not considered in the
+ comparison.
+
+ Based on http://codespeak.net/svn/lxml/trunk/src/lxml/doctestcompare.py
+ """
+ _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
+ def norm_whitespace(v):
+ return _norm_whitespace_re.sub(' ', v)
+
+ def child_text(element):
+ return ''.join([c.data for c in element.childNodes
+ if c.nodeType == Node.TEXT_NODE])
+
+ def children(element):
+ return [c for c in element.childNodes
+ if c.nodeType == Node.ELEMENT_NODE]
+
+ def norm_child_text(element):
+ return norm_whitespace(child_text(element))
+
+ def attrs_dict(element):
+ return dict(element.attributes.items())
+
+ def check_element(want_element, got_element):
+ if want_element.tagName != got_element.tagName:
+ return False
+ if norm_child_text(want_element) != norm_child_text(got_element):
+ return False
+ if attrs_dict(want_element) != attrs_dict(got_element):
+ return False
+ want_children = children(want_element)
+ got_children = children(got_element)
+ if len(want_children) != len(got_children):
+ return False
+ for want, got in zip(want_children, got_children):
+ if not check_element(want, got):
+ return False
+ return True
+
+ def first_node(document):
+ for node in document.childNodes:
+ if node.nodeType != Node.COMMENT_NODE:
+ return node
+
+ want, got = strip_quotes(want, got)
+ want = want.replace('\\n','\n')
+ got = got.replace('\\n','\n')
+
+ # If the string is not a complete xml document, we may need to add a
+ # root element. This allow us to compare fragments, like "<foo/><bar/>"
+ if not want.startswith('<?xml'):
+ wrapper = '<root>%s</root>'
+ want = wrapper % want
+ got = wrapper % got
+
+ # Parse the want and got strings, and compare the parsings.
+ want_root = first_node(parseString(want))
+ got_root = first_node(parseString(got))
+
+ return check_element(want_root, got_root)
+
+
+def strip_quotes(want, got):
+ """
+ Strip quotes of doctests output values:
+
+ >>> strip_quotes("'foo'")
+ "foo"
+ >>> strip_quotes('"foo"')
+ "foo"
+ """
+ def is_quoted_string(s):
+ s = s.strip()
+ return (len(s) >= 2
+ and s[0] == s[-1]
+ and s[0] in ('"', "'"))
+
+ def is_quoted_unicode(s):
+ s = s.strip()
+ return (len(s) >= 3
+ and s[0] == 'u'
+ and s[1] == s[-1]
+ and s[1] in ('"', "'"))
+
+ if is_quoted_string(want) and is_quoted_string(got):
+ want = want.strip()[1:-1]
+ got = got.strip()[1:-1]
+ elif is_quoted_unicode(want) and is_quoted_unicode(got):
+ want = want.strip()[2:-1]
+ got = got.strip()[2:-1]
+ return want, got
+
+
+def str_prefix(s):
+ return s % {'_': '' if six.PY3 else 'u'}
+
+
+class CaptureQueriesContext(object):
+ """
+ Context manager that captures queries executed by the specified connection.
+ """
+ def __init__(self, connection):
+ self.connection = connection
+
+ def __iter__(self):
+ return iter(self.captured_queries)
+
+ def __getitem__(self, index):
+ return self.captured_queries[index]
+
+ def __len__(self):
+ return len(self.captured_queries)
+
+ @property
+ def captured_queries(self):
+ return self.connection.queries[self.initial_queries:self.final_queries]
+
+ def __enter__(self):
+ self.use_debug_cursor = self.connection.use_debug_cursor
+ self.connection.use_debug_cursor = True
+ self.initial_queries = len(self.connection.queries)
+ self.final_queries = None
+ request_started.disconnect(reset_queries)
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.connection.use_debug_cursor = self.use_debug_cursor
+ request_started.connect(reset_queries)
+ if exc_type is not None:
+ return
+ self.final_queries = len(self.connection.queries)
+
+
+class IgnoreDeprecationWarningsMixin(object):
+
+ warning_class = DeprecationWarning
+
+ def setUp(self):
+ super(IgnoreDeprecationWarningsMixin, self).setUp()
+ self.catch_warnings = warnings.catch_warnings()
+ self.catch_warnings.__enter__()
+ warnings.filterwarnings("ignore", category=self.warning_class)
+
+ def tearDown(self):
+ self.catch_warnings.__exit__(*sys.exc_info())
+ super(IgnoreDeprecationWarningsMixin, self).tearDown()
+
+
+class IgnorePendingDeprecationWarningsMixin(IgnoreDeprecationWarningsMixin):
+
+ warning_class = PendingDeprecationWarning
+
+
+@contextmanager
+def patch_logger(logger_name, log_level):
+ """
+ Context manager that takes a named logger and the logging level
+ and provides a simple mock-like list of messages received
+ """
+ calls = []
+ def replacement(msg):
+ calls.append(msg)
+ logger = logging.getLogger(logger_name)
+ orig = getattr(logger, log_level)
+ setattr(logger, log_level, replacement)
+ try:
+ yield calls
+ finally:
+ setattr(logger, log_level, orig)
+
+
+class TransRealMixin(object):
+ """This is the only way to reset the translation machinery. Otherwise
+ the test suite occasionally fails because of global state pollution
+ between tests."""
+ def flush_caches(self):
+ from django.utils.translation import trans_real
+ trans_real._translations = {}
+ trans_real._active = local()
+ trans_real._default = None
+ trans_real._accepted = {}
+ trans_real._checked_languages = {}
+
+ def tearDown(self):
+ self.flush_caches()
+ super(TransRealMixin, self).tearDown()
+
+
+# On OSes that don't provide tzset (Windows), we can't set the timezone
+# in which the program runs. As a consequence, we must skip tests that
+# don't enforce a specific timezone (with timezone.override or equivalent),
+# or attempt to interpret naive datetimes in the default timezone.
+
+requires_tz_support = skipUnless(TZ_SUPPORT,
+ "This test relies on the ability to run a program in an arbitrary "
+ "time zone, but your operating system isn't able to do that.")