]> granicus.if.org Git - python/commitdiff
Issue #19535: Fixed test_docxmlrpc, test_functools, test_inspect, and
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 8 Dec 2013 16:16:18 +0000 (18:16 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Sun, 8 Dec 2013 16:16:18 +0000 (18:16 +0200)
test_statistics when python is run with -OO.

1  2 
Lib/test/test_functools.py
Lib/test/test_inspect.py
Lib/test/test_statistics.py
Misc/NEWS

index d04423777c942743522aa2a2a31ebb75d7e86b57,d1ce2a9c8efaaf854532459b963e5ec283769392..75ae7f3a15d5b2d0021be3b75d8ccb1be13f9450
@@@ -1071,490 -802,14 +1071,491 @@@ class TestLRU(unittest.TestCase)
                           DoubleEq(2))               # Verify the correct return value
  
  
-         self.assertEqual(g.__doc__, "Simple test")
 +class TestSingleDispatch(unittest.TestCase):
 +    def test_simple_overloads(self):
 +        @functools.singledispatch
 +        def g(obj):
 +            return "base"
 +        def g_int(i):
 +            return "integer"
 +        g.register(int, g_int)
 +        self.assertEqual(g("str"), "base")
 +        self.assertEqual(g(1), "integer")
 +        self.assertEqual(g([1,2,3]), "base")
 +
 +    def test_mro(self):
 +        @functools.singledispatch
 +        def g(obj):
 +            return "base"
 +        class A:
 +            pass
 +        class C(A):
 +            pass
 +        class B(A):
 +            pass
 +        class D(C, B):
 +            pass
 +        def g_A(a):
 +            return "A"
 +        def g_B(b):
 +            return "B"
 +        g.register(A, g_A)
 +        g.register(B, g_B)
 +        self.assertEqual(g(A()), "A")
 +        self.assertEqual(g(B()), "B")
 +        self.assertEqual(g(C()), "A")
 +        self.assertEqual(g(D()), "B")
 +
 +    def test_register_decorator(self):
 +        @functools.singledispatch
 +        def g(obj):
 +            return "base"
 +        @g.register(int)
 +        def g_int(i):
 +            return "int %s" % (i,)
 +        self.assertEqual(g(""), "base")
 +        self.assertEqual(g(12), "int 12")
 +        self.assertIs(g.dispatch(int), g_int)
 +        self.assertIs(g.dispatch(object), g.dispatch(str))
 +        # Note: in the assert above this is not g.
 +        # @singledispatch returns the wrapper.
 +
 +    def test_wrapping_attributes(self):
 +        @functools.singledispatch
 +        def g(obj):
 +            "Simple test"
 +            return "Test"
 +        self.assertEqual(g.__name__, "g")
++        if sys.flags.optimize < 2:
++            self.assertEqual(g.__doc__, "Simple test")
 +
 +    @unittest.skipUnless(decimal, 'requires _decimal')
 +    @support.cpython_only
 +    def test_c_classes(self):
 +        @functools.singledispatch
 +        def g(obj):
 +            return "base"
 +        @g.register(decimal.DecimalException)
 +        def _(obj):
 +            return obj.args
 +        subn = decimal.Subnormal("Exponent < Emin")
 +        rnd = decimal.Rounded("Number got rounded")
 +        self.assertEqual(g(subn), ("Exponent < Emin",))
 +        self.assertEqual(g(rnd), ("Number got rounded",))
 +        @g.register(decimal.Subnormal)
 +        def _(obj):
 +            return "Too small to care."
 +        self.assertEqual(g(subn), "Too small to care.")
 +        self.assertEqual(g(rnd), ("Number got rounded",))
 +
 +    def test_compose_mro(self):
 +        # None of the examples in this test depend on haystack ordering.
 +        c = collections
 +        mro = functools._compose_mro
 +        bases = [c.Sequence, c.MutableMapping, c.Mapping, c.Set]
 +        for haystack in permutations(bases):
 +            m = mro(dict, haystack)
 +            self.assertEqual(m, [dict, c.MutableMapping, c.Mapping, c.Sized,
 +                                 c.Iterable, c.Container, object])
 +        bases = [c.Container, c.Mapping, c.MutableMapping, c.OrderedDict]
 +        for haystack in permutations(bases):
 +            m = mro(c.ChainMap, haystack)
 +            self.assertEqual(m, [c.ChainMap, c.MutableMapping, c.Mapping,
 +                                 c.Sized, c.Iterable, c.Container, object])
 +
 +        # If there's a generic function with implementations registered for
 +        # both Sized and Container, passing a defaultdict to it results in an
 +        # ambiguous dispatch which will cause a RuntimeError (see
 +        # test_mro_conflicts).
 +        bases = [c.Container, c.Sized, str]
 +        for haystack in permutations(bases):
 +            m = mro(c.defaultdict, [c.Sized, c.Container, str])
 +            self.assertEqual(m, [c.defaultdict, dict, c.Sized, c.Container,
 +                                 object])
 +
 +        # MutableSequence below is registered directly on D. In other words, it
 +        # preceeds MutableMapping which means single dispatch will always
 +        # choose MutableSequence here.
 +        class D(c.defaultdict):
 +            pass
 +        c.MutableSequence.register(D)
 +        bases = [c.MutableSequence, c.MutableMapping]
 +        for haystack in permutations(bases):
 +            m = mro(D, bases)
 +            self.assertEqual(m, [D, c.MutableSequence, c.Sequence,
 +                                 c.defaultdict, dict, c.MutableMapping,
 +                                 c.Mapping, c.Sized, c.Iterable, c.Container,
 +                                 object])
 +
 +        # Container and Callable are registered on different base classes and
 +        # a generic function supporting both should always pick the Callable
 +        # implementation if a C instance is passed.
 +        class C(c.defaultdict):
 +            def __call__(self):
 +                pass
 +        bases = [c.Sized, c.Callable, c.Container, c.Mapping]
 +        for haystack in permutations(bases):
 +            m = mro(C, haystack)
 +            self.assertEqual(m, [C, c.Callable, c.defaultdict, dict, c.Mapping,
 +                                 c.Sized, c.Iterable, c.Container, object])
 +
 +    def test_register_abc(self):
 +        c = collections
 +        d = {"a": "b"}
 +        l = [1, 2, 3]
 +        s = {object(), None}
 +        f = frozenset(s)
 +        t = (1, 2, 3)
 +        @functools.singledispatch
 +        def g(obj):
 +            return "base"
 +        self.assertEqual(g(d), "base")
 +        self.assertEqual(g(l), "base")
 +        self.assertEqual(g(s), "base")
 +        self.assertEqual(g(f), "base")
 +        self.assertEqual(g(t), "base")
 +        g.register(c.Sized, lambda obj: "sized")
 +        self.assertEqual(g(d), "sized")
 +        self.assertEqual(g(l), "sized")
 +        self.assertEqual(g(s), "sized")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.MutableMapping, lambda obj: "mutablemapping")
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(g(l), "sized")
 +        self.assertEqual(g(s), "sized")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.ChainMap, lambda obj: "chainmap")
 +        self.assertEqual(g(d), "mutablemapping")  # irrelevant ABCs registered
 +        self.assertEqual(g(l), "sized")
 +        self.assertEqual(g(s), "sized")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.MutableSequence, lambda obj: "mutablesequence")
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "sized")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.MutableSet, lambda obj: "mutableset")
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.Mapping, lambda obj: "mapping")
 +        self.assertEqual(g(d), "mutablemapping")  # not specific enough
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sized")
 +        g.register(c.Sequence, lambda obj: "sequence")
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "sized")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(c.Set, lambda obj: "set")
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "set")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(dict, lambda obj: "dict")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "mutablesequence")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "set")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(list, lambda obj: "list")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(g(s), "mutableset")
 +        self.assertEqual(g(f), "set")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(set, lambda obj: "concrete-set")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(g(s), "concrete-set")
 +        self.assertEqual(g(f), "set")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(frozenset, lambda obj: "frozen-set")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(g(s), "concrete-set")
 +        self.assertEqual(g(f), "frozen-set")
 +        self.assertEqual(g(t), "sequence")
 +        g.register(tuple, lambda obj: "tuple")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(g(s), "concrete-set")
 +        self.assertEqual(g(f), "frozen-set")
 +        self.assertEqual(g(t), "tuple")
 +
 +    def test_c3_abc(self):
 +        c = collections
 +        mro = functools._c3_mro
 +        class A(object):
 +            pass
 +        class B(A):
 +            def __len__(self):
 +                return 0   # implies Sized
 +        @c.Container.register
 +        class C(object):
 +            pass
 +        class D(object):
 +            pass   # unrelated
 +        class X(D, C, B):
 +            def __call__(self):
 +                pass   # implies Callable
 +        expected = [X, c.Callable, D, C, c.Container, B, c.Sized, A, object]
 +        for abcs in permutations([c.Sized, c.Callable, c.Container]):
 +            self.assertEqual(mro(X, abcs=abcs), expected)
 +        # unrelated ABCs don't appear in the resulting MRO
 +        many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable]
 +        self.assertEqual(mro(X, abcs=many_abcs), expected)
 +
 +    def test_mro_conflicts(self):
 +        c = collections
 +        @functools.singledispatch
 +        def g(arg):
 +            return "base"
 +        class O(c.Sized):
 +            def __len__(self):
 +                return 0
 +        o = O()
 +        self.assertEqual(g(o), "base")
 +        g.register(c.Iterable, lambda arg: "iterable")
 +        g.register(c.Container, lambda arg: "container")
 +        g.register(c.Sized, lambda arg: "sized")
 +        g.register(c.Set, lambda arg: "set")
 +        self.assertEqual(g(o), "sized")
 +        c.Iterable.register(O)
 +        self.assertEqual(g(o), "sized")   # because it's explicitly in __mro__
 +        c.Container.register(O)
 +        self.assertEqual(g(o), "sized")   # see above: Sized is in __mro__
 +        c.Set.register(O)
 +        self.assertEqual(g(o), "set")     # because c.Set is a subclass of
 +                                          # c.Sized and c.Container
 +        class P:
 +            pass
 +        p = P()
 +        self.assertEqual(g(p), "base")
 +        c.Iterable.register(P)
 +        self.assertEqual(g(p), "iterable")
 +        c.Container.register(P)
 +        with self.assertRaises(RuntimeError) as re_one:
 +            g(p)
 +        self.assertIn(
 +            str(re_one.exception),
 +            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
 +              "or <class 'collections.abc.Iterable'>"),
 +             ("Ambiguous dispatch: <class 'collections.abc.Iterable'> "
 +              "or <class 'collections.abc.Container'>")),
 +        )
 +        class Q(c.Sized):
 +            def __len__(self):
 +                return 0
 +        q = Q()
 +        self.assertEqual(g(q), "sized")
 +        c.Iterable.register(Q)
 +        self.assertEqual(g(q), "sized")   # because it's explicitly in __mro__
 +        c.Set.register(Q)
 +        self.assertEqual(g(q), "set")     # because c.Set is a subclass of
 +                                          # c.Sized and c.Iterable
 +        @functools.singledispatch
 +        def h(arg):
 +            return "base"
 +        @h.register(c.Sized)
 +        def _(arg):
 +            return "sized"
 +        @h.register(c.Container)
 +        def _(arg):
 +            return "container"
 +        # Even though Sized and Container are explicit bases of MutableMapping,
 +        # this ABC is implicitly registered on defaultdict which makes all of
 +        # MutableMapping's bases implicit as well from defaultdict's
 +        # perspective.
 +        with self.assertRaises(RuntimeError) as re_two:
 +            h(c.defaultdict(lambda: 0))
 +        self.assertIn(
 +            str(re_two.exception),
 +            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
 +              "or <class 'collections.abc.Sized'>"),
 +             ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
 +              "or <class 'collections.abc.Container'>")),
 +        )
 +        class R(c.defaultdict):
 +            pass
 +        c.MutableSequence.register(R)
 +        @functools.singledispatch
 +        def i(arg):
 +            return "base"
 +        @i.register(c.MutableMapping)
 +        def _(arg):
 +            return "mapping"
 +        @i.register(c.MutableSequence)
 +        def _(arg):
 +            return "sequence"
 +        r = R()
 +        self.assertEqual(i(r), "sequence")
 +        class S:
 +            pass
 +        class T(S, c.Sized):
 +            def __len__(self):
 +                return 0
 +        t = T()
 +        self.assertEqual(h(t), "sized")
 +        c.Container.register(T)
 +        self.assertEqual(h(t), "sized")   # because it's explicitly in the MRO
 +        class U:
 +            def __len__(self):
 +                return 0
 +        u = U()
 +        self.assertEqual(h(u), "sized")   # implicit Sized subclass inferred
 +                                          # from the existence of __len__()
 +        c.Container.register(U)
 +        # There is no preference for registered versus inferred ABCs.
 +        with self.assertRaises(RuntimeError) as re_three:
 +            h(u)
 +        self.assertIn(
 +            str(re_three.exception),
 +            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
 +              "or <class 'collections.abc.Sized'>"),
 +             ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
 +              "or <class 'collections.abc.Container'>")),
 +        )
 +        class V(c.Sized, S):
 +            def __len__(self):
 +                return 0
 +        @functools.singledispatch
 +        def j(arg):
 +            return "base"
 +        @j.register(S)
 +        def _(arg):
 +            return "s"
 +        @j.register(c.Container)
 +        def _(arg):
 +            return "container"
 +        v = V()
 +        self.assertEqual(j(v), "s")
 +        c.Container.register(V)
 +        self.assertEqual(j(v), "container")   # because it ends up right after
 +                                              # Sized in the MRO
 +
 +    def test_cache_invalidation(self):
 +        from collections import UserDict
 +        class TracingDict(UserDict):
 +            def __init__(self, *args, **kwargs):
 +                super(TracingDict, self).__init__(*args, **kwargs)
 +                self.set_ops = []
 +                self.get_ops = []
 +            def __getitem__(self, key):
 +                result = self.data[key]
 +                self.get_ops.append(key)
 +                return result
 +            def __setitem__(self, key, value):
 +                self.set_ops.append(key)
 +                self.data[key] = value
 +            def clear(self):
 +                self.data.clear()
 +        _orig_wkd = functools.WeakKeyDictionary
 +        td = TracingDict()
 +        functools.WeakKeyDictionary = lambda: td
 +        c = collections
 +        @functools.singledispatch
 +        def g(arg):
 +            return "base"
 +        d = {}
 +        l = []
 +        self.assertEqual(len(td), 0)
 +        self.assertEqual(g(d), "base")
 +        self.assertEqual(len(td), 1)
 +        self.assertEqual(td.get_ops, [])
 +        self.assertEqual(td.set_ops, [dict])
 +        self.assertEqual(td.data[dict], g.registry[object])
 +        self.assertEqual(g(l), "base")
 +        self.assertEqual(len(td), 2)
 +        self.assertEqual(td.get_ops, [])
 +        self.assertEqual(td.set_ops, [dict, list])
 +        self.assertEqual(td.data[dict], g.registry[object])
 +        self.assertEqual(td.data[list], g.registry[object])
 +        self.assertEqual(td.data[dict], td.data[list])
 +        self.assertEqual(g(l), "base")
 +        self.assertEqual(g(d), "base")
 +        self.assertEqual(td.get_ops, [list, dict])
 +        self.assertEqual(td.set_ops, [dict, list])
 +        g.register(list, lambda arg: "list")
 +        self.assertEqual(td.get_ops, [list, dict])
 +        self.assertEqual(len(td), 0)
 +        self.assertEqual(g(d), "base")
 +        self.assertEqual(len(td), 1)
 +        self.assertEqual(td.get_ops, [list, dict])
 +        self.assertEqual(td.set_ops, [dict, list, dict])
 +        self.assertEqual(td.data[dict],
 +                         functools._find_impl(dict, g.registry))
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(len(td), 2)
 +        self.assertEqual(td.get_ops, [list, dict])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list])
 +        self.assertEqual(td.data[list],
 +                         functools._find_impl(list, g.registry))
 +        class X:
 +            pass
 +        c.MutableMapping.register(X)   # Will not invalidate the cache,
 +                                       # not using ABCs yet.
 +        self.assertEqual(g(d), "base")
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(td.get_ops, [list, dict, dict, list])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list])
 +        g.register(c.Sized, lambda arg: "sized")
 +        self.assertEqual(len(td), 0)
 +        self.assertEqual(g(d), "sized")
 +        self.assertEqual(len(td), 1)
 +        self.assertEqual(td.get_ops, [list, dict, dict, list])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list, dict])
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(len(td), 2)
 +        self.assertEqual(td.get_ops, [list, dict, dict, list])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(g(d), "sized")
 +        self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
 +        g.dispatch(list)
 +        g.dispatch(dict)
 +        self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict,
 +                                      list, dict])
 +        self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
 +        c.MutableSet.register(X)       # Will invalidate the cache.
 +        self.assertEqual(len(td), 2)   # Stale cache.
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(len(td), 1)
 +        g.register(c.MutableMapping, lambda arg: "mutablemapping")
 +        self.assertEqual(len(td), 0)
 +        self.assertEqual(g(d), "mutablemapping")
 +        self.assertEqual(len(td), 1)
 +        self.assertEqual(g(l), "list")
 +        self.assertEqual(len(td), 2)
 +        g.register(dict, lambda arg: "dict")
 +        self.assertEqual(g(d), "dict")
 +        self.assertEqual(g(l), "list")
 +        g._clear_cache()
 +        self.assertEqual(len(td), 0)
 +        functools.WeakKeyDictionary = _orig_wkd
 +
 +
  def test_main(verbose=None):
      test_classes = (
 -        TestPartial,
 -        TestPartialSubclass,
 -        TestPythonPartial,
 +        TestPartialC,
 +        TestPartialPy,
 +        TestPartialCSubclass,
 +        TestPartialMethod,
          TestUpdateWrapper,
          TestTotalOrdering,
 -        TestCmpToKey,
 +        TestCmpToKeyC,
 +        TestCmpToKeyPy,
          TestWraps,
          TestReduce,
          TestLRU,
index 365f59230a48bffa3108b8d60ee91dc2d2d9be77,5cbec9bb17b4593cb04720b4041f7cf347ae5a46..520bf0e60832f3f8215ffa2ebfeddf530b972527
@@@ -2438,103 -2301,6 +2438,104 @@@ class TestBoundArguments(unittest.TestC
          self.assertNotEqual(ba, ba4)
  
  
-         self.assertIn(module.__cached__, output)
 +class TestUnwrap(unittest.TestCase):
 +
 +    def test_unwrap_one(self):
 +        def func(a, b):
 +            return a + b
 +        wrapper = functools.lru_cache(maxsize=20)(func)
 +        self.assertIs(inspect.unwrap(wrapper), func)
 +
 +    def test_unwrap_several(self):
 +        def func(a, b):
 +            return a + b
 +        wrapper = func
 +        for __ in range(10):
 +            @functools.wraps(wrapper)
 +            def wrapper():
 +                pass
 +        self.assertIsNot(wrapper.__wrapped__, func)
 +        self.assertIs(inspect.unwrap(wrapper), func)
 +
 +    def test_stop(self):
 +        def func1(a, b):
 +            return a + b
 +        @functools.wraps(func1)
 +        def func2():
 +            pass
 +        @functools.wraps(func2)
 +        def wrapper():
 +            pass
 +        func2.stop_here = 1
 +        unwrapped = inspect.unwrap(wrapper,
 +                                   stop=(lambda f: hasattr(f, "stop_here")))
 +        self.assertIs(unwrapped, func2)
 +
 +    def test_cycle(self):
 +        def func1(): pass
 +        func1.__wrapped__ = func1
 +        with self.assertRaisesRegex(ValueError, 'wrapper loop'):
 +            inspect.unwrap(func1)
 +
 +        def func2(): pass
 +        func2.__wrapped__ = func1
 +        func1.__wrapped__ = func2
 +        with self.assertRaisesRegex(ValueError, 'wrapper loop'):
 +            inspect.unwrap(func1)
 +        with self.assertRaisesRegex(ValueError, 'wrapper loop'):
 +            inspect.unwrap(func2)
 +
 +    def test_unhashable(self):
 +        def func(): pass
 +        func.__wrapped__ = None
 +        class C:
 +            __hash__ = None
 +            __wrapped__ = func
 +        self.assertIsNone(inspect.unwrap(C()))
 +
 +class TestMain(unittest.TestCase):
 +    def test_only_source(self):
 +        module = importlib.import_module('unittest')
 +        rc, out, err = assert_python_ok('-m', 'inspect',
 +                                        'unittest')
 +        lines = out.decode().splitlines()
 +        # ignore the final newline
 +        self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
 +        self.assertEqual(err, b'')
 +
 +    @unittest.skipIf(ThreadPoolExecutor is None,
 +            'threads required to test __qualname__ for source files')
 +    def test_qualname_source(self):
 +        rc, out, err = assert_python_ok('-m', 'inspect',
 +                                     'concurrent.futures:ThreadPoolExecutor')
 +        lines = out.decode().splitlines()
 +        # ignore the final newline
 +        self.assertEqual(lines[:-1],
 +                         inspect.getsource(ThreadPoolExecutor).splitlines())
 +        self.assertEqual(err, b'')
 +
 +    def test_builtins(self):
 +        module = importlib.import_module('unittest')
 +        _, out, err = assert_python_failure('-m', 'inspect',
 +                                            'sys')
 +        lines = err.decode().splitlines()
 +        self.assertEqual(lines, ["Can't get info for builtin modules."])
 +
 +    def test_details(self):
 +        module = importlib.import_module('unittest')
 +        rc, out, err = assert_python_ok('-m', 'inspect',
 +                                        'unittest', '--details')
 +        output = out.decode()
 +        # Just a quick sanity check on the output
 +        self.assertIn(module.__name__, output)
 +        self.assertIn(module.__file__, output)
++        if not sys.flags.optimize:
++            self.assertIn(module.__cached__, output)
 +        self.assertEqual(err, b'')
 +
 +
 +
 +
  def test_main():
      run_unittest(
          TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
index ee585e2c1c1c3ccd043ee709342f80363af702a7,0000000000000000000000000000000000000000..3d30d88f697ecd5149498a45c995c79231ecbfb4
mode 100644,000000..100644
--- /dev/null
@@@ -1,1534 -1,0 +1,1537 @@@
 +"""Test suite for statistics module, including helper NumericTestCase and
 +approx_equal function.
 +
 +"""
 +
 +import collections
 +import decimal
 +import doctest
 +import math
 +import random
++import sys
 +import types
 +import unittest
 +
 +from decimal import Decimal
 +from fractions import Fraction
 +
 +
 +# Module to be tested.
 +import statistics
 +
 +
 +# === Helper functions and class ===
 +
 +def _calc_errors(actual, expected):
 +    """Return the absolute and relative errors between two numbers.
 +
 +    >>> _calc_errors(100, 75)
 +    (25, 0.25)
 +    >>> _calc_errors(100, 100)
 +    (0, 0.0)
 +
 +    Returns the (absolute error, relative error) between the two arguments.
 +    """
 +    base = max(abs(actual), abs(expected))
 +    abs_err = abs(actual - expected)
 +    rel_err = abs_err/base if base else float('inf')
 +    return (abs_err, rel_err)
 +
 +
 +def approx_equal(x, y, tol=1e-12, rel=1e-7):
 +    """approx_equal(x, y [, tol [, rel]]) => True|False
 +
 +    Return True if numbers x and y are approximately equal, to within some
 +    margin of error, otherwise return False. Numbers which compare equal
 +    will also compare approximately equal.
 +
 +    x is approximately equal to y if the difference between them is less than
 +    an absolute error tol or a relative error rel, whichever is bigger.
 +
 +    If given, both tol and rel must be finite, non-negative numbers. If not
 +    given, default values are tol=1e-12 and rel=1e-7.
 +
 +    >>> approx_equal(1.2589, 1.2587, tol=0.0003, rel=0)
 +    True
 +    >>> approx_equal(1.2589, 1.2587, tol=0.0001, rel=0)
 +    False
 +
 +    Absolute error is defined as abs(x-y); if that is less than or equal to
 +    tol, x and y are considered approximately equal.
 +
 +    Relative error is defined as abs((x-y)/x) or abs((x-y)/y), whichever is
 +    smaller, provided x or y are not zero. If that figure is less than or
 +    equal to rel, x and y are considered approximately equal.
 +
 +    Complex numbers are not directly supported. If you wish to compare to
 +    complex numbers, extract their real and imaginary parts and compare them
 +    individually.
 +
 +    NANs always compare unequal, even with themselves. Infinities compare
 +    approximately equal if they have the same sign (both positive or both
 +    negative). Infinities with different signs compare unequal; so do
 +    comparisons of infinities with finite numbers.
 +    """
 +    if tol < 0 or rel < 0:
 +        raise ValueError('error tolerances must be non-negative')
 +    # NANs are never equal to anything, approximately or otherwise.
 +    if math.isnan(x) or math.isnan(y):
 +        return False
 +    # Numbers which compare equal also compare approximately equal.
 +    if x == y:
 +        # This includes the case of two infinities with the same sign.
 +        return True
 +    if math.isinf(x) or math.isinf(y):
 +        # This includes the case of two infinities of opposite sign, or
 +        # one infinity and one finite number.
 +        return False
 +    # Two finite numbers.
 +    actual_error = abs(x - y)
 +    allowed_error = max(tol, rel*max(abs(x), abs(y)))
 +    return actual_error <= allowed_error
 +
 +
 +# This class exists only as somewhere to stick a docstring containing
 +# doctests. The following docstring and tests were originally in a separate
 +# module. Now that it has been merged in here, I need somewhere to hang the.
 +# docstring. Ultimately, this class will die, and the information below will
 +# either become redundant, or be moved into more appropriate places.
 +class _DoNothing:
 +    """
 +    When doing numeric work, especially with floats, exact equality is often
 +    not what you want. Due to round-off error, it is often a bad idea to try
 +    to compare floats with equality. Instead the usual procedure is to test
 +    them with some (hopefully small!) allowance for error.
 +
 +    The ``approx_equal`` function allows you to specify either an absolute
 +    error tolerance, or a relative error, or both.
 +
 +    Absolute error tolerances are simple, but you need to know the magnitude
 +    of the quantities being compared:
 +
 +    >>> approx_equal(12.345, 12.346, tol=1e-3)
 +    True
 +    >>> approx_equal(12.345e6, 12.346e6, tol=1e-3)  # tol is too small.
 +    False
 +
 +    Relative errors are more suitable when the values you are comparing can
 +    vary in magnitude:
 +
 +    >>> approx_equal(12.345, 12.346, rel=1e-4)
 +    True
 +    >>> approx_equal(12.345e6, 12.346e6, rel=1e-4)
 +    True
 +
 +    but a naive implementation of relative error testing can run into trouble
 +    around zero.
 +
 +    If you supply both an absolute tolerance and a relative error, the
 +    comparison succeeds if either individual test succeeds:
 +
 +    >>> approx_equal(12.345e6, 12.346e6, tol=1e-3, rel=1e-4)
 +    True
 +
 +    """
 +    pass
 +
 +
 +
 +# We prefer this for testing numeric values that may not be exactly equal,
 +# and avoid using TestCase.assertAlmostEqual, because it sucks :-)
 +
 +class NumericTestCase(unittest.TestCase):
 +    """Unit test class for numeric work.
 +
 +    This subclasses TestCase. In addition to the standard method
 +    ``TestCase.assertAlmostEqual``,  ``assertApproxEqual`` is provided.
 +    """
 +    # By default, we expect exact equality, unless overridden.
 +    tol = rel = 0
 +
 +    def assertApproxEqual(
 +            self, first, second, tol=None, rel=None, msg=None
 +            ):
 +        """Test passes if ``first`` and ``second`` are approximately equal.
 +
 +        This test passes if ``first`` and ``second`` are equal to
 +        within ``tol``, an absolute error, or ``rel``, a relative error.
 +
 +        If either ``tol`` or ``rel`` are None or not given, they default to
 +        test attributes of the same name (by default, 0).
 +
 +        The objects may be either numbers, or sequences of numbers. Sequences
 +        are tested element-by-element.
 +
 +        >>> class MyTest(NumericTestCase):
 +        ...     def test_number(self):
 +        ...         x = 1.0/6
 +        ...         y = sum([x]*6)
 +        ...         self.assertApproxEqual(y, 1.0, tol=1e-15)
 +        ...     def test_sequence(self):
 +        ...         a = [1.001, 1.001e-10, 1.001e10]
 +        ...         b = [1.0, 1e-10, 1e10]
 +        ...         self.assertApproxEqual(a, b, rel=1e-3)
 +        ...
 +        >>> import unittest
 +        >>> from io import StringIO  # Suppress test runner output.
 +        >>> suite = unittest.TestLoader().loadTestsFromTestCase(MyTest)
 +        >>> unittest.TextTestRunner(stream=StringIO()).run(suite)
 +        <unittest.runner.TextTestResult run=2 errors=0 failures=0>
 +
 +        """
 +        if tol is None:
 +            tol = self.tol
 +        if rel is None:
 +            rel = self.rel
 +        if (
 +                isinstance(first, collections.Sequence) and
 +                isinstance(second, collections.Sequence)
 +            ):
 +            check = self._check_approx_seq
 +        else:
 +            check = self._check_approx_num
 +        check(first, second, tol, rel, msg)
 +
 +    def _check_approx_seq(self, first, second, tol, rel, msg):
 +        if len(first) != len(second):
 +            standardMsg = (
 +                "sequences differ in length: %d items != %d items"
 +                % (len(first), len(second))
 +                )
 +            msg = self._formatMessage(msg, standardMsg)
 +            raise self.failureException(msg)
 +        for i, (a,e) in enumerate(zip(first, second)):
 +            self._check_approx_num(a, e, tol, rel, msg, i)
 +
 +    def _check_approx_num(self, first, second, tol, rel, msg, idx=None):
 +        if approx_equal(first, second, tol, rel):
 +            # Test passes. Return early, we are done.
 +            return None
 +        # Otherwise we failed.
 +        standardMsg = self._make_std_err_msg(first, second, tol, rel, idx)
 +        msg = self._formatMessage(msg, standardMsg)
 +        raise self.failureException(msg)
 +
 +    @staticmethod
 +    def _make_std_err_msg(first, second, tol, rel, idx):
 +        # Create the standard error message for approx_equal failures.
 +        assert first != second
 +        template = (
 +            '  %r != %r\n'
 +            '  values differ by more than tol=%r and rel=%r\n'
 +            '  -> absolute error = %r\n'
 +            '  -> relative error = %r'
 +            )
 +        if idx is not None:
 +            header = 'numeric sequences first differ at index %d.\n' % idx
 +            template = header + template
 +        # Calculate actual errors:
 +        abs_err, rel_err = _calc_errors(first, second)
 +        return template % (first, second, tol, rel, abs_err, rel_err)
 +
 +
 +# ========================
 +# === Test the helpers ===
 +# ========================
 +
 +
 +# --- Tests for approx_equal ---
 +
 +class ApproxEqualSymmetryTest(unittest.TestCase):
 +    # Test symmetry of approx_equal.
 +
 +    def test_relative_symmetry(self):
 +        # Check that approx_equal treats relative error symmetrically.
 +        # (a-b)/a is usually not equal to (a-b)/b. Ensure that this
 +        # doesn't matter.
 +        #
 +        #   Note: the reason for this test is that an early version
 +        #   of approx_equal was not symmetric. A relative error test
 +        #   would pass, or fail, depending on which value was passed
 +        #   as the first argument.
 +        #
 +        args1 = [2456, 37.8, -12.45, Decimal('2.54'), Fraction(17, 54)]
 +        args2 = [2459, 37.2, -12.41, Decimal('2.59'), Fraction(15, 54)]
 +        assert len(args1) == len(args2)
 +        for a, b in zip(args1, args2):
 +            self.do_relative_symmetry(a, b)
 +
 +    def do_relative_symmetry(self, a, b):
 +        a, b = min(a, b), max(a, b)
 +        assert a < b
 +        delta = b - a  # The absolute difference between the values.
 +        rel_err1, rel_err2 = abs(delta/a), abs(delta/b)
 +        # Choose an error margin halfway between the two.
 +        rel = (rel_err1 + rel_err2)/2
 +        # Now see that values a and b compare approx equal regardless of
 +        # which is given first.
 +        self.assertTrue(approx_equal(a, b, tol=0, rel=rel))
 +        self.assertTrue(approx_equal(b, a, tol=0, rel=rel))
 +
 +    def test_symmetry(self):
 +        # Test that approx_equal(a, b) == approx_equal(b, a)
 +        args = [-23, -2, 5, 107, 93568]
 +        delta = 2
 +        for a in args:
 +            for type_ in (int, float, Decimal, Fraction):
 +                x = type_(a)*100
 +                y = x + delta
 +                r = abs(delta/max(x, y))
 +                # There are five cases to check:
 +                # 1) actual error <= tol, <= rel
 +                self.do_symmetry_test(x, y, tol=delta, rel=r)
 +                self.do_symmetry_test(x, y, tol=delta+1, rel=2*r)
 +                # 2) actual error > tol, > rel
 +                self.do_symmetry_test(x, y, tol=delta-1, rel=r/2)
 +                # 3) actual error <= tol, > rel
 +                self.do_symmetry_test(x, y, tol=delta, rel=r/2)
 +                # 4) actual error > tol, <= rel
 +                self.do_symmetry_test(x, y, tol=delta-1, rel=r)
 +                self.do_symmetry_test(x, y, tol=delta-1, rel=2*r)
 +                # 5) exact equality test
 +                self.do_symmetry_test(x, x, tol=0, rel=0)
 +                self.do_symmetry_test(x, y, tol=0, rel=0)
 +
 +    def do_symmetry_test(self, a, b, tol, rel):
 +        template = "approx_equal comparisons don't match for %r"
 +        flag1 = approx_equal(a, b, tol, rel)
 +        flag2 = approx_equal(b, a, tol, rel)
 +        self.assertEqual(flag1, flag2, template.format((a, b, tol, rel)))
 +
 +
 +class ApproxEqualExactTest(unittest.TestCase):
 +    # Test the approx_equal function with exactly equal values.
 +    # Equal values should compare as approximately equal.
 +    # Test cases for exactly equal values, which should compare approx
 +    # equal regardless of the error tolerances given.
 +
 +    def do_exactly_equal_test(self, x, tol, rel):
 +        result = approx_equal(x, x, tol=tol, rel=rel)
 +        self.assertTrue(result, 'equality failure for x=%r' % x)
 +        result = approx_equal(-x, -x, tol=tol, rel=rel)
 +        self.assertTrue(result, 'equality failure for x=%r' % -x)
 +
 +    def test_exactly_equal_ints(self):
 +        # Test that equal int values are exactly equal.
 +        for n in [42, 19740, 14974, 230, 1795, 700245, 36587]:
 +            self.do_exactly_equal_test(n, 0, 0)
 +
 +    def test_exactly_equal_floats(self):
 +        # Test that equal float values are exactly equal.
 +        for x in [0.42, 1.9740, 1497.4, 23.0, 179.5, 70.0245, 36.587]:
 +            self.do_exactly_equal_test(x, 0, 0)
 +
 +    def test_exactly_equal_fractions(self):
 +        # Test that equal Fraction values are exactly equal.
 +        F = Fraction
 +        for f in [F(1, 2), F(0), F(5, 3), F(9, 7), F(35, 36), F(3, 7)]:
 +            self.do_exactly_equal_test(f, 0, 0)
 +
 +    def test_exactly_equal_decimals(self):
 +        # Test that equal Decimal values are exactly equal.
 +        D = Decimal
 +        for d in map(D, "8.2 31.274 912.04 16.745 1.2047".split()):
 +            self.do_exactly_equal_test(d, 0, 0)
 +
 +    def test_exactly_equal_absolute(self):
 +        # Test that equal values are exactly equal with an absolute error.
 +        for n in [16, 1013, 1372, 1198, 971, 4]:
 +            # Test as ints.
 +            self.do_exactly_equal_test(n, 0.01, 0)
 +            # Test as floats.
 +            self.do_exactly_equal_test(n/10, 0.01, 0)
 +            # Test as Fractions.
 +            f = Fraction(n, 1234)
 +            self.do_exactly_equal_test(f, 0.01, 0)
 +
 +    def test_exactly_equal_absolute_decimals(self):
 +        # Test equal Decimal values are exactly equal with an absolute error.
 +        self.do_exactly_equal_test(Decimal("3.571"), Decimal("0.01"), 0)
 +        self.do_exactly_equal_test(-Decimal("81.3971"), Decimal("0.01"), 0)
 +
 +    def test_exactly_equal_relative(self):
 +        # Test that equal values are exactly equal with a relative error.
 +        for x in [8347, 101.3, -7910.28, Fraction(5, 21)]:
 +            self.do_exactly_equal_test(x, 0, 0.01)
 +        self.do_exactly_equal_test(Decimal("11.68"), 0, Decimal("0.01"))
 +
 +    def test_exactly_equal_both(self):
 +        # Test that equal values are equal when both tol and rel are given.
 +        for x in [41017, 16.742, -813.02, Fraction(3, 8)]:
 +            self.do_exactly_equal_test(x, 0.1, 0.01)
 +        D = Decimal
 +        self.do_exactly_equal_test(D("7.2"), D("0.1"), D("0.01"))
 +
 +
 +class ApproxEqualUnequalTest(unittest.TestCase):
 +    # Unequal values should compare unequal with zero error tolerances.
 +    # Test cases for unequal values, with exact equality test.
 +
 +    def do_exactly_unequal_test(self, x):
 +        for a in (x, -x):
 +            result = approx_equal(a, a+1, tol=0, rel=0)
 +            self.assertFalse(result, 'inequality failure for x=%r' % a)
 +
 +    def test_exactly_unequal_ints(self):
 +        # Test unequal int values are unequal with zero error tolerance.
 +        for n in [951, 572305, 478, 917, 17240]:
 +            self.do_exactly_unequal_test(n)
 +
 +    def test_exactly_unequal_floats(self):
 +        # Test unequal float values are unequal with zero error tolerance.
 +        for x in [9.51, 5723.05, 47.8, 9.17, 17.24]:
 +            self.do_exactly_unequal_test(x)
 +
 +    def test_exactly_unequal_fractions(self):
 +        # Test that unequal Fractions are unequal with zero error tolerance.
 +        F = Fraction
 +        for f in [F(1, 5), F(7, 9), F(12, 11), F(101, 99023)]:
 +            self.do_exactly_unequal_test(f)
 +
 +    def test_exactly_unequal_decimals(self):
 +        # Test that unequal Decimals are unequal with zero error tolerance.
 +        for d in map(Decimal, "3.1415 298.12 3.47 18.996 0.00245".split()):
 +            self.do_exactly_unequal_test(d)
 +
 +
 +class ApproxEqualInexactTest(unittest.TestCase):
 +    # Inexact test cases for approx_error.
 +    # Test cases when comparing two values that are not exactly equal.
 +
 +    # === Absolute error tests ===
 +
 +    def do_approx_equal_abs_test(self, x, delta):
 +        template = "Test failure for x={!r}, y={!r}"
 +        for y in (x + delta, x - delta):
 +            msg = template.format(x, y)
 +            self.assertTrue(approx_equal(x, y, tol=2*delta, rel=0), msg)
 +            self.assertFalse(approx_equal(x, y, tol=delta/2, rel=0), msg)
 +
 +    def test_approx_equal_absolute_ints(self):
 +        # Test approximate equality of ints with an absolute error.
 +        for n in [-10737, -1975, -7, -2, 0, 1, 9, 37, 423, 9874, 23789110]:
 +            self.do_approx_equal_abs_test(n, 10)
 +            self.do_approx_equal_abs_test(n, 2)
 +
 +    def test_approx_equal_absolute_floats(self):
 +        # Test approximate equality of floats with an absolute error.
 +        for x in [-284.126, -97.1, -3.4, -2.15, 0.5, 1.0, 7.8, 4.23, 3817.4]:
 +            self.do_approx_equal_abs_test(x, 1.5)
 +            self.do_approx_equal_abs_test(x, 0.01)
 +            self.do_approx_equal_abs_test(x, 0.0001)
 +
 +    def test_approx_equal_absolute_fractions(self):
 +        # Test approximate equality of Fractions with an absolute error.
 +        delta = Fraction(1, 29)
 +        numerators = [-84, -15, -2, -1, 0, 1, 5, 17, 23, 34, 71]
 +        for f in (Fraction(n, 29) for n in numerators):
 +            self.do_approx_equal_abs_test(f, delta)
 +            self.do_approx_equal_abs_test(f, float(delta))
 +
 +    def test_approx_equal_absolute_decimals(self):
 +        # Test approximate equality of Decimals with an absolute error.
 +        delta = Decimal("0.01")
 +        for d in map(Decimal, "1.0 3.5 36.08 61.79 7912.3648".split()):
 +            self.do_approx_equal_abs_test(d, delta)
 +            self.do_approx_equal_abs_test(-d, delta)
 +
 +    def test_cross_zero(self):
 +        # Test for the case of the two values having opposite signs.
 +        self.assertTrue(approx_equal(1e-5, -1e-5, tol=1e-4, rel=0))
 +
 +    # === Relative error tests ===
 +
 +    def do_approx_equal_rel_test(self, x, delta):
 +        template = "Test failure for x={!r}, y={!r}"
 +        for y in (x*(1+delta), x*(1-delta)):
 +            msg = template.format(x, y)
 +            self.assertTrue(approx_equal(x, y, tol=0, rel=2*delta), msg)
 +            self.assertFalse(approx_equal(x, y, tol=0, rel=delta/2), msg)
 +
 +    def test_approx_equal_relative_ints(self):
 +        # Test approximate equality of ints with a relative error.
 +        self.assertTrue(approx_equal(64, 47, tol=0, rel=0.36))
 +        self.assertTrue(approx_equal(64, 47, tol=0, rel=0.37))
 +        # ---
 +        self.assertTrue(approx_equal(449, 512, tol=0, rel=0.125))
 +        self.assertTrue(approx_equal(448, 512, tol=0, rel=0.125))
 +        self.assertFalse(approx_equal(447, 512, tol=0, rel=0.125))
 +
 +    def test_approx_equal_relative_floats(self):
 +        # Test approximate equality of floats with a relative error.
 +        for x in [-178.34, -0.1, 0.1, 1.0, 36.97, 2847.136, 9145.074]:
 +            self.do_approx_equal_rel_test(x, 0.02)
 +            self.do_approx_equal_rel_test(x, 0.0001)
 +
 +    def test_approx_equal_relative_fractions(self):
 +        # Test approximate equality of Fractions with a relative error.
 +        F = Fraction
 +        delta = Fraction(3, 8)
 +        for f in [F(3, 84), F(17, 30), F(49, 50), F(92, 85)]:
 +            for d in (delta, float(delta)):
 +                self.do_approx_equal_rel_test(f, d)
 +                self.do_approx_equal_rel_test(-f, d)
 +
 +    def test_approx_equal_relative_decimals(self):
 +        # Test approximate equality of Decimals with a relative error.
 +        for d in map(Decimal, "0.02 1.0 5.7 13.67 94.138 91027.9321".split()):
 +            self.do_approx_equal_rel_test(d, Decimal("0.001"))
 +            self.do_approx_equal_rel_test(-d, Decimal("0.05"))
 +
 +    # === Both absolute and relative error tests ===
 +
 +    # There are four cases to consider:
 +    #   1) actual error <= both absolute and relative error
 +    #   2) actual error <= absolute error but > relative error
 +    #   3) actual error <= relative error but > absolute error
 +    #   4) actual error > both absolute and relative error
 +
 +    def do_check_both(self, a, b, tol, rel, tol_flag, rel_flag):
 +        check = self.assertTrue if tol_flag else self.assertFalse
 +        check(approx_equal(a, b, tol=tol, rel=0))
 +        check = self.assertTrue if rel_flag else self.assertFalse
 +        check(approx_equal(a, b, tol=0, rel=rel))
 +        check = self.assertTrue if (tol_flag or rel_flag) else self.assertFalse
 +        check(approx_equal(a, b, tol=tol, rel=rel))
 +
 +    def test_approx_equal_both1(self):
 +        # Test actual error <= both absolute and relative error.
 +        self.do_check_both(7.955, 7.952, 0.004, 3.8e-4, True, True)
 +        self.do_check_both(-7.387, -7.386, 0.002, 0.0002, True, True)
 +
 +    def test_approx_equal_both2(self):
 +        # Test actual error <= absolute error but > relative error.
 +        self.do_check_both(7.955, 7.952, 0.004, 3.7e-4, True, False)
 +
 +    def test_approx_equal_both3(self):
 +        # Test actual error <= relative error but > absolute error.
 +        self.do_check_both(7.955, 7.952, 0.001, 3.8e-4, False, True)
 +
 +    def test_approx_equal_both4(self):
 +        # Test actual error > both absolute and relative error.
 +        self.do_check_both(2.78, 2.75, 0.01, 0.001, False, False)
 +        self.do_check_both(971.44, 971.47, 0.02, 3e-5, False, False)
 +
 +
 +class ApproxEqualSpecialsTest(unittest.TestCase):
 +    # Test approx_equal with NANs and INFs and zeroes.
 +
 +    def test_inf(self):
 +        for type_ in (float, Decimal):
 +            inf = type_('inf')
 +            self.assertTrue(approx_equal(inf, inf))
 +            self.assertTrue(approx_equal(inf, inf, 0, 0))
 +            self.assertTrue(approx_equal(inf, inf, 1, 0.01))
 +            self.assertTrue(approx_equal(-inf, -inf))
 +            self.assertFalse(approx_equal(inf, -inf))
 +            self.assertFalse(approx_equal(inf, 1000))
 +
 +    def test_nan(self):
 +        for type_ in (float, Decimal):
 +            nan = type_('nan')
 +            for other in (nan, type_('inf'), 1000):
 +                self.assertFalse(approx_equal(nan, other))
 +
 +    def test_float_zeroes(self):
 +        nzero = math.copysign(0.0, -1)
 +        self.assertTrue(approx_equal(nzero, 0.0, tol=0.1, rel=0.1))
 +
 +    def test_decimal_zeroes(self):
 +        nzero = Decimal("-0.0")
 +        self.assertTrue(approx_equal(nzero, Decimal(0), tol=0.1, rel=0.1))
 +
 +
 +class TestApproxEqualErrors(unittest.TestCase):
 +    # Test error conditions of approx_equal.
 +
 +    def test_bad_tol(self):
 +        # Test negative tol raises.
 +        self.assertRaises(ValueError, approx_equal, 100, 100, -1, 0.1)
 +
 +    def test_bad_rel(self):
 +        # Test negative rel raises.
 +        self.assertRaises(ValueError, approx_equal, 100, 100, 1, -0.1)
 +
 +
 +# --- Tests for NumericTestCase ---
 +
 +# The formatting routine that generates the error messages is complex enough
 +# that it too needs testing.
 +
 +class TestNumericTestCase(unittest.TestCase):
 +    # The exact wording of NumericTestCase error messages is *not* guaranteed,
 +    # but we need to give them some sort of test to ensure that they are
 +    # generated correctly. As a compromise, we look for specific substrings
 +    # that are expected to be found even if the overall error message changes.
 +
 +    def do_test(self, args):
 +        actual_msg = NumericTestCase._make_std_err_msg(*args)
 +        expected = self.generate_substrings(*args)
 +        for substring in expected:
 +            self.assertIn(substring, actual_msg)
 +
 +    def test_numerictestcase_is_testcase(self):
 +        # Ensure that NumericTestCase actually is a TestCase.
 +        self.assertTrue(issubclass(NumericTestCase, unittest.TestCase))
 +
 +    def test_error_msg_numeric(self):
 +        # Test the error message generated for numeric comparisons.
 +        args = (2.5, 4.0, 0.5, 0.25, None)
 +        self.do_test(args)
 +
 +    def test_error_msg_sequence(self):
 +        # Test the error message generated for sequence comparisons.
 +        args = (3.75, 8.25, 1.25, 0.5, 7)
 +        self.do_test(args)
 +
 +    def generate_substrings(self, first, second, tol, rel, idx):
 +        """Return substrings we expect to see in error messages."""
 +        abs_err, rel_err = _calc_errors(first, second)
 +        substrings = [
 +                'tol=%r' % tol,
 +                'rel=%r' % rel,
 +                'absolute error = %r' % abs_err,
 +                'relative error = %r' % rel_err,
 +                ]
 +        if idx is not None:
 +            substrings.append('differ at index %d' % idx)
 +        return substrings
 +
 +
 +# =======================================
 +# === Tests for the statistics module ===
 +# =======================================
 +
 +
 +class GlobalsTest(unittest.TestCase):
 +    module = statistics
 +    expected_metadata = ["__doc__", "__all__"]
 +
 +    def test_meta(self):
 +        # Test for the existence of metadata.
 +        for meta in self.expected_metadata:
 +            self.assertTrue(hasattr(self.module, meta),
 +                            "%s not present" % meta)
 +
 +    def test_check_all(self):
 +        # Check everything in __all__ exists and is public.
 +        module = self.module
 +        for name in module.__all__:
 +            # No private names in __all__:
 +            self.assertFalse(name.startswith("_"),
 +                             'private name "%s" in __all__' % name)
 +            # And anything in __all__ must exist:
 +            self.assertTrue(hasattr(module, name),
 +                            'missing name "%s" in __all__' % name)
 +
 +
 +class DocTests(unittest.TestCase):
++    @unittest.skipIf(sys.flags.optimize >= 2,
++                     "Docstrings are omitted with -OO and above")
 +    def test_doc_tests(self):
 +        failed, tried = doctest.testmod(statistics)
 +        self.assertGreater(tried, 0)
 +        self.assertEqual(failed, 0)
 +
 +class StatisticsErrorTest(unittest.TestCase):
 +    def test_has_exception(self):
 +        errmsg = (
 +                "Expected StatisticsError to be a ValueError, but got a"
 +                " subclass of %r instead."
 +                )
 +        self.assertTrue(hasattr(statistics, 'StatisticsError'))
 +        self.assertTrue(
 +                issubclass(statistics.StatisticsError, ValueError),
 +                errmsg % statistics.StatisticsError.__base__
 +                )
 +
 +
 +# === Tests for private utility functions ===
 +
 +class ExactRatioTest(unittest.TestCase):
 +    # Test _exact_ratio utility.
 +
 +    def test_int(self):
 +        for i in (-20, -3, 0, 5, 99, 10**20):
 +            self.assertEqual(statistics._exact_ratio(i), (i, 1))
 +
 +    def test_fraction(self):
 +        numerators = (-5, 1, 12, 38)
 +        for n in numerators:
 +            f = Fraction(n, 37)
 +            self.assertEqual(statistics._exact_ratio(f), (n, 37))
 +
 +    def test_float(self):
 +        self.assertEqual(statistics._exact_ratio(0.125), (1, 8))
 +        self.assertEqual(statistics._exact_ratio(1.125), (9, 8))
 +        data = [random.uniform(-100, 100) for _ in range(100)]
 +        for x in data:
 +            num, den = statistics._exact_ratio(x)
 +            self.assertEqual(x, num/den)
 +
 +    def test_decimal(self):
 +        D = Decimal
 +        _exact_ratio = statistics._exact_ratio
 +        self.assertEqual(_exact_ratio(D("0.125")), (125, 1000))
 +        self.assertEqual(_exact_ratio(D("12.345")), (12345, 1000))
 +        self.assertEqual(_exact_ratio(D("-1.98")), (-198, 100))
 +
 +
 +class DecimalToRatioTest(unittest.TestCase):
 +    # Test _decimal_to_ratio private function.
 +
 +    def testSpecialsRaise(self):
 +        # Test that NANs and INFs raise ValueError.
 +        # Non-special values are covered by _exact_ratio above.
 +        for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')):
 +            self.assertRaises(ValueError, statistics._decimal_to_ratio, d)
 +
 +
 +
 +# === Tests for public functions ===
 +
 +class UnivariateCommonMixin:
 +    # Common tests for most univariate functions that take a data argument.
 +
 +    def test_no_args(self):
 +        # Fail if given no arguments.
 +        self.assertRaises(TypeError, self.func)
 +
 +    def test_empty_data(self):
 +        # Fail when the data argument (first argument) is empty.
 +        for empty in ([], (), iter([])):
 +            self.assertRaises(statistics.StatisticsError, self.func, empty)
 +
 +    def prepare_data(self):
 +        """Return int data for various tests."""
 +        data = list(range(10))
 +        while data == sorted(data):
 +            random.shuffle(data)
 +        return data
 +
 +    def test_no_inplace_modifications(self):
 +        # Test that the function does not modify its input data.
 +        data = self.prepare_data()
 +        assert len(data) != 1  # Necessary to avoid infinite loop.
 +        assert data != sorted(data)
 +        saved = data[:]
 +        assert data is not saved
 +        _ = self.func(data)
 +        self.assertListEqual(data, saved, "data has been modified")
 +
 +    def test_order_doesnt_matter(self):
 +        # Test that the order of data points doesn't change the result.
 +
 +        # CAUTION: due to floating point rounding errors, the result actually
 +        # may depend on the order. Consider this test representing an ideal.
 +        # To avoid this test failing, only test with exact values such as ints
 +        # or Fractions.
 +        data = [1, 2, 3, 3, 3, 4, 5, 6]*100
 +        expected = self.func(data)
 +        random.shuffle(data)
 +        actual = self.func(data)
 +        self.assertEqual(expected, actual)
 +
 +    def test_type_of_data_collection(self):
 +        # Test that the type of iterable data doesn't effect the result.
 +        class MyList(list):
 +            pass
 +        class MyTuple(tuple):
 +            pass
 +        def generator(data):
 +            return (obj for obj in data)
 +        data = self.prepare_data()
 +        expected = self.func(data)
 +        for kind in (list, tuple, iter, MyList, MyTuple, generator):
 +            result = self.func(kind(data))
 +            self.assertEqual(result, expected)
 +
 +    def test_range_data(self):
 +        # Test that functions work with range objects.
 +        data = range(20, 50, 3)
 +        expected = self.func(list(data))
 +        self.assertEqual(self.func(data), expected)
 +
 +    def test_bad_arg_types(self):
 +        # Test that function raises when given data of the wrong type.
 +
 +        # Don't roll the following into a loop like this:
 +        #   for bad in list_of_bad:
 +        #       self.check_for_type_error(bad)
 +        #
 +        # Since assertRaises doesn't show the arguments that caused the test
 +        # failure, it is very difficult to debug these test failures when the
 +        # following are in a loop.
 +        self.check_for_type_error(None)
 +        self.check_for_type_error(23)
 +        self.check_for_type_error(42.0)
 +        self.check_for_type_error(object())
 +
 +    def check_for_type_error(self, *args):
 +        self.assertRaises(TypeError, self.func, *args)
 +
 +    def test_type_of_data_element(self):
 +        # Check the type of data elements doesn't affect the numeric result.
 +        # This is a weaker test than UnivariateTypeMixin.testTypesConserved,
 +        # because it checks the numeric result by equality, but not by type.
 +        class MyFloat(float):
 +            def __truediv__(self, other):
 +                return type(self)(super().__truediv__(other))
 +            def __add__(self, other):
 +                return type(self)(super().__add__(other))
 +            __radd__ = __add__
 +
 +        raw = self.prepare_data()
 +        expected = self.func(raw)
 +        for kind in (float, MyFloat, Decimal, Fraction):
 +            data = [kind(x) for x in raw]
 +            result = type(expected)(self.func(data))
 +            self.assertEqual(result, expected)
 +
 +
 +class UnivariateTypeMixin:
 +    """Mixin class for type-conserving functions.
 +
 +    This mixin class holds test(s) for functions which conserve the type of
 +    individual data points. E.g. the mean of a list of Fractions should itself
 +    be a Fraction.
 +
 +    Not all tests to do with types need go in this class. Only those that
 +    rely on the function returning the same type as its input data.
 +    """
 +    def test_types_conserved(self):
 +        # Test that functions keeps the same type as their data points.
 +        # (Excludes mixed data types.) This only tests the type of the return
 +        # result, not the value.
 +        class MyFloat(float):
 +            def __truediv__(self, other):
 +                return type(self)(super().__truediv__(other))
 +            def __sub__(self, other):
 +                return type(self)(super().__sub__(other))
 +            def __rsub__(self, other):
 +                return type(self)(super().__rsub__(other))
 +            def __pow__(self, other):
 +                return type(self)(super().__pow__(other))
 +            def __add__(self, other):
 +                return type(self)(super().__add__(other))
 +            __radd__ = __add__
 +
 +        data = self.prepare_data()
 +        for kind in (float, Decimal, Fraction, MyFloat):
 +            d = [kind(x) for x in data]
 +            result = self.func(d)
 +            self.assertIs(type(result), kind)
 +
 +
 +class TestSum(NumericTestCase, UnivariateCommonMixin, UnivariateTypeMixin):
 +    # Test cases for statistics._sum() function.
 +
 +    def setUp(self):
 +        self.func = statistics._sum
 +
 +    def test_empty_data(self):
 +        # Override test for empty data.
 +        for data in ([], (), iter([])):
 +            self.assertEqual(self.func(data), 0)
 +            self.assertEqual(self.func(data, 23), 23)
 +            self.assertEqual(self.func(data, 2.3), 2.3)
 +
 +    def test_ints(self):
 +        self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]), 60)
 +        self.assertEqual(self.func([4, 2, 3, -8, 7], 1000), 1008)
 +
 +    def test_floats(self):
 +        self.assertEqual(self.func([0.25]*20), 5.0)
 +        self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5), 3.125)
 +
 +    def test_fractions(self):
 +        F = Fraction
 +        self.assertEqual(self.func([Fraction(1, 1000)]*500), Fraction(1, 2))
 +
 +    def test_decimals(self):
 +        D = Decimal
 +        data = [D("0.001"), D("5.246"), D("1.702"), D("-0.025"),
 +                D("3.974"), D("2.328"), D("4.617"), D("2.843"),
 +                ]
 +        self.assertEqual(self.func(data), Decimal("20.686"))
 +
 +    def test_compare_with_math_fsum(self):
 +        # Compare with the math.fsum function.
 +        # Ideally we ought to get the exact same result, but sometimes
 +        # we differ by a very slight amount :-(
 +        data = [random.uniform(-100, 1000) for _ in range(1000)]
 +        self.assertApproxEqual(self.func(data), math.fsum(data), rel=2e-16)
 +
 +    def test_start_argument(self):
 +        # Test that the optional start argument works correctly.
 +        data = [random.uniform(1, 1000) for _ in range(100)]
 +        t = self.func(data)
 +        self.assertEqual(t+42, self.func(data, 42))
 +        self.assertEqual(t-23, self.func(data, -23))
 +        self.assertEqual(t+1e20, self.func(data, 1e20))
 +
 +    def test_strings_fail(self):
 +        # Sum of strings should fail.
 +        self.assertRaises(TypeError, self.func, [1, 2, 3], '999')
 +        self.assertRaises(TypeError, self.func, [1, 2, 3, '999'])
 +
 +    def test_bytes_fail(self):
 +        # Sum of bytes should fail.
 +        self.assertRaises(TypeError, self.func, [1, 2, 3], b'999')
 +        self.assertRaises(TypeError, self.func, [1, 2, 3, b'999'])
 +
 +    def test_mixed_sum(self):
 +        # Mixed sums are allowed.
 +
 +        # Careful here: order matters. Can't mix Fraction and Decimal directly,
 +        # only after they're converted to float.
 +        data = [1, 2, Fraction(1, 2), 3.0, Decimal("0.25")]
 +        self.assertEqual(self.func(data), 6.75)
 +
 +
 +class SumInternalsTest(NumericTestCase):
 +    # Test internals of the sum function.
 +
 +    def test_ignore_instance_float_method(self):
 +        # Test that __float__ methods on data instances are ignored.
 +
 +        # Python typically calls __dunder__ methods on the class, not the
 +        # instance. The ``sum`` implementation calls __float__ directly. To
 +        # better match the behaviour of Python, we call it only on the class,
 +        # not the instance. This test will fail if somebody "fixes" that code.
 +
 +        # Create a fake __float__ method.
 +        def __float__(self):
 +            raise AssertionError('test fails')
 +
 +        # Inject it into an instance.
 +        class MyNumber(Fraction):
 +            pass
 +        x = MyNumber(3)
 +        x.__float__ = types.MethodType(__float__, x)
 +
 +        # Check it works as expected.
 +        self.assertRaises(AssertionError, x.__float__)
 +        self.assertEqual(float(x), 3.0)
 +        # And now test the function.
 +        self.assertEqual(statistics._sum([1.0, 2.0, x, 4.0]), 10.0)
 +
 +
 +class SumTortureTest(NumericTestCase):
 +    def test_torture(self):
 +        # Tim Peters' torture test for sum, and variants of same.
 +        self.assertEqual(statistics._sum([1, 1e100, 1, -1e100]*10000), 20000.0)
 +        self.assertEqual(statistics._sum([1e100, 1, 1, -1e100]*10000), 20000.0)
 +        self.assertApproxEqual(
 +            statistics._sum([1e-100, 1, 1e-100, -1]*10000), 2.0e-96, rel=5e-16
 +            )
 +
 +
 +class SumSpecialValues(NumericTestCase):
 +    # Test that sum works correctly with IEEE-754 special values.
 +
 +    def test_nan(self):
 +        for type_ in (float, Decimal):
 +            nan = type_('nan')
 +            result = statistics._sum([1, nan, 2])
 +            self.assertIs(type(result), type_)
 +            self.assertTrue(math.isnan(result))
 +
 +    def check_infinity(self, x, inf):
 +        """Check x is an infinity of the same type and sign as inf."""
 +        self.assertTrue(math.isinf(x))
 +        self.assertIs(type(x), type(inf))
 +        self.assertEqual(x > 0, inf > 0)
 +        assert x == inf
 +
 +    def do_test_inf(self, inf):
 +        # Adding a single infinity gives infinity.
 +        result = statistics._sum([1, 2, inf, 3])
 +        self.check_infinity(result, inf)
 +        # Adding two infinities of the same sign also gives infinity.
 +        result = statistics._sum([1, 2, inf, 3, inf, 4])
 +        self.check_infinity(result, inf)
 +
 +    def test_float_inf(self):
 +        inf = float('inf')
 +        for sign in (+1, -1):
 +            self.do_test_inf(sign*inf)
 +
 +    def test_decimal_inf(self):
 +        inf = Decimal('inf')
 +        for sign in (+1, -1):
 +            self.do_test_inf(sign*inf)
 +
 +    def test_float_mismatched_infs(self):
 +        # Test that adding two infinities of opposite sign gives a NAN.
 +        inf = float('inf')
 +        result = statistics._sum([1, 2, inf, 3, -inf, 4])
 +        self.assertTrue(math.isnan(result))
 +
 +    def test_decimal_mismatched_infs_to_nan(self):
 +        # Test adding Decimal INFs with opposite sign returns NAN.
 +        inf = Decimal('inf')
 +        data = [1, 2, inf, 3, -inf, 4]
 +        with decimal.localcontext(decimal.ExtendedContext):
 +            self.assertTrue(math.isnan(statistics._sum(data)))
 +
 +    def test_decimal_mismatched_infs_to_nan(self):
 +        # Test adding Decimal INFs with opposite sign raises InvalidOperation.
 +        inf = Decimal('inf')
 +        data = [1, 2, inf, 3, -inf, 4]
 +        with decimal.localcontext(decimal.BasicContext):
 +            self.assertRaises(decimal.InvalidOperation, statistics._sum, data)
 +
 +    def test_decimal_snan_raises(self):
 +        # Adding sNAN should raise InvalidOperation.
 +        sNAN = Decimal('sNAN')
 +        data = [1, sNAN, 2]
 +        self.assertRaises(decimal.InvalidOperation, statistics._sum, data)
 +
 +
 +# === Tests for averages ===
 +
 +class AverageMixin(UnivariateCommonMixin):
 +    # Mixin class holding common tests for averages.
 +
 +    def test_single_value(self):
 +        # Average of a single value is the value itself.
 +        for x in (23, 42.5, 1.3e15, Fraction(15, 19), Decimal('0.28')):
 +            self.assertEqual(self.func([x]), x)
 +
 +    def test_repeated_single_value(self):
 +        # The average of a single repeated value is the value itself.
 +        for x in (3.5, 17, 2.5e15, Fraction(61, 67), Decimal('4.9712')):
 +            for count in (2, 5, 10, 20):
 +                data = [x]*count
 +                self.assertEqual(self.func(data), x)
 +
 +
 +class TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin):
 +    def setUp(self):
 +        self.func = statistics.mean
 +
 +    def test_torture_pep(self):
 +        # "Torture Test" from PEP-450.
 +        self.assertEqual(self.func([1e100, 1, 3, -1e100]), 1)
 +
 +    def test_ints(self):
 +        # Test mean with ints.
 +        data = [0, 1, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7, 7, 8, 9]
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 4.8125)
 +
 +    def test_floats(self):
 +        # Test mean with floats.
 +        data = [17.25, 19.75, 20.0, 21.5, 21.75, 23.25, 25.125, 27.5]
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 22.015625)
 +
 +    def test_decimals(self):
 +        # Test mean with ints.
 +        D = Decimal
 +        data = [D("1.634"), D("2.517"), D("3.912"), D("4.072"), D("5.813")]
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), D("3.5896"))
 +
 +    def test_fractions(self):
 +        # Test mean with Fractions.
 +        F = Fraction
 +        data = [F(1, 2), F(2, 3), F(3, 4), F(4, 5), F(5, 6), F(6, 7), F(7, 8)]
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), F(1479, 1960))
 +
 +    def test_inf(self):
 +        # Test mean with infinities.
 +        raw = [1, 3, 5, 7, 9]  # Use only ints, to avoid TypeError later.
 +        for kind in (float, Decimal):
 +            for sign in (1, -1):
 +                inf = kind("inf")*sign
 +                data = raw + [inf]
 +                result = self.func(data)
 +                self.assertTrue(math.isinf(result))
 +                self.assertEqual(result, inf)
 +
 +    def test_mismatched_infs(self):
 +        # Test mean with infinities of opposite sign.
 +        data = [2, 4, 6, float('inf'), 1, 3, 5, float('-inf')]
 +        result = self.func(data)
 +        self.assertTrue(math.isnan(result))
 +
 +    def test_nan(self):
 +        # Test mean with NANs.
 +        raw = [1, 3, 5, 7, 9]  # Use only ints, to avoid TypeError later.
 +        for kind in (float, Decimal):
 +            inf = kind("nan")
 +            data = raw + [inf]
 +            result = self.func(data)
 +            self.assertTrue(math.isnan(result))
 +
 +    def test_big_data(self):
 +        # Test adding a large constant to every data point.
 +        c = 1e9
 +        data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4]
 +        expected = self.func(data) + c
 +        assert expected != c
 +        result = self.func([x+c for x in data])
 +        self.assertEqual(result, expected)
 +
 +    def test_doubled_data(self):
 +        # Mean of [a,b,c...z] should be same as for [a,a,b,b,c,c...z,z].
 +        data = [random.uniform(-3, 5) for _ in range(1000)]
 +        expected = self.func(data)
 +        actual = self.func(data*2)
 +        self.assertApproxEqual(actual, expected)
 +
 +
 +class TestMedian(NumericTestCase, AverageMixin):
 +    # Common tests for median and all median.* functions.
 +    def setUp(self):
 +        self.func = statistics.median
 +
 +    def prepare_data(self):
 +        """Overload method from UnivariateCommonMixin."""
 +        data = super().prepare_data()
 +        if len(data)%2 != 1:
 +            data.append(2)
 +        return data
 +
 +    def test_even_ints(self):
 +        # Test median with an even number of int data points.
 +        data = [1, 2, 3, 4, 5, 6]
 +        assert len(data)%2 == 0
 +        self.assertEqual(self.func(data), 3.5)
 +
 +    def test_odd_ints(self):
 +        # Test median with an odd number of int data points.
 +        data = [1, 2, 3, 4, 5, 6, 9]
 +        assert len(data)%2 == 1
 +        self.assertEqual(self.func(data), 4)
 +
 +    def test_odd_fractions(self):
 +        # Test median works with an odd number of Fractions.
 +        F = Fraction
 +        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7)]
 +        assert len(data)%2 == 1
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), F(3, 7))
 +
 +    def test_even_fractions(self):
 +        # Test median works with an even number of Fractions.
 +        F = Fraction
 +        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), F(1, 2))
 +
 +    def test_odd_decimals(self):
 +        # Test median works with an odd number of Decimals.
 +        D = Decimal
 +        data = [D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')]
 +        assert len(data)%2 == 1
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), D('4.2'))
 +
 +    def test_even_decimals(self):
 +        # Test median works with an even number of Decimals.
 +        D = Decimal
 +        data = [D('1.2'), D('2.5'), D('3.1'), D('4.2'), D('5.7'), D('5.8')]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), D('3.65'))
 +
 +
 +class TestMedianDataType(NumericTestCase, UnivariateTypeMixin):
 +    # Test conservation of data element type for median.
 +    def setUp(self):
 +        self.func = statistics.median
 +
 +    def prepare_data(self):
 +        data = list(range(15))
 +        assert len(data)%2 == 1
 +        while data == sorted(data):
 +            random.shuffle(data)
 +        return data
 +
 +
 +class TestMedianLow(TestMedian, UnivariateTypeMixin):
 +    def setUp(self):
 +        self.func = statistics.median_low
 +
 +    def test_even_ints(self):
 +        # Test median_low with an even number of ints.
 +        data = [1, 2, 3, 4, 5, 6]
 +        assert len(data)%2 == 0
 +        self.assertEqual(self.func(data), 3)
 +
 +    def test_even_fractions(self):
 +        # Test median_low works with an even number of Fractions.
 +        F = Fraction
 +        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), F(3, 7))
 +
 +    def test_even_decimals(self):
 +        # Test median_low works with an even number of Decimals.
 +        D = Decimal
 +        data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), D('3.3'))
 +
 +
 +class TestMedianHigh(TestMedian, UnivariateTypeMixin):
 +    def setUp(self):
 +        self.func = statistics.median_high
 +
 +    def test_even_ints(self):
 +        # Test median_high with an even number of ints.
 +        data = [1, 2, 3, 4, 5, 6]
 +        assert len(data)%2 == 0
 +        self.assertEqual(self.func(data), 4)
 +
 +    def test_even_fractions(self):
 +        # Test median_high works with an even number of Fractions.
 +        F = Fraction
 +        data = [F(1, 7), F(2, 7), F(3, 7), F(4, 7), F(5, 7), F(6, 7)]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), F(4, 7))
 +
 +    def test_even_decimals(self):
 +        # Test median_high works with an even number of Decimals.
 +        D = Decimal
 +        data = [D('1.1'), D('2.2'), D('3.3'), D('4.4'), D('5.5'), D('6.6')]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), D('4.4'))
 +
 +
 +class TestMedianGrouped(TestMedian):
 +    # Test median_grouped.
 +    # Doesn't conserve data element types, so don't use TestMedianType.
 +    def setUp(self):
 +        self.func = statistics.median_grouped
 +
 +    def test_odd_number_repeated(self):
 +        # Test median.grouped with repeated median values.
 +        data = [12, 13, 14, 14, 14, 15, 15]
 +        assert len(data)%2 == 1
 +        self.assertEqual(self.func(data), 14)
 +        #---
 +        data = [12, 13, 14, 14, 14, 14, 15]
 +        assert len(data)%2 == 1
 +        self.assertEqual(self.func(data), 13.875)
 +        #---
 +        data = [5, 10, 10, 15, 20, 20, 20, 20, 25, 25, 30]
 +        assert len(data)%2 == 1
 +        self.assertEqual(self.func(data, 5), 19.375)
 +        #---
 +        data = [16, 18, 18, 18, 18, 20, 20, 20, 22, 22, 22, 24, 24, 26, 28]
 +        assert len(data)%2 == 1
 +        self.assertApproxEqual(self.func(data, 2), 20.66666667, tol=1e-8)
 +
 +    def test_even_number_repeated(self):
 +        # Test median.grouped with repeated median values.
 +        data = [5, 10, 10, 15, 20, 20, 20, 25, 25, 30]
 +        assert len(data)%2 == 0
 +        self.assertApproxEqual(self.func(data, 5), 19.16666667, tol=1e-8)
 +        #---
 +        data = [2, 3, 4, 4, 4, 5]
 +        assert len(data)%2 == 0
 +        self.assertApproxEqual(self.func(data), 3.83333333, tol=1e-8)
 +        #---
 +        data = [2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6]
 +        assert len(data)%2 == 0
 +        self.assertEqual(self.func(data), 4.5)
 +        #---
 +        data = [3, 4, 4, 4, 5, 5, 5, 5, 6, 6]
 +        assert len(data)%2 == 0
 +        self.assertEqual(self.func(data), 4.75)
 +
 +    def test_repeated_single_value(self):
 +        # Override method from AverageMixin.
 +        # Yet again, failure of median_grouped to conserve the data type
 +        # causes me headaches :-(
 +        for x in (5.3, 68, 4.3e17, Fraction(29, 101), Decimal('32.9714')):
 +            for count in (2, 5, 10, 20):
 +                data = [x]*count
 +                self.assertEqual(self.func(data), float(x))
 +
 +    def test_odd_fractions(self):
 +        # Test median_grouped works with an odd number of Fractions.
 +        F = Fraction
 +        data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4)]
 +        assert len(data)%2 == 1
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 3.0)
 +
 +    def test_even_fractions(self):
 +        # Test median_grouped works with an even number of Fractions.
 +        F = Fraction
 +        data = [F(5, 4), F(9, 4), F(13, 4), F(13, 4), F(17, 4), F(17, 4)]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 3.25)
 +
 +    def test_odd_decimals(self):
 +        # Test median_grouped works with an odd number of Decimals.
 +        D = Decimal
 +        data = [D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')]
 +        assert len(data)%2 == 1
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 6.75)
 +
 +    def test_even_decimals(self):
 +        # Test median_grouped works with an even number of Decimals.
 +        D = Decimal
 +        data = [D('5.5'), D('5.5'), D('6.5'), D('6.5'), D('7.5'), D('8.5')]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 6.5)
 +        #---
 +        data = [D('5.5'), D('5.5'), D('6.5'), D('7.5'), D('7.5'), D('8.5')]
 +        assert len(data)%2 == 0
 +        random.shuffle(data)
 +        self.assertEqual(self.func(data), 7.0)
 +
 +    def test_interval(self):
 +        # Test median_grouped with interval argument.
 +        data = [2.25, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75]
 +        self.assertEqual(self.func(data, 0.25), 2.875)
 +        data = [2.25, 2.5, 2.5, 2.75, 2.75, 2.75, 3.0, 3.0, 3.25, 3.5, 3.75]
 +        self.assertApproxEqual(self.func(data, 0.25), 2.83333333, tol=1e-8)
 +        data = [220, 220, 240, 260, 260, 260, 260, 280, 280, 300, 320, 340]
 +        self.assertEqual(self.func(data, 20), 265.0)
 +
 +
 +class TestMode(NumericTestCase, AverageMixin, UnivariateTypeMixin):
 +    # Test cases for the discrete version of mode.
 +    def setUp(self):
 +        self.func = statistics.mode
 +
 +    def prepare_data(self):
 +        """Overload method from UnivariateCommonMixin."""
 +        # Make sure test data has exactly one mode.
 +        return [1, 1, 1, 1, 3, 4, 7, 9, 0, 8, 2]
 +
 +    def test_range_data(self):
 +        # Override test from UnivariateCommonMixin.
 +        data = range(20, 50, 3)
 +        self.assertRaises(statistics.StatisticsError, self.func, data)
 +
 +    def test_nominal_data(self):
 +        # Test mode with nominal data.
 +        data = 'abcbdb'
 +        self.assertEqual(self.func(data), 'b')
 +        data = 'fe fi fo fum fi fi'.split()
 +        self.assertEqual(self.func(data), 'fi')
 +
 +    def test_discrete_data(self):
 +        # Test mode with discrete numeric data.
 +        data = list(range(10))
 +        for i in range(10):
 +            d = data + [i]
 +            random.shuffle(d)
 +            self.assertEqual(self.func(d), i)
 +
 +    def test_bimodal_data(self):
 +        # Test mode with bimodal data.
 +        data = [1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9, 9]
 +        assert data.count(2) == data.count(6) == 4
 +        # Check for an exception.
 +        self.assertRaises(statistics.StatisticsError, self.func, data)
 +
 +    def test_unique_data_failure(self):
 +        # Test mode exception when data points are all unique.
 +        data = list(range(10))
 +        self.assertRaises(statistics.StatisticsError, self.func, data)
 +
 +    def test_none_data(self):
 +        # Test that mode raises TypeError if given None as data.
 +
 +        # This test is necessary because the implementation of mode uses
 +        # collections.Counter, which accepts None and returns an empty dict.
 +        self.assertRaises(TypeError, self.func, None)
 +
 +
 +# === Tests for variances and standard deviations ===
 +
 +class VarianceStdevMixin(UnivariateCommonMixin):
 +    # Mixin class holding common tests for variance and std dev.
 +
 +    # Subclasses should inherit from this before NumericTestClass, in order
 +    # to see the rel attribute below. See testShiftData for an explanation.
 +
 +    rel = 1e-12
 +
 +    def test_single_value(self):
 +        # Deviation of a single value is zero.
 +        for x in (11, 19.8, 4.6e14, Fraction(21, 34), Decimal('8.392')):
 +            self.assertEqual(self.func([x]), 0)
 +
 +    def test_repeated_single_value(self):
 +        # The deviation of a single repeated value is zero.
 +        for x in (7.2, 49, 8.1e15, Fraction(3, 7), Decimal('62.4802')):
 +            for count in (2, 3, 5, 15):
 +                data = [x]*count
 +                self.assertEqual(self.func(data), 0)
 +
 +    def test_domain_error_regression(self):
 +        # Regression test for a domain error exception.
 +        # (Thanks to Geremy Condra.)
 +        data = [0.123456789012345]*10000
 +        # All the items are identical, so variance should be exactly zero.
 +        # We allow some small round-off error, but not much.
 +        result = self.func(data)
 +        self.assertApproxEqual(result, 0.0, tol=5e-17)
 +        self.assertGreaterEqual(result, 0)  # A negative result must fail.
 +
 +    def test_shift_data(self):
 +        # Test that shifting the data by a constant amount does not affect
 +        # the variance or stdev. Or at least not much.
 +
 +        # Due to rounding, this test should be considered an ideal. We allow
 +        # some tolerance away from "no change at all" by setting tol and/or rel
 +        # attributes. Subclasses may set tighter or looser error tolerances.
 +        raw = [1.03, 1.27, 1.94, 2.04, 2.58, 3.14, 4.75, 4.98, 5.42, 6.78]
 +        expected = self.func(raw)
 +        # Don't set shift too high, the bigger it is, the more rounding error.
 +        shift = 1e5
 +        data = [x + shift for x in raw]
 +        self.assertApproxEqual(self.func(data), expected)
 +
 +    def test_shift_data_exact(self):
 +        # Like test_shift_data, but result is always exact.
 +        raw = [1, 3, 3, 4, 5, 7, 9, 10, 11, 16]
 +        assert all(x==int(x) for x in raw)
 +        expected = self.func(raw)
 +        shift = 10**9
 +        data = [x + shift for x in raw]
 +        self.assertEqual(self.func(data), expected)
 +
 +    def test_iter_list_same(self):
 +        # Test that iter data and list data give the same result.
 +
 +        # This is an explicit test that iterators and lists are treated the
 +        # same; justification for this test over and above the similar test
 +        # in UnivariateCommonMixin is that an earlier design had variance and
 +        # friends swap between one- and two-pass algorithms, which would
 +        # sometimes give different results.
 +        data = [random.uniform(-3, 8) for _ in range(1000)]
 +        expected = self.func(data)
 +        self.assertEqual(self.func(iter(data)), expected)
 +
 +
 +class TestPVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin):
 +    # Tests for population variance.
 +    def setUp(self):
 +        self.func = statistics.pvariance
 +
 +    def test_exact_uniform(self):
 +        # Test the variance against an exact result for uniform data.
 +        data = list(range(10000))
 +        random.shuffle(data)
 +        expected = (10000**2 - 1)/12  # Exact value.
 +        self.assertEqual(self.func(data), expected)
 +
 +    def test_ints(self):
 +        # Test population variance with int data.
 +        data = [4, 7, 13, 16]
 +        exact = 22.5
 +        self.assertEqual(self.func(data), exact)
 +
 +    def test_fractions(self):
 +        # Test population variance with Fraction data.
 +        F = Fraction
 +        data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)]
 +        exact = F(3, 8)
 +        result = self.func(data)
 +        self.assertEqual(result, exact)
 +        self.assertIsInstance(result, Fraction)
 +
 +    def test_decimals(self):
 +        # Test population variance with Decimal data.
 +        D = Decimal
 +        data = [D("12.1"), D("12.2"), D("12.5"), D("12.9")]
 +        exact = D('0.096875')
 +        result = self.func(data)
 +        self.assertEqual(result, exact)
 +        self.assertIsInstance(result, Decimal)
 +
 +
 +class TestVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin):
 +    # Tests for sample variance.
 +    def setUp(self):
 +        self.func = statistics.variance
 +
 +    def test_single_value(self):
 +        # Override method from VarianceStdevMixin.
 +        for x in (35, 24.7, 8.2e15, Fraction(19, 30), Decimal('4.2084')):
 +            self.assertRaises(statistics.StatisticsError, self.func, [x])
 +
 +    def test_ints(self):
 +        # Test sample variance with int data.
 +        data = [4, 7, 13, 16]
 +        exact = 30
 +        self.assertEqual(self.func(data), exact)
 +
 +    def test_fractions(self):
 +        # Test sample variance with Fraction data.
 +        F = Fraction
 +        data = [F(1, 4), F(1, 4), F(3, 4), F(7, 4)]
 +        exact = F(1, 2)
 +        result = self.func(data)
 +        self.assertEqual(result, exact)
 +        self.assertIsInstance(result, Fraction)
 +
 +    def test_decimals(self):
 +        # Test sample variance with Decimal data.
 +        D = Decimal
 +        data = [D(2), D(2), D(7), D(9)]
 +        exact = 4*D('9.5')/D(3)
 +        result = self.func(data)
 +        self.assertEqual(result, exact)
 +        self.assertIsInstance(result, Decimal)
 +
 +
 +class TestPStdev(VarianceStdevMixin, NumericTestCase):
 +    # Tests for population standard deviation.
 +    def setUp(self):
 +        self.func = statistics.pstdev
 +
 +    def test_compare_to_variance(self):
 +        # Test that stdev is, in fact, the square root of variance.
 +        data = [random.uniform(-17, 24) for _ in range(1000)]
 +        expected = math.sqrt(statistics.pvariance(data))
 +        self.assertEqual(self.func(data), expected)
 +
 +
 +class TestStdev(VarianceStdevMixin, NumericTestCase):
 +    # Tests for sample standard deviation.
 +    def setUp(self):
 +        self.func = statistics.stdev
 +
 +    def test_single_value(self):
 +        # Override method from VarianceStdevMixin.
 +        for x in (81, 203.74, 3.9e14, Fraction(5, 21), Decimal('35.719')):
 +            self.assertRaises(statistics.StatisticsError, self.func, [x])
 +
 +    def test_compare_to_variance(self):
 +        # Test that stdev is, in fact, the square root of variance.
 +        data = [random.uniform(-2, 9) for _ in range(1000)]
 +        expected = math.sqrt(statistics.variance(data))
 +        self.assertEqual(self.func(data), expected)
 +
 +
 +# === Run tests ===
 +
 +def load_tests(loader, tests, ignore):
 +    """Used for doctest/unittest integration."""
 +    tests.addTests(doctest.DocTestSuite())
 +    return tests
 +
 +
 +if __name__ == "__main__":
 +    unittest.main()
diff --cc Misc/NEWS
index 8e758cbf282c8c445427d314925b9cddab36ca9f,0eac7fb2ad74e290080ab6223847673fd0224720..633ef5040ea315cd7cbc9f1785807c3527eba331
+++ b/Misc/NEWS
@@@ -112,6 -56,49 +112,9 @@@ Librar
  Tests
  -----
  
 -- Issue #19535: Fixed test_docxmlrpc when python is run with -OO.
++- Issue #19535: Fixed test_docxmlrpc, test_functools, test_inspect, and
++  test_statistics when python is run with -OO.
  - Issue #19926: Removed unneeded test_main from test_abstract_numbers.
    Patch by Vajrasky Kok.