mirror of
https://github.com/python/cpython.git
synced 2025-11-17 01:25:57 +00:00
Backport PEP 3141 from the py3k branch to the trunk. This includes r50877 (just
the complex_pow part), r56649, r56652, r56715, r57296, r57302, r57359, r57361, r57372, r57738, r57739, r58017, r58039, r58040, and r59390, and new documentation. The only significant difference is that round(x) returns a float to preserve backward-compatibility. See http://bugs.python.org/issue1689.
This commit is contained in:
parent
27edd829d7
commit
2f3c16be73
21 changed files with 1089 additions and 124 deletions
393
Lib/numbers.py
Normal file
393
Lib/numbers.py
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
# Copyright 2007 Google, Inc. All Rights Reserved.
|
||||
# Licensed to PSF under a Contributor Agreement.
|
||||
|
||||
"""Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
|
||||
|
||||
TODO: Fill out more detailed documentation on the operators."""
|
||||
|
||||
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||
|
||||
__all__ = ["Number", "Exact", "Inexact",
|
||||
"Complex", "Real", "Rational", "Integral",
|
||||
]
|
||||
|
||||
|
||||
class Number(object):
|
||||
"""All numbers inherit from this class.
|
||||
|
||||
If you just want to check if an argument x is a number, without
|
||||
caring what kind, use isinstance(x, Number).
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
|
||||
class Exact(Number):
|
||||
"""Operations on instances of this type are exact.
|
||||
|
||||
As long as the result of a homogenous operation is of the same
|
||||
type, you can assume that it was computed exactly, and there are
|
||||
no round-off errors. Laws like commutativity and associativity
|
||||
hold.
|
||||
"""
|
||||
|
||||
Exact.register(int)
|
||||
Exact.register(long)
|
||||
|
||||
|
||||
class Inexact(Number):
|
||||
"""Operations on instances of this type are inexact.
|
||||
|
||||
Given X, an instance of Inexact, it is possible that (X + -X) + 3
|
||||
== 3, but X + (-X + 3) == 0. The exact form this error takes will
|
||||
vary by type, but it's generally unsafe to compare this type for
|
||||
equality.
|
||||
"""
|
||||
|
||||
Inexact.register(complex)
|
||||
Inexact.register(float)
|
||||
# Inexact.register(decimal.Decimal)
|
||||
|
||||
|
||||
class Complex(Number):
|
||||
"""Complex defines the operations that work on the builtin complex type.
|
||||
|
||||
In short, those are: a conversion to complex, .real, .imag, +, -,
|
||||
*, /, abs(), .conjugate, ==, and !=.
|
||||
|
||||
If it is given heterogenous arguments, and doesn't have special
|
||||
knowledge about them, it should fall back to the builtin complex
|
||||
type as described below.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def __complex__(self):
|
||||
"""Return a builtin complex instance. Called for complex(self)."""
|
||||
|
||||
def __bool__(self):
|
||||
"""True if self != 0. Called for bool(self)."""
|
||||
return self != 0
|
||||
|
||||
@abstractproperty
|
||||
def real(self):
|
||||
"""Retrieve the real component of this number.
|
||||
|
||||
This should subclass Real.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractproperty
|
||||
def imag(self):
|
||||
"""Retrieve the real component of this number.
|
||||
|
||||
This should subclass Real.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __add__(self, other):
|
||||
"""self + other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __radd__(self, other):
|
||||
"""other + self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __neg__(self):
|
||||
"""-self"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __pos__(self):
|
||||
"""+self"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __sub__(self, other):
|
||||
"""self - other"""
|
||||
return self + -other
|
||||
|
||||
def __rsub__(self, other):
|
||||
"""other - self"""
|
||||
return -self + other
|
||||
|
||||
@abstractmethod
|
||||
def __mul__(self, other):
|
||||
"""self * other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rmul__(self, other):
|
||||
"""other * self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __div__(self, other):
|
||||
"""self / other; should promote to float or complex when necessary."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rdiv__(self, other):
|
||||
"""other / self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __pow__(self, exponent):
|
||||
"""self**exponent; should promote to float or complex when necessary."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rpow__(self, base):
|
||||
"""base ** self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __abs__(self):
|
||||
"""Returns the Real distance from 0. Called for abs(self)."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def conjugate(self):
|
||||
"""(x+y*i).conjugate() returns (x-y*i)."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __eq__(self, other):
|
||||
"""self == other"""
|
||||
raise NotImplementedError
|
||||
|
||||
# __ne__ is inherited from object and negates whatever __eq__ does.
|
||||
|
||||
Complex.register(complex)
|
||||
|
||||
|
||||
class Real(Complex):
|
||||
"""To Complex, Real adds the operations that work on real numbers.
|
||||
|
||||
In short, those are: a conversion to float, trunc(), divmod,
|
||||
%, <, <=, >, and >=.
|
||||
|
||||
Real also provides defaults for the derived operations.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def __float__(self):
|
||||
"""Any Real can be converted to a native float object.
|
||||
|
||||
Called for float(self)."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __trunc__(self):
|
||||
"""trunc(self): Truncates self to an Integral.
|
||||
|
||||
Returns an Integral i such that:
|
||||
* i>0 iff self>0;
|
||||
* abs(i) <= abs(self);
|
||||
* for any Integral j satisfying the first two conditions,
|
||||
abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
|
||||
i.e. "truncate towards 0".
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __floor__(self):
|
||||
"""Finds the greatest Integral <= self."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __ceil__(self):
|
||||
"""Finds the least Integral >= self."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __round__(self, ndigits=None):
|
||||
"""Rounds self to ndigits decimal places, defaulting to 0.
|
||||
|
||||
If ndigits is omitted or None, returns an Integral, otherwise
|
||||
returns a Real. Rounds half toward even.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __divmod__(self, other):
|
||||
"""divmod(self, other): The pair (self // other, self % other).
|
||||
|
||||
Sometimes this can be computed faster than the pair of
|
||||
operations.
|
||||
"""
|
||||
return (self // other, self % other)
|
||||
|
||||
def __rdivmod__(self, other):
|
||||
"""divmod(other, self): The pair (self // other, self % other).
|
||||
|
||||
Sometimes this can be computed faster than the pair of
|
||||
operations.
|
||||
"""
|
||||
return (other // self, other % self)
|
||||
|
||||
@abstractmethod
|
||||
def __floordiv__(self, other):
|
||||
"""self // other: The floor() of self/other."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rfloordiv__(self, other):
|
||||
"""other // self: The floor() of other/self."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __mod__(self, other):
|
||||
"""self % other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rmod__(self, other):
|
||||
"""other % self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __lt__(self, other):
|
||||
"""self < other
|
||||
|
||||
< on Reals defines a total ordering, except perhaps for NaN."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __le__(self, other):
|
||||
"""self <= other"""
|
||||
raise NotImplementedError
|
||||
|
||||
# Concrete implementations of Complex abstract methods.
|
||||
def __complex__(self):
|
||||
"""complex(self) == complex(float(self), 0)"""
|
||||
return complex(float(self))
|
||||
|
||||
@property
|
||||
def real(self):
|
||||
"""Real numbers are their real component."""
|
||||
return +self
|
||||
|
||||
@property
|
||||
def imag(self):
|
||||
"""Real numbers have no imaginary component."""
|
||||
return 0
|
||||
|
||||
def conjugate(self):
|
||||
"""Conjugate is a no-op for Reals."""
|
||||
return +self
|
||||
|
||||
Real.register(float)
|
||||
# Real.register(decimal.Decimal)
|
||||
|
||||
|
||||
class Rational(Real, Exact):
|
||||
""".numerator and .denominator should be in lowest terms."""
|
||||
|
||||
@abstractproperty
|
||||
def numerator(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractproperty
|
||||
def denominator(self):
|
||||
raise NotImplementedError
|
||||
|
||||
# Concrete implementation of Real's conversion to float.
|
||||
def __float__(self):
|
||||
"""float(self) = self.numerator / self.denominator"""
|
||||
return self.numerator / self.denominator
|
||||
|
||||
|
||||
class Integral(Rational):
|
||||
"""Integral adds a conversion to long and the bit-string operations."""
|
||||
|
||||
@abstractmethod
|
||||
def __long__(self):
|
||||
"""long(self)"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __index__(self):
|
||||
"""index(self)"""
|
||||
return long(self)
|
||||
|
||||
@abstractmethod
|
||||
def __pow__(self, exponent, modulus=None):
|
||||
"""self ** exponent % modulus, but maybe faster.
|
||||
|
||||
Accept the modulus argument if you want to support the
|
||||
3-argument version of pow(). Raise a TypeError if exponent < 0
|
||||
or any argument isn't Integral. Otherwise, just implement the
|
||||
2-argument version described in Complex.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __lshift__(self, other):
|
||||
"""self << other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rlshift__(self, other):
|
||||
"""other << self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rshift__(self, other):
|
||||
"""self >> other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rrshift__(self, other):
|
||||
"""other >> self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __and__(self, other):
|
||||
"""self & other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rand__(self, other):
|
||||
"""other & self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __xor__(self, other):
|
||||
"""self ^ other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __rxor__(self, other):
|
||||
"""other ^ self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __or__(self, other):
|
||||
"""self | other"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __ror__(self, other):
|
||||
"""other | self"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __invert__(self):
|
||||
"""~self"""
|
||||
raise NotImplementedError
|
||||
|
||||
# Concrete implementations of Rational and Real abstract methods.
|
||||
def __float__(self):
|
||||
"""float(self) == float(long(self))"""
|
||||
return float(long(self))
|
||||
|
||||
@property
|
||||
def numerator(self):
|
||||
"""Integers are their own numerators."""
|
||||
return +self
|
||||
|
||||
@property
|
||||
def denominator(self):
|
||||
"""Integers have a denominator of 1."""
|
||||
return 1
|
||||
|
||||
Integral.register(int)
|
||||
Integral.register(long)
|
||||
62
Lib/test/test_abstract_numbers.py
Normal file
62
Lib/test/test_abstract_numbers.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
"""Unit tests for numbers.py."""
|
||||
|
||||
import unittest
|
||||
from test import test_support
|
||||
from numbers import Number
|
||||
from numbers import Exact, Inexact
|
||||
from numbers import Complex, Real, Rational, Integral
|
||||
import operator
|
||||
|
||||
class TestNumbers(unittest.TestCase):
|
||||
def test_int(self):
|
||||
self.failUnless(issubclass(int, Integral))
|
||||
self.failUnless(issubclass(int, Complex))
|
||||
self.failUnless(issubclass(int, Exact))
|
||||
self.failIf(issubclass(int, Inexact))
|
||||
|
||||
self.assertEqual(7, int(7).real)
|
||||
self.assertEqual(0, int(7).imag)
|
||||
self.assertEqual(7, int(7).conjugate())
|
||||
self.assertEqual(7, int(7).numerator)
|
||||
self.assertEqual(1, int(7).denominator)
|
||||
|
||||
def test_long(self):
|
||||
self.failUnless(issubclass(long, Integral))
|
||||
self.failUnless(issubclass(long, Complex))
|
||||
self.failUnless(issubclass(long, Exact))
|
||||
self.failIf(issubclass(long, Inexact))
|
||||
|
||||
self.assertEqual(7, long(7).real)
|
||||
self.assertEqual(0, long(7).imag)
|
||||
self.assertEqual(7, long(7).conjugate())
|
||||
self.assertEqual(7, long(7).numerator)
|
||||
self.assertEqual(1, long(7).denominator)
|
||||
|
||||
def test_float(self):
|
||||
self.failIf(issubclass(float, Rational))
|
||||
self.failUnless(issubclass(float, Real))
|
||||
self.failIf(issubclass(float, Exact))
|
||||
self.failUnless(issubclass(float, Inexact))
|
||||
|
||||
self.assertEqual(7.3, float(7.3).real)
|
||||
self.assertEqual(0, float(7.3).imag)
|
||||
self.assertEqual(7.3, float(7.3).conjugate())
|
||||
|
||||
def test_complex(self):
|
||||
self.failIf(issubclass(complex, Real))
|
||||
self.failUnless(issubclass(complex, Complex))
|
||||
self.failIf(issubclass(complex, Exact))
|
||||
self.failUnless(issubclass(complex, Inexact))
|
||||
|
||||
c1, c2 = complex(3, 2), complex(4,1)
|
||||
# XXX: This is not ideal, but see the comment in builtin_trunc().
|
||||
self.assertRaises(AttributeError, trunc, c1)
|
||||
self.assertRaises(TypeError, float, c1)
|
||||
self.assertRaises(TypeError, int, c1)
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(TestNumbers)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -1450,11 +1450,13 @@ class BuiltinTest(unittest.TestCase):
|
|||
else:
|
||||
self.assertAlmostEqual(pow(x, y, z), 24.0)
|
||||
|
||||
self.assertAlmostEqual(pow(-1, 0.5), 1j)
|
||||
self.assertAlmostEqual(pow(-1, 1./3), 0.5 + 0.8660254037844386j)
|
||||
|
||||
self.assertRaises(TypeError, pow, -1, -2, 3)
|
||||
self.assertRaises(ValueError, pow, 1, 2, 0)
|
||||
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
|
||||
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
|
||||
self.assertRaises(ValueError, pow, -342.43, 0.234)
|
||||
|
||||
self.assertRaises(TypeError, pow)
|
||||
|
||||
|
|
@ -1622,6 +1624,7 @@ class BuiltinTest(unittest.TestCase):
|
|||
|
||||
def test_round(self):
|
||||
self.assertEqual(round(0.0), 0.0)
|
||||
self.assertEqual(type(round(0.0)), float) # Will be int in 3.0.
|
||||
self.assertEqual(round(1.0), 1.0)
|
||||
self.assertEqual(round(10.0), 10.0)
|
||||
self.assertEqual(round(1000000000.0), 1000000000.0)
|
||||
|
|
@ -1650,12 +1653,50 @@ class BuiltinTest(unittest.TestCase):
|
|||
self.assertEqual(round(-999999999.9), -1000000000.0)
|
||||
|
||||
self.assertEqual(round(-8.0, -1), -10.0)
|
||||
self.assertEqual(type(round(-8.0, -1)), float)
|
||||
|
||||
self.assertEqual(type(round(-8.0, 0)), float)
|
||||
self.assertEqual(type(round(-8.0, 1)), float)
|
||||
|
||||
# Check even / odd rounding behaviour
|
||||
self.assertEqual(round(5.5), 6)
|
||||
self.assertEqual(round(6.5), 6)
|
||||
self.assertEqual(round(-5.5), -6)
|
||||
self.assertEqual(round(-6.5), -6)
|
||||
|
||||
# Check behavior on ints
|
||||
self.assertEqual(round(0), 0)
|
||||
self.assertEqual(round(8), 8)
|
||||
self.assertEqual(round(-8), -8)
|
||||
self.assertEqual(type(round(0)), float) # Will be int in 3.0.
|
||||
self.assertEqual(type(round(-8, -1)), float)
|
||||
self.assertEqual(type(round(-8, 0)), float)
|
||||
self.assertEqual(type(round(-8, 1)), float)
|
||||
|
||||
# test new kwargs
|
||||
self.assertEqual(round(number=-8.0, ndigits=-1), -10.0)
|
||||
|
||||
self.assertRaises(TypeError, round)
|
||||
|
||||
# test generic rounding delegation for reals
|
||||
class TestRound(object):
|
||||
def __round__(self):
|
||||
return 23
|
||||
|
||||
class TestNoRound(object):
|
||||
pass
|
||||
|
||||
self.assertEqual(round(TestRound()), 23)
|
||||
|
||||
self.assertRaises(TypeError, round, 1, 2, 3)
|
||||
# XXX: This is not ideal, but see the comment in builtin_round().
|
||||
self.assertRaises(AttributeError, round, TestNoRound())
|
||||
|
||||
t = TestNoRound()
|
||||
t.__round__ = lambda *args: args
|
||||
self.assertEquals((), round(t))
|
||||
self.assertEquals((0,), round(t, 0))
|
||||
|
||||
def test_setattr(self):
|
||||
setattr(sys, 'spam', 1)
|
||||
self.assertEqual(sys.spam, 1)
|
||||
|
|
@ -1697,6 +1738,38 @@ class BuiltinTest(unittest.TestCase):
|
|||
raise ValueError
|
||||
self.assertRaises(ValueError, sum, BadSeq())
|
||||
|
||||
def test_trunc(self):
|
||||
|
||||
self.assertEqual(trunc(1), 1)
|
||||
self.assertEqual(trunc(-1), -1)
|
||||
self.assertEqual(type(trunc(1)), int)
|
||||
self.assertEqual(type(trunc(1.5)), int)
|
||||
self.assertEqual(trunc(1.5), 1)
|
||||
self.assertEqual(trunc(-1.5), -1)
|
||||
self.assertEqual(trunc(1.999999), 1)
|
||||
self.assertEqual(trunc(-1.999999), -1)
|
||||
self.assertEqual(trunc(-0.999999), -0)
|
||||
self.assertEqual(trunc(-100.999), -100)
|
||||
|
||||
class TestTrunc(object):
|
||||
def __trunc__(self):
|
||||
return 23
|
||||
|
||||
class TestNoTrunc(object):
|
||||
pass
|
||||
|
||||
self.assertEqual(trunc(TestTrunc()), 23)
|
||||
|
||||
self.assertRaises(TypeError, trunc)
|
||||
self.assertRaises(TypeError, trunc, 1, 2)
|
||||
# XXX: This is not ideal, but see the comment in builtin_trunc().
|
||||
self.assertRaises(AttributeError, trunc, TestNoTrunc())
|
||||
|
||||
t = TestNoTrunc()
|
||||
t.__trunc__ = lambda *args: args
|
||||
self.assertEquals((), trunc(t))
|
||||
self.assertRaises(TypeError, trunc, t, 0)
|
||||
|
||||
def test_tuple(self):
|
||||
self.assertEqual(tuple(()), ())
|
||||
t0_3 = (0, 1, 2, 3)
|
||||
|
|
|
|||
|
|
@ -385,7 +385,9 @@ class LongTest(unittest.TestCase):
|
|||
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
|
||||
"math.sin(huge)", "math.sin(mhuge)",
|
||||
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
|
||||
"math.floor(huge)", "math.floor(mhuge)"]:
|
||||
# math.floor() of an int returns an int now
|
||||
##"math.floor(huge)", "math.floor(mhuge)",
|
||||
]:
|
||||
|
||||
self.assertRaises(OverflowError, eval, test, namespace)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,19 @@ class MathTests(unittest.TestCase):
|
|||
self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
|
||||
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
|
||||
|
||||
class TestCeil(object):
|
||||
def __ceil__(self):
|
||||
return 42
|
||||
class TestNoCeil(object):
|
||||
pass
|
||||
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
|
||||
self.assertRaises(TypeError, math.ceil, TestNoCeil())
|
||||
|
||||
t = TestNoCeil()
|
||||
t.__ceil__ = lambda *args: args
|
||||
self.assertRaises(TypeError, math.ceil, t)
|
||||
self.assertRaises(TypeError, math.ceil, t, 0)
|
||||
|
||||
def testCos(self):
|
||||
self.assertRaises(TypeError, math.cos)
|
||||
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
|
||||
|
|
@ -101,6 +114,19 @@ class MathTests(unittest.TestCase):
|
|||
self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
|
||||
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
|
||||
|
||||
class TestFloor(object):
|
||||
def __floor__(self):
|
||||
return 42
|
||||
class TestNoFloor(object):
|
||||
pass
|
||||
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
|
||||
self.assertRaises(TypeError, math.floor, TestNoFloor())
|
||||
|
||||
t = TestNoFloor()
|
||||
t.__floor__ = lambda *args: args
|
||||
self.assertRaises(TypeError, math.floor, t)
|
||||
self.assertRaises(TypeError, math.floor, t, 0)
|
||||
|
||||
def testFmod(self):
|
||||
self.assertRaises(TypeError, math.fmod)
|
||||
self.ftest('fmod(10,1)', math.fmod(10,1), 0)
|
||||
|
|
|
|||
|
|
@ -2264,13 +2264,34 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
|||
expected = ['startTest', 'test', 'stopTest']
|
||||
self.assertEqual(events, expected)
|
||||
|
||||
class Test_Assertions(TestCase):
|
||||
def test_AlmostEqual(self):
|
||||
self.failUnlessAlmostEqual(1.00000001, 1.0)
|
||||
self.failIfAlmostEqual(1.0000001, 1.0)
|
||||
self.assertRaises(AssertionError,
|
||||
self.failUnlessAlmostEqual, 1.0000001, 1.0)
|
||||
self.assertRaises(AssertionError,
|
||||
self.failIfAlmostEqual, 1.00000001, 1.0)
|
||||
|
||||
self.failUnlessAlmostEqual(1.1, 1.0, places=0)
|
||||
self.assertRaises(AssertionError,
|
||||
self.failUnlessAlmostEqual, 1.1, 1.0, places=1)
|
||||
|
||||
self.failUnlessAlmostEqual(0, .1+.1j, places=0)
|
||||
self.failIfAlmostEqual(0, .1+.1j, places=1)
|
||||
self.assertRaises(AssertionError,
|
||||
self.failUnlessAlmostEqual, 0, .1+.1j, places=1)
|
||||
self.assertRaises(AssertionError,
|
||||
self.failIfAlmostEqual, 0, .1+.1j, places=0)
|
||||
|
||||
######################################################################
|
||||
## Main
|
||||
######################################################################
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(Test_TestCase, Test_TestLoader,
|
||||
Test_TestSuite, Test_TestResult, Test_FunctionTestCase)
|
||||
Test_TestSuite, Test_TestResult, Test_FunctionTestCase,
|
||||
Test_Assertions)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ class TestCase:
|
|||
Note that decimal places (from zero) are usually not the same
|
||||
as significant digits (measured from the most signficant digit).
|
||||
"""
|
||||
if round(second-first, places) != 0:
|
||||
if round(abs(second-first), places) != 0:
|
||||
raise self.failureException, \
|
||||
(msg or '%r != %r within %r places' % (first, second, places))
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ class TestCase:
|
|||
Note that decimal places (from zero) are usually not the same
|
||||
as significant digits (measured from the most signficant digit).
|
||||
"""
|
||||
if round(second-first, places) == 0:
|
||||
if round(abs(second-first), places) == 0:
|
||||
raise self.failureException, \
|
||||
(msg or '%r == %r within %r places' % (first, second, places))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue