Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bf44069

Browse files
committed
Improve Context construction and representation:
* Rename "trap_enablers" to just "traps". * Simplify names of "settraps" and "setflags" to just "traps" and "flags". * Show "capitals" in the context representation * Simplify the Context constructor to match its repr form so that only the set flags and traps need to be listed. * Representation can now be run through eval(). Improve the error message when the Decimal constructor is given a float. The test suite no longer needs a duplicate reset_flags method.
1 parent d9dfe02 commit bf44069

3 files changed

Lines changed: 54 additions & 58 deletions

File tree

Doc/lib/libdecimal.tex

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ \subsection{Quick-start Tutorial \label{decimal-tutorial}}
112112
>>> from decimal import *
113113
>>> getcontext()
114114
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
115-
setflags=[], settraps=[])
115+
capitals=1, flags=[], traps=[])
116116
117117
>>> getcontext().prec = 7
118118
\end{verbatim}
@@ -204,10 +204,10 @@ \subsection{Quick-start Tutorial \label{decimal-tutorial}}
204204
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
205205
>>> myothercontext
206206
Context(prec=60, rounding=ROUND_HALF_DOWN, Emin=-999999999, Emax=999999999,
207-
setflags=[], settraps=[])
207+
capitals=1, flags=[], traps=[])
208208
>>> ExtendedContext
209209
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
210-
setflags=[], settraps=[])
210+
capitals=1, flags=[], traps=[])
211211
>>> setcontext(myothercontext)
212212
>>> Decimal(1) / Decimal(7)
213213
Decimal("0.142857142857142857142857142857142857142857142857142857142857")
@@ -236,21 +236,21 @@ \subsection{Quick-start Tutorial \label{decimal-tutorial}}
236236
Decimal("3.14159292")
237237
>>> getcontext()
238238
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
239-
setflags=['Inexact', 'Rounded'], settraps=[])
239+
capitals=1, flags=[Inexact, Rounded], traps=[])
240240
\end{verbatim}
241241

242-
The \var{setflags} entry shows that the rational approximation to
242+
The \var{flags} entry shows that the rational approximation to
243243
\constant{Pi} was rounded (digits beyond the context precision were thrown
244244
away) and that the result is inexact (some of the discarded digits were
245245
non-zero).
246246

247-
Individual traps are set using the dictionary in the \member{trap_enablers}
247+
Individual traps are set using the dictionary in the \member{traps}
248248
field of a context:
249249

250250
\begin{verbatim}
251251
>>> Decimal(1) / Decimal(0)
252252
Decimal("Infinity")
253-
>>> getcontext().trap_enablers[DivisionByZero] = 1
253+
>>> getcontext().traps[DivisionByZero] = 1
254254
>>> Decimal(1) / Decimal(0)
255255
256256
Traceback (most recent call last):
@@ -264,14 +264,14 @@ \subsection{Quick-start Tutorial \label{decimal-tutorial}}
264264

265265
\begin{verbatim}
266266
>>> getcontext.clear_flags()
267-
>>> for sig in getcontext().trap_enablers:
268-
... getcontext().trap_enablers[sig] = 1
267+
>>> for sig in getcontext().traps:
268+
... getcontext().traps[sig] = 1
269269
270-
>>> getcontext().trap_enablers.update({Rounded:0, Inexact:0, Subnormal:0})
270+
>>> getcontext().traps.update({Rounded:0, Inexact:0, Subnormal:0})
271271
>>> getcontext()
272272
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
273-
setflags=[], settraps=['Clamped', 'Underflow', 'InvalidOperation',
274-
'DivisionByZero', 'Overflow'])
273+
capitals=1, flags=[], traps=[Clamped, Underflow,
274+
InvalidOperation, DivisionByZero, Overflow])
275275
\end{verbatim}
276276

277277
Applications typically set the context once at the beginning of a program
@@ -489,7 +489,7 @@ \subsection{Context objects \label{decimal-decimal}}
489489
In addition to the three supplied contexts, new contexts can be created
490490
with the \class{Context} constructor.
491491

492-
\begin{classdesc}{Context}{prec=None, rounding=None, trap_enablers=None,
492+
\begin{classdesc}{Context}{prec=None, rounding=None, traps=None,
493493
flags=None, Emin=None, Emax=None, capitals=1}
494494
Creates a new context. If a field is not specified or is \constant{None},
495495
the default values are copied from the \constant{DefaultContext}. If the
@@ -508,7 +508,7 @@ \subsection{Context objects \label{decimal-decimal}}
508508
\constant{ROUND_HALF_UP} (away from zero), or
509509
\constant{ROUND_UP} (away from zero).
510510

511-
The \var{trap_enablers} and \var{flags} fields are mappings from signals
511+
The \var{traps} and \var{flags} fields are mappings from signals
512512
to either \constant{0} or \constant{1}.
513513

514514
The \var{Emin} and \var{Emax} fields are integers specifying the outer
@@ -839,7 +839,7 @@ \subsection{Working with threads \label{decimal-threads}}
839839
# Set applicationwide defaults for all threads about to be launched
840840
DefaultContext.prec=12
841841
DefaultContext.rounding=ROUND_DOWN
842-
DefaultContext.trap_enablers=dict.fromkeys(Signals, 0)
842+
DefaultContext.traps=dict.fromkeys(Signals, 0)
843843
setcontext(DefaultContext)
844844
845845
# Now start all of the threads

Lib/decimal.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,20 @@
7070
-Infinity
7171
>>> print dig / 0
7272
Infinity
73-
>>> getcontext().trap_enablers[DivisionByZero] = 1
73+
>>> getcontext().traps[DivisionByZero] = 1
7474
>>> print dig / 0
7575
Traceback (most recent call last):
7676
...
7777
...
7878
...
7979
DivisionByZero: x / 0
8080
>>> c = Context()
81-
>>> c.trap_enablers[InvalidOperation] = 0
81+
>>> c.traps[InvalidOperation] = 0
8282
>>> print c.flags[InvalidOperation]
8383
0
8484
>>> c.divide(Decimal(0), Decimal(0))
8585
Decimal("NaN")
86-
>>> c.trap_enablers[InvalidOperation] = 1
86+
>>> c.traps[InvalidOperation] = 1
8787
>>> print c.flags[InvalidOperation]
8888
1
8989
>>> c.flags[InvalidOperation] = 0
@@ -98,7 +98,7 @@
9898
>>> print c.flags[InvalidOperation]
9999
1
100100
>>> c.flags[InvalidOperation] = 0
101-
>>> c.trap_enablers[InvalidOperation] = 0
101+
>>> c.traps[InvalidOperation] = 0
102102
>>> print c.divide(Decimal(0), Decimal(0))
103103
NaN
104104
>>> print c.flags[InvalidOperation]
@@ -495,7 +495,11 @@ def __init__(self, value="0", context=None):
495495
self._int = value._int
496496
return
497497

498-
raise TypeError("Can't convert %r" % value)
498+
if isinstance(value, float):
499+
raise TypeError("Cannot convert float to Decimal. " +
500+
"First convert the float to a string")
501+
502+
raise TypeError("Cannot convert %r" % value)
499503

500504
def _convert_other(self, other):
501505
"""Convert other to Decimal.
@@ -2096,7 +2100,7 @@ class Context(object):
20962100
prec - precision (for use in rounding, division, square roots..)
20972101
rounding - rounding type. (how you round)
20982102
_rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
2099-
trap_enablers - If trap_enablers[exception] = 1, then the exception is
2103+
traps - If traps[exception] = 1, then the exception is
21002104
raised when it is caused. Otherwise, a value is
21012105
substituted in.
21022106
flags - When an exception is caused, flags[exception] is incremented.
@@ -2110,13 +2114,15 @@ class Context(object):
21102114
"""
21112115

21122116
def __init__(self, prec=None, rounding=None,
2113-
trap_enablers=None, flags=None,
2117+
traps=None, flags=[],
21142118
_rounding_decision=None,
21152119
Emin=None, Emax=None,
21162120
capitals=None, _clamp=0,
21172121
_ignored_flags=[]):
2118-
if flags is None:
2119-
flags = dict.fromkeys(Signals, 0)
2122+
if not isinstance(flags, dict):
2123+
flags = dict([(s,s in flags) for s in Signals])
2124+
if traps is not None and not isinstance(traps, dict):
2125+
traps = dict([(s,s in traps) for s in Signals])
21202126
for name, val in locals().items():
21212127
if val is None:
21222128
setattr(self, name, copy.copy(getattr(DefaultContext, name)))
@@ -2125,11 +2131,11 @@ def __init__(self, prec=None, rounding=None,
21252131
del self.self
21262132

21272133
def __repr__(self):
2128-
"""Show the current context in readable form, not in a form for eval()."""
2134+
"""Show the current context."""
21292135
s = []
2130-
s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d' % vars(self))
2131-
s.append('setflags=%r' % [f.__name__ for f, v in self.flags.items() if v])
2132-
s.append('settraps=%r' % [t.__name__ for t, v in self.trap_enablers.items() if v])
2136+
s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' % vars(self))
2137+
s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']')
2138+
s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']')
21332139
return ', '.join(s) + ')'
21342140

21352141
def clear_flags(self):
@@ -2139,7 +2145,7 @@ def clear_flags(self):
21392145

21402146
def copy(self):
21412147
"""Returns a copy from self."""
2142-
nc = Context(self.prec, self.rounding, self.trap_enablers, self.flags,
2148+
nc = Context(self.prec, self.rounding, self.traps, self.flags,
21432149
self._rounding_decision, self.Emin, self.Emax,
21442150
self.capitals, self._clamp, self._ignored_flags)
21452151
return nc
@@ -2159,7 +2165,7 @@ def _raise_error(self, condition, explanation = None, *args):
21592165
return error().handle(self, *args)
21602166

21612167
self.flags[error] += 1
2162-
if not self.trap_enablers[error]:
2168+
if not self.traps[error]:
21632169
#The errors define how to handle themselves.
21642170
return condition().handle(self, *args)
21652171

@@ -2946,13 +2952,10 @@ def _isnan(num):
29462952
# The default context prototype used by Context()
29472953
# Is mutable, so than new contexts can have different default values
29482954

2949-
_default_traps = dict.fromkeys(Signals, 0)
2950-
_default_traps.update({DivisionByZero:1, Overflow:1, InvalidOperation:1})
2951-
29522955
DefaultContext = Context(
29532956
prec=28, rounding=ROUND_HALF_EVEN,
2954-
trap_enablers=_default_traps,
2955-
flags=None,
2957+
traps=[DivisionByZero, Overflow, InvalidOperation],
2958+
flags=[],
29562959
_rounding_decision=ALWAYS_ROUND,
29572960
Emax=DEFAULT_MAX_EXPONENT,
29582961
Emin=DEFAULT_MIN_EXPONENT,
@@ -2964,20 +2967,17 @@ def _isnan(num):
29642967
# contexts and be able to reproduce results from other implementations
29652968
# of the spec.
29662969

2967-
_basic_traps = dict.fromkeys(Signals, 1)
2968-
_basic_traps.update({Inexact:0, Rounded:0, Subnormal:0})
2969-
29702970
BasicContext = Context(
29712971
prec=9, rounding=ROUND_HALF_UP,
2972-
trap_enablers=_basic_traps,
2973-
flags=None,
2972+
traps=[DivisionByZero, Overflow, InvalidOperation, Clamped, Underflow],
2973+
flags=[],
29742974
_rounding_decision=ALWAYS_ROUND,
29752975
)
29762976

29772977
ExtendedContext = Context(
29782978
prec=9, rounding=ROUND_HALF_EVEN,
2979-
trap_enablers=dict.fromkeys(Signals, 0),
2980-
flags=None,
2979+
traps=[],
2980+
flags=[],
29812981
_rounding_decision=ALWAYS_ROUND,
29822982
)
29832983

Lib/test/test_decimal.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
# Tests are built around these assumed context defaults
3939
DefaultContext.prec=9
4040
DefaultContext.rounding=ROUND_HALF_EVEN
41-
DefaultContext.trap_enablers=dict.fromkeys(Signals, 0)
41+
DefaultContext.traps=dict.fromkeys(Signals, 0)
4242
setcontext(DefaultContext)
4343

4444

@@ -105,8 +105,8 @@ class DecimalTest(unittest.TestCase):
105105
def setUp(self):
106106
global dir
107107
self.context = Context()
108-
for key in DefaultContext.trap_enablers.keys():
109-
DefaultContext.trap_enablers[key] = 1
108+
for key in DefaultContext.traps.keys():
109+
DefaultContext.traps[key] = 1
110110
self.ignore_list = ['#']
111111
# Basically, a # means return NaN InvalidOperation.
112112
# Different from a sNaN in trim
@@ -120,8 +120,8 @@ def setUp(self):
120120
def tearDown(self):
121121
"""Cleaning up enviroment."""
122122
# leaving context in original state
123-
for key in DefaultContext.trap_enablers.keys():
124-
DefaultContext.trap_enablers[key] = 0
123+
for key in DefaultContext.traps.keys():
124+
DefaultContext.traps[key] = 0
125125
return
126126

127127
def eval_file(self, file):
@@ -205,9 +205,9 @@ def FixQuotes(val):
205205
theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
206206

207207
for exception in Signals:
208-
self.context.trap_enablers[exception] = 1 #Catch these bugs...
208+
self.context.traps[exception] = 1 #Catch these bugs...
209209
for exception in theirexceptions:
210-
self.context.trap_enablers[exception] = 0
210+
self.context.traps[exception] = 0
211211
for i, val in enumerate(valstemp):
212212
if val.count("'") % 2 == 1:
213213
quote = 1 - quote
@@ -221,7 +221,7 @@ def FixQuotes(val):
221221
if fname in ('to_sci_string', 'to_eng_string'):
222222
if EXTENDEDERRORTEST:
223223
for error in theirexceptions:
224-
self.context.trap_enablers[error] = 1
224+
self.context.traps[error] = 1
225225
try:
226226
funct(self.context.create_decimal(v))
227227
except error:
@@ -231,7 +231,7 @@ def FixQuotes(val):
231231
(e, s, error))
232232
else:
233233
self.fail("Did not raise %s in %s" % (error, s))
234-
self.context.trap_enablers[error] = 0
234+
self.context.traps[error] = 0
235235
v = self.context.create_decimal(v)
236236
else:
237237
v = Decimal(v)
@@ -241,7 +241,7 @@ def FixQuotes(val):
241241

242242
if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
243243
for error in theirexceptions:
244-
self.context.trap_enablers[error] = 1
244+
self.context.traps[error] = 1
245245
try:
246246
funct(*vals)
247247
except error:
@@ -251,7 +251,7 @@ def FixQuotes(val):
251251
(e, s, error))
252252
else:
253253
self.fail("Did not raise %s in %s" % (error, s))
254-
self.context.trap_enablers[error] = 0
254+
self.context.traps[error] = 0
255255
try:
256256
result = str(funct(*vals))
257257
if fname == 'same_quantum':
@@ -263,7 +263,7 @@ def FixQuotes(val):
263263
raise
264264

265265
myexceptions = self.getexceptions()
266-
self.resetflags()
266+
self.context.clear_flags()
267267

268268
myexceptions.sort()
269269
theirexceptions.sort()
@@ -282,10 +282,6 @@ def getexceptions(self):
282282
L.append(exception)
283283
return L
284284

285-
def resetflags(self):
286-
for exception in Signals:
287-
self.context.flags[exception] = 0
288-
289285
def change_precision(self, prec):
290286
self.context.prec = prec
291287
def change_rounding_method(self, rounding):

0 commit comments

Comments
 (0)