mirror of
https://github.com/python/cpython.git
synced 2025-09-28 11:15:17 +00:00
Merge 3.3.
This commit is contained in:
commit
6d554b0428
4 changed files with 126 additions and 152 deletions
|
@ -78,14 +78,20 @@ def assert_signals(cls, context, attr, expected):
|
||||||
d = getattr(context, attr)
|
d = getattr(context, attr)
|
||||||
cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
|
cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
|
||||||
|
|
||||||
RoundingModes = {
|
ROUND_UP = P.ROUND_UP
|
||||||
C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
|
ROUND_DOWN = P.ROUND_DOWN
|
||||||
C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
|
ROUND_CEILING = P.ROUND_CEILING
|
||||||
C.ROUND_05UP) if C else None,
|
ROUND_FLOOR = P.ROUND_FLOOR
|
||||||
P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
|
ROUND_HALF_UP = P.ROUND_HALF_UP
|
||||||
P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
|
ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
|
||||||
P.ROUND_05UP)
|
ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
|
||||||
}
|
ROUND_05UP = P.ROUND_05UP
|
||||||
|
|
||||||
|
RoundingModes = [
|
||||||
|
ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
|
||||||
|
ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
|
||||||
|
ROUND_05UP
|
||||||
|
]
|
||||||
|
|
||||||
# Tests are built around these assumed context defaults.
|
# Tests are built around these assumed context defaults.
|
||||||
# test_main() restores the original context.
|
# test_main() restores the original context.
|
||||||
|
@ -96,7 +102,7 @@ ORIGINAL_CONTEXT = {
|
||||||
def init(m):
|
def init(m):
|
||||||
if not m: return
|
if not m: return
|
||||||
DefaultTestContext = m.Context(
|
DefaultTestContext = m.Context(
|
||||||
prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
|
prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
|
||||||
)
|
)
|
||||||
m.setcontext(DefaultTestContext)
|
m.setcontext(DefaultTestContext)
|
||||||
|
|
||||||
|
@ -229,14 +235,14 @@ class IBMTestCases(unittest.TestCase):
|
||||||
'xor':'logical_xor'}
|
'xor':'logical_xor'}
|
||||||
|
|
||||||
# Map test-case names to roundings.
|
# Map test-case names to roundings.
|
||||||
self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
|
self.RoundingDict = {'ceiling' : ROUND_CEILING,
|
||||||
'down' : self.decimal.ROUND_DOWN,
|
'down' : ROUND_DOWN,
|
||||||
'floor' : self.decimal.ROUND_FLOOR,
|
'floor' : ROUND_FLOOR,
|
||||||
'half_down' : self.decimal.ROUND_HALF_DOWN,
|
'half_down' : ROUND_HALF_DOWN,
|
||||||
'half_even' : self.decimal.ROUND_HALF_EVEN,
|
'half_even' : ROUND_HALF_EVEN,
|
||||||
'half_up' : self.decimal.ROUND_HALF_UP,
|
'half_up' : ROUND_HALF_UP,
|
||||||
'up' : self.decimal.ROUND_UP,
|
'up' : ROUND_UP,
|
||||||
'05up' : self.decimal.ROUND_05UP}
|
'05up' : ROUND_05UP}
|
||||||
|
|
||||||
# Map the test cases' error names to the actual errors.
|
# Map the test cases' error names to the actual errors.
|
||||||
self.ErrorNames = {'clamped' : self.decimal.Clamped,
|
self.ErrorNames = {'clamped' : self.decimal.Clamped,
|
||||||
|
@ -2101,9 +2107,6 @@ class UsabilityTest(unittest.TestCase):
|
||||||
Inexact = self.decimal.Inexact
|
Inexact = self.decimal.Inexact
|
||||||
Rounded = self.decimal.Rounded
|
Rounded = self.decimal.Rounded
|
||||||
Clamped = self.decimal.Clamped
|
Clamped = self.decimal.Clamped
|
||||||
ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
|
|
||||||
ROUND_DOWN = self.decimal.ROUND_DOWN
|
|
||||||
ROUND_UP = self.decimal.ROUND_UP
|
|
||||||
|
|
||||||
with localcontext(Context()) as c:
|
with localcontext(Context()) as c:
|
||||||
c.prec = 7
|
c.prec = 7
|
||||||
|
@ -2430,7 +2433,6 @@ class PythonAPItests(unittest.TestCase):
|
||||||
|
|
||||||
def test_int(self):
|
def test_int(self):
|
||||||
Decimal = self.decimal.Decimal
|
Decimal = self.decimal.Decimal
|
||||||
ROUND_DOWN = self.decimal.ROUND_DOWN
|
|
||||||
|
|
||||||
for x in range(-250, 250):
|
for x in range(-250, 250):
|
||||||
s = '%0.2f' % (x / 100.0)
|
s = '%0.2f' % (x / 100.0)
|
||||||
|
@ -2448,7 +2450,6 @@ class PythonAPItests(unittest.TestCase):
|
||||||
|
|
||||||
def test_trunc(self):
|
def test_trunc(self):
|
||||||
Decimal = self.decimal.Decimal
|
Decimal = self.decimal.Decimal
|
||||||
ROUND_DOWN = self.decimal.ROUND_DOWN
|
|
||||||
|
|
||||||
for x in range(-250, 250):
|
for x in range(-250, 250):
|
||||||
s = '%0.2f' % (x / 100.0)
|
s = '%0.2f' % (x / 100.0)
|
||||||
|
@ -2491,8 +2492,6 @@ class PythonAPItests(unittest.TestCase):
|
||||||
def test_create_decimal_from_float(self):
|
def test_create_decimal_from_float(self):
|
||||||
Decimal = self.decimal.Decimal
|
Decimal = self.decimal.Decimal
|
||||||
Context = self.decimal.Context
|
Context = self.decimal.Context
|
||||||
ROUND_DOWN = self.decimal.ROUND_DOWN
|
|
||||||
ROUND_UP = self.decimal.ROUND_UP
|
|
||||||
Inexact = self.decimal.Inexact
|
Inexact = self.decimal.Inexact
|
||||||
|
|
||||||
context = Context(prec=5, rounding=ROUND_DOWN)
|
context = Context(prec=5, rounding=ROUND_DOWN)
|
||||||
|
@ -2522,7 +2521,6 @@ class PythonAPItests(unittest.TestCase):
|
||||||
Decimal = self.decimal.Decimal
|
Decimal = self.decimal.Decimal
|
||||||
Context = self.decimal.Context
|
Context = self.decimal.Context
|
||||||
InvalidOperation = self.decimal.InvalidOperation
|
InvalidOperation = self.decimal.InvalidOperation
|
||||||
ROUND_DOWN = self.decimal.ROUND_DOWN
|
|
||||||
|
|
||||||
c = Context(Emax=99999, Emin=-99999)
|
c = Context(Emax=99999, Emin=-99999)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -2723,7 +2721,6 @@ class ContextAPItests(unittest.TestCase):
|
||||||
InvalidOperation = self.decimal.InvalidOperation
|
InvalidOperation = self.decimal.InvalidOperation
|
||||||
DivisionByZero = self.decimal.DivisionByZero
|
DivisionByZero = self.decimal.DivisionByZero
|
||||||
Overflow = self.decimal.Overflow
|
Overflow = self.decimal.Overflow
|
||||||
ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
|
|
||||||
|
|
||||||
c1 = Context()
|
c1 = Context()
|
||||||
c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
|
c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
|
||||||
|
@ -2739,6 +2736,21 @@ class ContextAPItests(unittest.TestCase):
|
||||||
assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
|
assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
|
||||||
Overflow])
|
Overflow])
|
||||||
|
|
||||||
|
@cpython_only
|
||||||
|
def test_from_legacy_strings(self):
|
||||||
|
import _testcapi
|
||||||
|
c = self.decimal.Context()
|
||||||
|
|
||||||
|
for rnd in RoundingModes:
|
||||||
|
c.rounding = _testcapi.unicode_legacy_string(rnd)
|
||||||
|
self.assertEqual(c.rounding, rnd)
|
||||||
|
|
||||||
|
s = _testcapi.unicode_legacy_string('')
|
||||||
|
self.assertRaises(TypeError, setattr, c, 'rounding', s)
|
||||||
|
|
||||||
|
s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
|
||||||
|
self.assertRaises(TypeError, setattr, c, 'rounding', s)
|
||||||
|
|
||||||
def test_pickle(self):
|
def test_pickle(self):
|
||||||
|
|
||||||
Context = self.decimal.Context
|
Context = self.decimal.Context
|
||||||
|
@ -2762,7 +2774,7 @@ class ContextAPItests(unittest.TestCase):
|
||||||
# Test interchangeability
|
# Test interchangeability
|
||||||
combinations = [(C, P), (P, C)] if C else [(P, P)]
|
combinations = [(C, P), (P, C)] if C else [(P, P)]
|
||||||
for dumper, loader in combinations:
|
for dumper, loader in combinations:
|
||||||
for ri, _ in enumerate(RoundingModes[dumper]):
|
for ri, _ in enumerate(RoundingModes):
|
||||||
for fi, _ in enumerate(OrderedSignals[dumper]):
|
for fi, _ in enumerate(OrderedSignals[dumper]):
|
||||||
for ti, _ in enumerate(OrderedSignals[dumper]):
|
for ti, _ in enumerate(OrderedSignals[dumper]):
|
||||||
|
|
||||||
|
@ -2776,7 +2788,7 @@ class ContextAPItests(unittest.TestCase):
|
||||||
sys.modules['decimal'] = dumper
|
sys.modules['decimal'] = dumper
|
||||||
c = dumper.Context(
|
c = dumper.Context(
|
||||||
prec=prec, Emin=emin, Emax=emax,
|
prec=prec, Emin=emin, Emax=emax,
|
||||||
rounding=RoundingModes[dumper][ri],
|
rounding=RoundingModes[ri],
|
||||||
capitals=caps, clamp=clamp,
|
capitals=caps, clamp=clamp,
|
||||||
flags=OrderedSignals[dumper][:fi],
|
flags=OrderedSignals[dumper][:fi],
|
||||||
traps=OrderedSignals[dumper][:ti]
|
traps=OrderedSignals[dumper][:ti]
|
||||||
|
@ -2791,7 +2803,7 @@ class ContextAPItests(unittest.TestCase):
|
||||||
self.assertEqual(d.prec, prec)
|
self.assertEqual(d.prec, prec)
|
||||||
self.assertEqual(d.Emin, emin)
|
self.assertEqual(d.Emin, emin)
|
||||||
self.assertEqual(d.Emax, emax)
|
self.assertEqual(d.Emax, emax)
|
||||||
self.assertEqual(d.rounding, RoundingModes[loader][ri])
|
self.assertEqual(d.rounding, RoundingModes[ri])
|
||||||
self.assertEqual(d.capitals, caps)
|
self.assertEqual(d.capitals, caps)
|
||||||
self.assertEqual(d.clamp, clamp)
|
self.assertEqual(d.clamp, clamp)
|
||||||
assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
|
assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
|
||||||
|
@ -3593,7 +3605,6 @@ class ContextFlags(unittest.TestCase):
|
||||||
Underflow = self.decimal.Underflow
|
Underflow = self.decimal.Underflow
|
||||||
Clamped = self.decimal.Clamped
|
Clamped = self.decimal.Clamped
|
||||||
Subnormal = self.decimal.Subnormal
|
Subnormal = self.decimal.Subnormal
|
||||||
ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
|
|
||||||
|
|
||||||
def raise_error(context, flag):
|
def raise_error(context, flag):
|
||||||
if self.decimal == C:
|
if self.decimal == C:
|
||||||
|
@ -3960,17 +3971,6 @@ class ContextInputValidation(unittest.TestCase):
|
||||||
self.assertRaises(ValueError, setattr, c, 'Emin', 1)
|
self.assertRaises(ValueError, setattr, c, 'Emin', 1)
|
||||||
self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
|
self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
|
||||||
|
|
||||||
# rounding: always raise TypeError in order to get consistent
|
|
||||||
# exceptions across implementations. In decimal, rounding
|
|
||||||
# modes are strings, in _decimal they are integers. The idea
|
|
||||||
# is to view rounding as an abstract type and not mind the
|
|
||||||
# implementation details.
|
|
||||||
# Hence, a user should view the rounding modes as if they
|
|
||||||
# had been defined in a language that supports abstract
|
|
||||||
# data types, e.g. ocaml:
|
|
||||||
#
|
|
||||||
# type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
|
|
||||||
#
|
|
||||||
self.assertRaises(TypeError, setattr, c, 'rounding', -1)
|
self.assertRaises(TypeError, setattr, c, 'rounding', -1)
|
||||||
self.assertRaises(TypeError, setattr, c, 'rounding', 9)
|
self.assertRaises(TypeError, setattr, c, 'rounding', 9)
|
||||||
self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
|
self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
|
||||||
|
@ -4023,8 +4023,6 @@ class ContextSubclassing(unittest.TestCase):
|
||||||
decimal = self.decimal
|
decimal = self.decimal
|
||||||
Decimal = decimal.Decimal
|
Decimal = decimal.Decimal
|
||||||
Context = decimal.Context
|
Context = decimal.Context
|
||||||
ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
|
|
||||||
ROUND_DOWN = decimal.ROUND_DOWN
|
|
||||||
Clamped = decimal.Clamped
|
Clamped = decimal.Clamped
|
||||||
DivisionByZero = decimal.DivisionByZero
|
DivisionByZero = decimal.DivisionByZero
|
||||||
Inexact = decimal.Inexact
|
Inexact = decimal.Inexact
|
||||||
|
@ -4192,7 +4190,7 @@ class Coverage(unittest.TestCase):
|
||||||
c.prec = 425000000
|
c.prec = 425000000
|
||||||
c.Emax = 425000000
|
c.Emax = 425000000
|
||||||
c.Emin = -425000000
|
c.Emin = -425000000
|
||||||
c.rounding = self.decimal.ROUND_HALF_DOWN
|
c.rounding = ROUND_HALF_DOWN
|
||||||
c.capitals = 0
|
c.capitals = 0
|
||||||
c.clamp = 1
|
c.clamp = 1
|
||||||
for sig in OrderedSignals[self.decimal]:
|
for sig in OrderedSignals[self.decimal]:
|
||||||
|
@ -4584,7 +4582,6 @@ class PyWhitebox(unittest.TestCase):
|
||||||
def test_py_rescale(self):
|
def test_py_rescale(self):
|
||||||
# Coverage
|
# Coverage
|
||||||
Decimal = P.Decimal
|
Decimal = P.Decimal
|
||||||
ROUND_UP = P.ROUND_UP
|
|
||||||
localcontext = P.localcontext
|
localcontext = P.localcontext
|
||||||
|
|
||||||
with localcontext() as c:
|
with localcontext() as c:
|
||||||
|
@ -4594,7 +4591,6 @@ class PyWhitebox(unittest.TestCase):
|
||||||
def test_py__round(self):
|
def test_py__round(self):
|
||||||
# Coverage
|
# Coverage
|
||||||
Decimal = P.Decimal
|
Decimal = P.Decimal
|
||||||
ROUND_UP = P.ROUND_UP
|
|
||||||
|
|
||||||
self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
|
self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
|
||||||
|
|
||||||
|
@ -4663,11 +4659,6 @@ class CFunctionality(unittest.TestCase):
|
||||||
self.assertEqual(C.DECIMAL128, 128)
|
self.assertEqual(C.DECIMAL128, 128)
|
||||||
self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
|
self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
|
||||||
|
|
||||||
# Rounding modes
|
|
||||||
for i, v in enumerate(RoundingModes[C]):
|
|
||||||
self.assertEqual(v, i)
|
|
||||||
self.assertEqual(C.ROUND_TRUNC, 8)
|
|
||||||
|
|
||||||
# Conditions
|
# Conditions
|
||||||
for i, v in enumerate(cond):
|
for i, v in enumerate(cond):
|
||||||
self.assertEqual(v, 1<<i)
|
self.assertEqual(v, 1<<i)
|
||||||
|
@ -4727,7 +4718,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
# in the same order.
|
# in the same order.
|
||||||
DefaultContext = C.DefaultContext
|
DefaultContext = C.DefaultContext
|
||||||
FloatOperation = C.FloatOperation
|
FloatOperation = C.FloatOperation
|
||||||
ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
|
|
||||||
|
|
||||||
c = DefaultContext.copy()
|
c = DefaultContext.copy()
|
||||||
|
|
||||||
|
@ -4800,7 +4790,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
self.assertRaises(OverflowError, Context, prec=int_max+1)
|
self.assertRaises(OverflowError, Context, prec=int_max+1)
|
||||||
self.assertRaises(OverflowError, Context, Emax=int_max+1)
|
self.assertRaises(OverflowError, Context, Emax=int_max+1)
|
||||||
self.assertRaises(OverflowError, Context, Emin=-int_max-2)
|
self.assertRaises(OverflowError, Context, Emin=-int_max-2)
|
||||||
self.assertRaises(OverflowError, Context, rounding=int_max+1)
|
|
||||||
self.assertRaises(OverflowError, Context, clamp=int_max+1)
|
self.assertRaises(OverflowError, Context, clamp=int_max+1)
|
||||||
self.assertRaises(OverflowError, Context, capitals=int_max+1)
|
self.assertRaises(OverflowError, Context, capitals=int_max+1)
|
||||||
|
|
||||||
|
@ -4812,14 +4801,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
self.assertRaises(ValueError, setattr, c, attr, int_max)
|
self.assertRaises(ValueError, setattr, c, attr, int_max)
|
||||||
self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
|
self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
|
||||||
|
|
||||||
# OverflowError, general TypeError
|
|
||||||
for attr in ('rounding',):
|
|
||||||
self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
|
|
||||||
self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
|
|
||||||
if sys.platform != 'win32':
|
|
||||||
self.assertRaises(TypeError, setattr, c, attr, int_max)
|
|
||||||
self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
|
|
||||||
|
|
||||||
# OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
|
# OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
|
||||||
if C.MAX_PREC == 425000000:
|
if C.MAX_PREC == 425000000:
|
||||||
self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
|
self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
|
||||||
|
@ -4862,6 +4843,17 @@ class CWhitebox(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, setcontext, "xyz")
|
self.assertRaises(TypeError, setcontext, "xyz")
|
||||||
setcontext(saved_context)
|
setcontext(saved_context)
|
||||||
|
|
||||||
|
def test_rounding_strings_interned(self):
|
||||||
|
|
||||||
|
self.assertIs(C.ROUND_UP, P.ROUND_UP)
|
||||||
|
self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
|
||||||
|
self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
|
||||||
|
self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
|
||||||
|
self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
|
||||||
|
self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
|
||||||
|
self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
|
||||||
|
self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
|
||||||
|
|
||||||
@requires_extra_functionality
|
@requires_extra_functionality
|
||||||
def test_c_context_errors_extra(self):
|
def test_c_context_errors_extra(self):
|
||||||
Context = C.Context
|
Context = C.Context
|
||||||
|
@ -4908,7 +4900,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
def test_c_valid_context(self):
|
def test_c_valid_context(self):
|
||||||
# These tests are for code coverage in _decimal.
|
# These tests are for code coverage in _decimal.
|
||||||
DefaultContext = C.DefaultContext
|
DefaultContext = C.DefaultContext
|
||||||
ROUND_HALF_UP = C.ROUND_HALF_UP
|
|
||||||
Clamped = C.Clamped
|
Clamped = C.Clamped
|
||||||
Underflow = C.Underflow
|
Underflow = C.Underflow
|
||||||
Inexact = C.Inexact
|
Inexact = C.Inexact
|
||||||
|
@ -5000,7 +4991,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
def test_c_integral(self):
|
def test_c_integral(self):
|
||||||
Decimal = C.Decimal
|
Decimal = C.Decimal
|
||||||
Inexact = C.Inexact
|
Inexact = C.Inexact
|
||||||
ROUND_UP = C.ROUND_UP
|
|
||||||
localcontext = C.localcontext
|
localcontext = C.localcontext
|
||||||
|
|
||||||
x = Decimal(10)
|
x = Decimal(10)
|
||||||
|
@ -5034,7 +5024,6 @@ class CWhitebox(unittest.TestCase):
|
||||||
Decimal = C.Decimal
|
Decimal = C.Decimal
|
||||||
InvalidOperation = C.InvalidOperation
|
InvalidOperation = C.InvalidOperation
|
||||||
DivisionByZero = C.DivisionByZero
|
DivisionByZero = C.DivisionByZero
|
||||||
ROUND_UP = C.ROUND_UP
|
|
||||||
getcontext = C.getcontext
|
getcontext = C.getcontext
|
||||||
localcontext = C.localcontext
|
localcontext = C.localcontext
|
||||||
|
|
||||||
|
@ -5237,7 +5226,7 @@ class CWhitebox(unittest.TestCase):
|
||||||
lim = len(OrderedSignals[C])
|
lim = len(OrderedSignals[C])
|
||||||
for r in range(lim):
|
for r in range(lim):
|
||||||
for t in range(lim):
|
for t in range(lim):
|
||||||
for round in RoundingModes[C]:
|
for round in RoundingModes:
|
||||||
flags = random.sample(OrderedSignals[C], r)
|
flags = random.sample(OrderedSignals[C], r)
|
||||||
traps = random.sample(OrderedSignals[C], t)
|
traps = random.sample(OrderedSignals[C], t)
|
||||||
prec = random.randrange(1, 10000)
|
prec = random.randrange(1, 10000)
|
||||||
|
|
|
@ -220,6 +220,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #16422: Use strings for rounding mode constants for better readability
|
||||||
|
and pickling compatibility.
|
||||||
|
|
||||||
- Issue #15861: tkinter now correctly works with lists and tuples containing
|
- Issue #15861: tkinter now correctly works with lists and tuples containing
|
||||||
strings with whitespaces, backslashes or unbalanced braces.
|
strings with whitespaces, backslashes or unbalanced braces.
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,13 @@ static const char *dec_signal_string[MPD_NUM_FLAGS] = {
|
||||||
"Underflow",
|
"Underflow",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef EXTRA_FUNCTIONALITY
|
||||||
|
#define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
|
||||||
|
#else
|
||||||
|
#define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
|
||||||
|
#endif
|
||||||
|
static PyObject *round_map[_PY_DEC_ROUND_GUARD];
|
||||||
|
|
||||||
static const char *invalid_rounding_err =
|
static const char *invalid_rounding_err =
|
||||||
"valid values for rounding are:\n\
|
"valid values for rounding are:\n\
|
||||||
[ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
|
[ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
|
||||||
|
@ -249,13 +256,6 @@ type_error_int(const char *mesg)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
type_error_ptr(const char *mesg)
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_TypeError, mesg);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
runtime_error_int(const char *mesg)
|
runtime_error_int(const char *mesg)
|
||||||
{
|
{
|
||||||
|
@ -502,6 +502,27 @@ dec_addstatus(PyObject *context, uint32_t status)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getround(PyObject *v)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (PyUnicode_Check(v)) {
|
||||||
|
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
|
||||||
|
if (v == round_map[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
|
||||||
|
if (PyUnicode_Compare(v, round_map[i]) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type_error_int(invalid_rounding_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* SignalDict Object */
|
/* SignalDict Object */
|
||||||
|
@ -715,7 +736,6 @@ context_get##mem(PyObject *self, void *closure UNUSED) \
|
||||||
Dec_CONTEXT_GET_SSIZE(prec)
|
Dec_CONTEXT_GET_SSIZE(prec)
|
||||||
Dec_CONTEXT_GET_SSIZE(emax)
|
Dec_CONTEXT_GET_SSIZE(emax)
|
||||||
Dec_CONTEXT_GET_SSIZE(emin)
|
Dec_CONTEXT_GET_SSIZE(emin)
|
||||||
Dec_CONTEXT_GET_SSIZE(round)
|
|
||||||
Dec_CONTEXT_GET_SSIZE(clamp)
|
Dec_CONTEXT_GET_SSIZE(clamp)
|
||||||
|
|
||||||
#ifdef EXTRA_FUNCTIONALITY
|
#ifdef EXTRA_FUNCTIONALITY
|
||||||
|
@ -723,6 +743,15 @@ Dec_CONTEXT_GET_ULONG(traps)
|
||||||
Dec_CONTEXT_GET_ULONG(status)
|
Dec_CONTEXT_GET_ULONG(status)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
context_getround(PyObject *self, void *closure UNUSED)
|
||||||
|
{
|
||||||
|
int i = mpd_getround(CTX(self));
|
||||||
|
|
||||||
|
Py_INCREF(round_map[i]);
|
||||||
|
return round_map[i];
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
context_getcapitals(PyObject *self, void *closure UNUSED)
|
context_getcapitals(PyObject *self, void *closure UNUSED)
|
||||||
{
|
{
|
||||||
|
@ -875,17 +904,16 @@ static int
|
||||||
context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
|
context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
|
||||||
{
|
{
|
||||||
mpd_context_t *ctx;
|
mpd_context_t *ctx;
|
||||||
mpd_ssize_t x;
|
int x;
|
||||||
|
|
||||||
x = PyLong_AsSsize_t(value);
|
x = getround(value);
|
||||||
if (x == -1 && PyErr_Occurred()) {
|
if (x == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
BOUNDS_CHECK(x, INT_MIN, INT_MAX);
|
|
||||||
|
|
||||||
ctx = CTX(self);
|
ctx = CTX(self);
|
||||||
if (!mpd_qsetround(ctx, (int)x)) {
|
if (!mpd_qsetround(ctx, x)) {
|
||||||
return type_error_int(invalid_rounding_err);
|
INTERNAL_ERROR_INT("context_setround"); /* GCOV_NOT_REACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1207,33 +1235,6 @@ context_dealloc(PyDecContextObject *self)
|
||||||
Py_TYPE(self)->tp_free(self);
|
Py_TYPE(self)->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
getround(PyObject *v)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
long x;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (PyLong_Check(v)) {
|
|
||||||
x = PyLong_AsLong(v);
|
|
||||||
if (x == -1 && PyErr_Occurred()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
BOUNDS_CHECK(x, 0, INT_MAX);
|
|
||||||
return (int)x;
|
|
||||||
}
|
|
||||||
else if (PyUnicode_Check(v)) {
|
|
||||||
for (i = 0; i < MPD_ROUND_GUARD; i++) {
|
|
||||||
s = mpd_round_string[i];
|
|
||||||
if (PyUnicode_CompareWithASCIIString(v, s) == 0) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return type_error_int("invalid rounding mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
context_init(PyObject *self, PyObject *args, PyObject *kwds)
|
context_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
|
@ -1264,6 +1265,9 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
if (prec != Py_None && context_setprec(self, prec, NULL) < 0) {
|
if (prec != Py_None && context_setprec(self, prec, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (rounding != Py_None && context_setround(self, rounding, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (emin != Py_None && context_setemin(self, emin, NULL) < 0) {
|
if (emin != Py_None && context_setemin(self, emin, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1277,16 +1281,6 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rounding != Py_None) {
|
|
||||||
int x = getround(rounding);
|
|
||||||
if (x < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!mpd_qsetround(CTX(self), x)) {
|
|
||||||
return type_error_int(invalid_rounding_err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (traps != Py_None) {
|
if (traps != Py_None) {
|
||||||
if (PyList_Check(traps)) {
|
if (PyList_Check(traps)) {
|
||||||
ret = context_settraps_list(self, traps);
|
ret = context_settraps_list(self, traps);
|
||||||
|
@ -3345,7 +3339,7 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!mpd_qsetround(&workctx, round)) {
|
if (!mpd_qsetround(&workctx, round)) {
|
||||||
return type_error_ptr(invalid_rounding_err);
|
INTERNAL_ERROR_PTR("PyDec_ToIntegralValue"); /* GCOV_NOT_REACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3386,7 +3380,7 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!mpd_qsetround(&workctx, round)) {
|
if (!mpd_qsetround(&workctx, round)) {
|
||||||
return type_error_ptr(invalid_rounding_err);
|
INTERNAL_ERROR_PTR("PyDec_ToIntegralExact"); /* GCOV_NOT_REACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4187,7 +4181,7 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!mpd_qsetround(&workctx, round)) {
|
if (!mpd_qsetround(&workctx, round)) {
|
||||||
return type_error_ptr(invalid_rounding_err);
|
INTERNAL_ERROR_PTR("dec_mpd_qquantize"); /* GCOV_NOT_REACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5419,17 +5413,6 @@ static struct int_constmap int_constants [] = {
|
||||||
{"DECIMAL64", MPD_DECIMAL64},
|
{"DECIMAL64", MPD_DECIMAL64},
|
||||||
{"DECIMAL128", MPD_DECIMAL128},
|
{"DECIMAL128", MPD_DECIMAL128},
|
||||||
{"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
|
{"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
|
||||||
#endif
|
|
||||||
{"ROUND_CEILING", MPD_ROUND_CEILING},
|
|
||||||
{"ROUND_FLOOR", MPD_ROUND_FLOOR},
|
|
||||||
{"ROUND_UP", MPD_ROUND_UP},
|
|
||||||
{"ROUND_DOWN", MPD_ROUND_DOWN},
|
|
||||||
{"ROUND_HALF_UP", MPD_ROUND_HALF_UP},
|
|
||||||
{"ROUND_HALF_DOWN", MPD_ROUND_HALF_DOWN},
|
|
||||||
{"ROUND_HALF_EVEN", MPD_ROUND_HALF_EVEN},
|
|
||||||
{"ROUND_05UP", MPD_ROUND_05UP},
|
|
||||||
#ifdef EXTRA_FUNCTIONALITY
|
|
||||||
{"ROUND_TRUNC", MPD_ROUND_TRUNC},
|
|
||||||
/* int condition flags */
|
/* int condition flags */
|
||||||
{"DecClamped", MPD_Clamped},
|
{"DecClamped", MPD_Clamped},
|
||||||
{"DecConversionSyntax", MPD_Conversion_syntax},
|
{"DecConversionSyntax", MPD_Conversion_syntax},
|
||||||
|
@ -5680,6 +5663,13 @@ PyInit__decimal(void)
|
||||||
int_cm->val));
|
int_cm->val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Init string constants */
|
||||||
|
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
|
||||||
|
ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
|
||||||
|
Py_INCREF(round_map[i]);
|
||||||
|
CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], round_map[i]));
|
||||||
|
}
|
||||||
|
|
||||||
/* Add specification version number */
|
/* Add specification version number */
|
||||||
CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));
|
CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));
|
||||||
|
|
||||||
|
|
|
@ -158,17 +158,9 @@ CondMap = {
|
||||||
C.FloatOperation: P.FloatOperation,
|
C.FloatOperation: P.FloatOperation,
|
||||||
}
|
}
|
||||||
|
|
||||||
RoundMap = {
|
RoundModes = [C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
|
||||||
C.ROUND_UP: P.ROUND_UP,
|
C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
|
||||||
C.ROUND_DOWN: P.ROUND_DOWN,
|
C.ROUND_05UP]
|
||||||
C.ROUND_CEILING: P.ROUND_CEILING,
|
|
||||||
C.ROUND_FLOOR: P.ROUND_FLOOR,
|
|
||||||
C.ROUND_HALF_UP: P.ROUND_HALF_UP,
|
|
||||||
C.ROUND_HALF_DOWN: P.ROUND_HALF_DOWN,
|
|
||||||
C.ROUND_HALF_EVEN: P.ROUND_HALF_EVEN,
|
|
||||||
C.ROUND_05UP: P.ROUND_05UP
|
|
||||||
}
|
|
||||||
RoundModes = RoundMap.items()
|
|
||||||
|
|
||||||
|
|
||||||
class Context(object):
|
class Context(object):
|
||||||
|
@ -183,7 +175,7 @@ class Context(object):
|
||||||
self.p.prec = self.c.prec
|
self.p.prec = self.c.prec
|
||||||
self.p.Emin = self.c.Emin
|
self.p.Emin = self.c.Emin
|
||||||
self.p.Emax = self.c.Emax
|
self.p.Emax = self.c.Emax
|
||||||
self.p.rounding = RoundMap[self.c.rounding]
|
self.p.rounding = self.c.rounding
|
||||||
self.p.capitals = self.c.capitals
|
self.p.capitals = self.c.capitals
|
||||||
self.settraps([sig for sig in self.c.traps if self.c.traps[sig]])
|
self.settraps([sig for sig in self.c.traps if self.c.traps[sig]])
|
||||||
self.setstatus([sig for sig in self.c.flags if self.c.flags[sig]])
|
self.setstatus([sig for sig in self.c.flags if self.c.flags[sig]])
|
||||||
|
@ -217,12 +209,12 @@ class Context(object):
|
||||||
self.p.Emax = val
|
self.p.Emax = val
|
||||||
|
|
||||||
def getround(self):
|
def getround(self):
|
||||||
assert(self.c.rounding == RoundMap[self.p.rounding])
|
assert(self.c.rounding == self.p.rounding)
|
||||||
return self.c.rounding
|
return self.c.rounding
|
||||||
|
|
||||||
def setround(self, val):
|
def setround(self, val):
|
||||||
self.c.rounding = val
|
self.c.rounding = val
|
||||||
self.p.rounding = RoundMap[val]
|
self.p.rounding = val
|
||||||
|
|
||||||
def getcapitals(self):
|
def getcapitals(self):
|
||||||
assert(self.c.capitals == self.p.capitals)
|
assert(self.c.capitals == self.p.capitals)
|
||||||
|
@ -627,7 +619,11 @@ def convert(t, convstr=True):
|
||||||
|
|
||||||
context.clear_status()
|
context.clear_status()
|
||||||
|
|
||||||
if not t.contextfunc and i == 0 or \
|
if op in RoundModes:
|
||||||
|
t.cop.append(op)
|
||||||
|
t.pop.append(op)
|
||||||
|
|
||||||
|
elif not t.contextfunc and i == 0 or \
|
||||||
convstr and isinstance(op, str):
|
convstr and isinstance(op, str):
|
||||||
try:
|
try:
|
||||||
c = C.Decimal(op)
|
c = C.Decimal(op)
|
||||||
|
@ -662,10 +658,6 @@ def convert(t, convstr=True):
|
||||||
t.cop.append(op.c)
|
t.cop.append(op.c)
|
||||||
t.pop.append(op.p)
|
t.pop.append(op.p)
|
||||||
|
|
||||||
elif op in RoundModes:
|
|
||||||
t.cop.append(op[0])
|
|
||||||
t.pop.append(op[1])
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
t.cop.append(op)
|
t.cop.append(op)
|
||||||
t.pop.append(op)
|
t.pop.append(op)
|
||||||
|
@ -809,7 +801,7 @@ def test_method(method, testspecs, testfunc):
|
||||||
log(" prec: %d emin: %d emax: %d",
|
log(" prec: %d emin: %d emax: %d",
|
||||||
(context.prec, context.Emin, context.Emax))
|
(context.prec, context.Emin, context.Emax))
|
||||||
restr_range = 9999 if context.Emax > 9999 else context.Emax+99
|
restr_range = 9999 if context.Emax > 9999 else context.Emax+99
|
||||||
for rounding in sorted(RoundMap):
|
for rounding in RoundModes:
|
||||||
context.rounding = rounding
|
context.rounding = rounding
|
||||||
context.capitals = random.randrange(2)
|
context.capitals = random.randrange(2)
|
||||||
if spec['clamp'] == 'rand':
|
if spec['clamp'] == 'rand':
|
||||||
|
@ -941,7 +933,7 @@ def test_round(method, prec, exprange, restricted_range, itr, stat):
|
||||||
|
|
||||||
def test_from_float(method, prec, exprange, restricted_range, itr, stat):
|
def test_from_float(method, prec, exprange, restricted_range, itr, stat):
|
||||||
"""Iterate the __float__ method through many test cases."""
|
"""Iterate the __float__ method through many test cases."""
|
||||||
for rounding in sorted(RoundMap):
|
for rounding in RoundModes:
|
||||||
context.rounding = rounding
|
context.rounding = rounding
|
||||||
for i in range(1000):
|
for i in range(1000):
|
||||||
f = randfloat()
|
f = randfloat()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue