diff -r 9d1a6a659977 Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c Sat Aug 18 12:46:14 2012 +0200 +++ b/Modules/_decimal/_decimal.c Sat Aug 18 14:28:50 2012 +0200 @@ -87,17 +87,86 @@ PyObject *global; } PyDecContextManagerObject; +typedef struct { + PyObject *PyDecSignalDict_Type; + PyObject *PyDecSignalDictMixin_Type; + /* Default module context */ + PyObject *module_context; + PyObject *default_context_template; + PyObject *basic_context_template; + PyObject *extended_context_template; + PyObject *DecimalException; + PyObject *DecimalTuple; + PyObject *SignalTuple; + PyObject *PyDecContextManager_Type; + PyObject *Rational; + PyObject *PyDec_Type; + PyObject *PyDecContext_Type; +} _decimal_state; + + +#define _decimal__state(o) ((_decimal_state *)PyModule_GetState(o)) + +static int +_decimal__clear(PyObject *m) +{ + _decimal_state *state = _decimal__state(m); + Py_CLEAR(state->DecimalTuple); + Py_CLEAR(state->PyDecSignalDict_Type); + Py_CLEAR(state->PyDecSignalDictMixin_Type); + Py_CLEAR(state->module_context); + Py_CLEAR(state->default_context_template); + Py_CLEAR(state->basic_context_template); + Py_CLEAR(state->extended_context_template); + Py_CLEAR(state->DecimalException); + Py_CLEAR(state->SignalTuple); + Py_CLEAR(state->PyDecContextManager_Type); + Py_CLEAR(state->Rational); + Py_CLEAR(state->PyDec_Type); + Py_CLEAR(state->PyDecContext_Type); + return 0; +} + +static int +_decimal__traverse(PyObject *m, visitproc visit, void *arg) +{ + _decimal_state *state = _decimal__state(m); + Py_VISIT(state->DecimalTuple); + Py_VISIT(state->PyDecSignalDict_Type); + Py_VISIT(state->PyDecSignalDictMixin_Type); + Py_VISIT(state->module_context); + Py_VISIT(state->default_context_template); + Py_VISIT(state->basic_context_template); + Py_VISIT(state->extended_context_template); + Py_VISIT(state->DecimalException); + Py_VISIT(state->SignalTuple); + Py_VISIT(state->PyDecContextManager_Type); + Py_VISIT(state->Rational); + Py_VISIT(state->PyDec_Type); + Py_VISIT(state->PyDecContext_Type); + return 0; +} + +static void +_decimal__free(void *m) +{ + _decimal__clear((PyObject *)m); +} + +static PyModuleDef _decimal_module; + +#define _decimal_state_global ((_decimal_state *)PyModule_GetState(PyState_FindModule(&_decimal_module))) + #undef MPD #undef CTX -static PyTypeObject PyDec_Type; -static PyTypeObject *PyDecSignalDict_Type; -static PyTypeObject PyDecContext_Type; -static PyTypeObject PyDecContextManager_Type; -#define PyDec_CheckExact(v) (Py_TYPE(v) == &PyDec_Type) -#define PyDec_Check(v) PyObject_TypeCheck(v, &PyDec_Type) -#define PyDecSignalDict_Check(v) (Py_TYPE(v) == PyDecSignalDict_Type) -#define PyDecContext_Check(v) PyObject_TypeCheck(v, &PyDecContext_Type) +#define PyDec_CheckExact(v) (Py_TYPE(v) == (PyTypeObject *)_decimal_state_global->PyDec_Type) +#define PyDec_Check(v) PyObject_TypeCheck(v,\ + (PyTypeObject *)_decimal_state_global->PyDec_Type) +#define PyDecSignalDict_Check(v) (Py_TYPE(v) ==\ + (PyTypeObject *)_decimal_state_global->PyDecSignalDict_Type) +#define PyDecContext_Check(v) PyObject_TypeCheck(v,\ + (PyTypeObject *)_decimal_state_global->PyDecContext_Type) #define MPD(v) (&((PyDecObject *)v)->dec) #define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags) #define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags) @@ -120,22 +189,19 @@ } -#ifdef WITHOUT_THREADS -/* Default module context */ -static PyObject *module_context = NULL; -#else +#ifndef WITHOUT_THREADS /* Key for thread state dictionary */ -static PyObject *tls_context_key = NULL; +static PyObject *tls_context_key; /* Invariant: NULL or the most recently accessed thread local context */ static PyDecContextObject *cached_context = NULL; #endif /* Template for creating new thread contexts, calling Context() without * arguments and initializing the module_context on first access. */ -static PyObject *default_context_template = NULL; + /* Basic and extended context templates */ -static PyObject *basic_context_template = NULL; -static PyObject *extended_context_template = NULL; + + /* Error codes for functions that return signals or conditions */ @@ -151,7 +217,7 @@ } DecCondMap; /* Top level Exception; inherits from ArithmeticError */ -static PyObject *DecimalException = NULL; + /* Exceptions that correspond to IEEE signals */ #define SUBNORMAL 5 @@ -526,11 +592,11 @@ return SIGNAL_MAP_LEN; } -static PyObject *SignalTuple; + static PyObject * signaldict_iter(PyObject *self UNUSED) { - return PyTuple_Type.tp_iter(SignalTuple); + return PyTuple_Type.tp_iter(_decimal_state_global->SignalTuple); } static PyObject * @@ -637,63 +703,37 @@ return flags_as_dict(SdFlags(self)); } - -static PyMappingMethods signaldict_as_mapping = { - (lenfunc)signaldict_len, /* mp_length */ - (binaryfunc)signaldict_getitem, /* mp_subscript */ - (objobjargproc)signaldict_setitem /* mp_ass_subscript */ -}; - static PyMethodDef signaldict_methods[] = { { "copy", (PyCFunction)signaldict_copy, METH_NOARGS, NULL}, {NULL, NULL} }; - -static PyTypeObject PyDecSignalDictMixin_Type = -{ - PyVarObject_HEAD_INIT(0, 0) - "decimal.SignalDictMixin", /* tp_name */ - sizeof(PyDecSignalDictObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc) 0, /* tp_getattr */ - (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc) signaldict_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - &signaldict_as_mapping, /* tp_as_mapping */ - PyObject_HashNotImplemented, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - (setattrofunc) 0, /* tp_setattro */ - (PyBufferProcs *) 0, /* tp_as_buffer */ +static PyType_Slot PyDecSignalDictMixin_Type_slots[] = { + {Py_tp_repr, (reprfunc) signaldict_repr}, + {Py_mp_length, (lenfunc)signaldict_len}, + {Py_mp_subscript, (binaryfunc)signaldict_getitem}, + {Py_mp_ass_subscript, (objobjargproc)signaldict_setitem}, + {Py_tp_hash, PyObject_HashNotImplemented}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_richcompare, signaldict_richcompare}, + {Py_tp_iter, (getiterfunc)signaldict_iter}, + {Py_tp_methods, signaldict_methods}, + {Py_tp_init, (initproc)signaldict_init}, + {Py_tp_new, PyType_GenericNew}, + {0, 0} +}; + +static PyType_Spec PyDecSignalDictMixin_Type_spec = { + "decimal.SignalDictMixin", + sizeof(PyDecSignalDictObject), + 0, Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE| - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - signaldict_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)signaldict_iter, /* tp_iter */ - 0, /* tp_iternext */ - signaldict_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)signaldict_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + Py_TPFLAGS_HAVE_GC, + PyDecSignalDictMixin_Type_slots, }; + /******************************************************************************/ /* Context Object, Part 1 */ /******************************************************************************/ @@ -1151,8 +1191,10 @@ PyDecContextObject *self = NULL; mpd_context_t *ctx; - if (type == &PyDecContext_Type) { - self = PyObject_New(PyDecContextObject, &PyDecContext_Type); + if (type == (PyTypeObject *)_decimal_state_global->PyDecContext_Type) { + self = PyObject_New(PyDecContextObject, type); + if(self) + Py_INCREF(type); } else { self = (PyDecContextObject *)type->tp_alloc(type, 0); @@ -1162,13 +1204,13 @@ return NULL; } - self->traps = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL); + self->traps = PyObject_CallObject(_decimal_state_global->PyDecSignalDict_Type, NULL); if (self->traps == NULL) { self->flags = NULL; Py_DECREF(self); return NULL; } - self->flags = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL); + self->flags = PyObject_CallObject(_decimal_state_global->PyDecSignalDict_Type, NULL); if (self->flags == NULL) { Py_DECREF(self); return NULL; @@ -1176,8 +1218,8 @@ ctx = CTX(self); - if (default_context_template) { - *ctx = *CTX(default_context_template); + if (_decimal_state_global->default_context_template) { + *ctx = *CTX(_decimal_state_global->default_context_template); } else { *ctx = dflt_ctx; @@ -1197,6 +1239,7 @@ static void context_dealloc(PyDecContextObject *self) { + PyTypeObject *type = Py_TYPE(self); #ifndef WITHOUT_THREADS if (self == cached_context) { cached_context = NULL; @@ -1204,7 +1247,10 @@ #endif Py_XDECREF(self->traps); Py_XDECREF(self->flags); - Py_TYPE(self)->tp_free(self); + type->tp_free(self); + if((void *)type->tp_dealloc == (void *)context_dealloc) { + Py_DECREF(type); + } } static int @@ -1394,7 +1440,7 @@ goto error; } - context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + context = PyObject_CallObject(_decimal_state_global->PyDecContext_Type, NULL); if (context == NULL) { return NULL; } @@ -1416,7 +1462,7 @@ { PyObject *copy; - copy = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + copy = PyObject_CallObject(_decimal_state_global->PyDecContext_Type, NULL); if (copy == NULL) { return NULL; } @@ -1508,16 +1554,16 @@ * from the DefaultContext when it is first accessed. This * complicates the code and has a speed penalty of 1-2%. */ if (module_context_set) { - return module_context; - } - - *CTX(module_context) = *CTX(default_context_template); - CTX(module_context)->status = 0; - CTX(module_context)->newtrap = 0; - CtxCaps(module_context) = CtxCaps(default_context_template); + return _decimal_state_global->module_context; + } + + *CTX(_decimal_state_global->module_context) = *CTX(_decimal_state_global->default_context_template); + CTX(_decimal_state_global->module_context)->status = 0; + CTX(_decimal_state_global->module_context)->newtrap = 0; + CtxCaps(_decimal_state_global->module_context) = CtxCaps(_decimal_state_global->default_context_template); module_context_set = 1; - return module_context; + return _decimal_state_global->module_context; } /* ctxobj := borrowed reference to the current context */ @@ -1548,9 +1594,9 @@ /* If the new context is one of the templates, make a copy. * This is the current behavior of decimal.py. */ - if (v == default_context_template || - v == basic_context_template || - v == extended_context_template) { + if (v == _decimal_state_global->default_context_template || + v == _decimal_state_global->basic_context_template || + v == _decimal_state_global->extended_context_template) { v = context_copy(v, NULL); if (v == NULL) { return NULL; @@ -1561,8 +1607,8 @@ Py_INCREF(v); } - Py_XDECREF(module_context); - module_context = v; + Py_XDECREF(_decimal_state_global->module_context); + _decimal_state_global->module_context = v; module_context_set = 1; Py_RETURN_NONE; } @@ -1600,7 +1646,7 @@ } /* Set up a new thread local context. */ - tl_context = context_copy(default_context_template, NULL); + tl_context = context_copy(_decimal_state_global->default_context_template, NULL); if (tl_context == NULL) { return NULL; } @@ -1687,9 +1733,9 @@ /* If the new context is one of the templates, make a copy. * This is the current behavior of decimal.py. */ - if (v == default_context_template || - v == basic_context_template || - v == extended_context_template) { + if (v == _decimal_state_global->default_context_template || + v == _decimal_state_global->basic_context_template || + v == _decimal_state_global->extended_context_template) { v = context_copy(v, NULL); if (v == NULL) { return NULL; @@ -1729,10 +1775,11 @@ CONTEXT_CHECK_VA(local); self = PyObject_New(PyDecContextManagerObject, - &PyDecContextManager_Type); + (PyTypeObject *)_decimal_state_global->PyDecContextManager_Type); if (self == NULL) { return NULL; } + Py_INCREF(_decimal_state_global->PyDecContextManager_Type); self->local = context_copy(local, NULL); if (self->local == NULL) { @@ -1749,8 +1796,12 @@ static void ctxmanager_dealloc(PyDecContextManagerObject *self) { + PyTypeObject *type = Py_TYPE(self); Py_XDECREF(self->local); Py_XDECREF(self->global); + if((void *)type->tp_dealloc == (void *)ctxmanager_dealloc) { + Py_DECREF(type); + } PyObject_Del(self); } @@ -1791,38 +1842,22 @@ {NULL, NULL} }; -static PyTypeObject PyDecContextManager_Type = -{ - PyVarObject_HEAD_INIT(NULL, 0) - "decimal.ContextManager", /* tp_name */ - sizeof(PyDecContextManagerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) ctxmanager_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc) 0, /* tp_getattr */ - (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc) 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */ - (setattrofunc) 0, /* tp_setattro */ - (PyBufferProcs *) 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - ctxmanager_methods, /* tp_methods */ +static PyType_Slot PyDecContextManager_Type_slots[] = { + {Py_tp_dealloc, (destructor) ctxmanager_dealloc}, + {Py_tp_getattro, (getattrofunc) PyObject_GenericGetAttr}, + {Py_tp_methods, ctxmanager_methods}, + {0, 0} }; +static PyType_Spec PyDecContextManager_Type_spec = { + "decimal.ContextManager", + sizeof(PyDecContextManagerObject), + 0, + Py_TPFLAGS_DEFAULT, + PyDecContextManager_Type_slots, +}; + + /******************************************************************************/ /* New Decimal Object */ @@ -1833,8 +1868,10 @@ { PyDecObject *dec; - if (type == &PyDec_Type) { - dec = PyObject_New(PyDecObject, &PyDec_Type); + if (type == (PyTypeObject *)_decimal_state_global->PyDec_Type) { + dec = PyObject_New(PyDecObject, type); + if(dec) + Py_INCREF(type); } else { dec = (PyDecObject *)type->tp_alloc(type, 0); @@ -1854,13 +1891,17 @@ return (PyObject *)dec; } -#define dec_alloc() PyDecType_New(&PyDec_Type) +#define dec_alloc() PyDecType_New((PyTypeObject *)_decimal_state_global->PyDec_Type) static void dec_dealloc(PyObject *dec) { + PyTypeObject *type = Py_TYPE(dec); mpd_del(MPD(dec)); - Py_TYPE(dec)->tp_free(dec); + type->tp_free(dec); + if((void *)type->tp_dealloc == (void *)dec_dealloc) { + Py_DECREF(type); + } } @@ -2210,7 +2251,8 @@ mpd_context_t maxctx; - assert(PyType_IsSubtype(type, &PyDec_Type)); + assert(PyType_IsSubtype(type, + (PyTypeObject *)_decimal_state_global->PyDec_Type)); if (PyLong_Check(v)) { return PyDecType_FromLongExact(type, v, context); @@ -2550,36 +2592,36 @@ } #define PyDec_FromCString(str, context) \ - PyDecType_FromCString(&PyDec_Type, str, context) + PyDecType_FromCString((PyTypeObject *)_decimal_state_global->PyDec_Type, str, context) #define PyDec_FromCStringExact(str, context) \ - PyDecType_FromCStringExact(&PyDec_Type, str, context) + PyDecType_FromCStringExact((PyTypeObject *)_decimal_state_global->PyDec_Type, str, context) #define PyDec_FromUnicode(unicode, context) \ - PyDecType_FromUnicode(&PyDec_Type, unicode, context) + PyDecType_FromUnicode((PyTypeObject *)_decimal_state_global->PyDec_Type, unicode, context) #define PyDec_FromUnicodeExact(unicode, context) \ - PyDecType_FromUnicodeExact(&PyDec_Type, unicode, context) + PyDecType_FromUnicodeExact((PyTypeObject *)_decimal_state_global->PyDec_Type, unicode, context) #define PyDec_FromUnicodeExactWS(unicode, context) \ - PyDecType_FromUnicodeExactWS(&PyDec_Type, unicode, context) + PyDecType_FromUnicodeExactWS((PyTypeObject *)_decimal_state_global->PyDec_Type, unicode, context) #define PyDec_FromSsize(v, context) \ - PyDecType_FromSsize(&PyDec_Type, v, context) + PyDecType_FromSsize((PyTypeObject *)_decimal_state_global->PyDec_Type, v, context) #define PyDec_FromSsizeExact(v, context) \ - PyDecType_FromSsizeExact(&PyDec_Type, v, context) + PyDecType_FromSsizeExact((PyTypeObject *)_decimal_state_global->PyDec_Type, v, context) #define PyDec_FromLong(pylong, context) \ - PyDecType_FromLong(&PyDec_Type, pylong, context) + PyDecType_FromLong((PyTypeObject *)_decimal_state_global->PyDec_Type, pylong, context) #define PyDec_FromLongExact(pylong, context) \ - PyDecType_FromLongExact(&PyDec_Type, pylong, context) + PyDecType_FromLongExact((PyTypeObject *)_decimal_state_global->PyDec_Type, pylong, context) #define PyDec_FromFloat(pyfloat, context) \ - PyDecType_FromFloat(&PyDec_Type, pyfloat, context) + PyDecType_FromFloat((PyTypeObject *)_decimal_state_global->PyDec_Type, pyfloat, context) #define PyDec_FromFloatExact(pyfloat, context) \ - PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context) + PyDecType_FromFloatExact((PyTypeObject *)_decimal_state_global->PyDec_Type, pyfloat, context) #define PyDec_FromSequence(sequence, context) \ - PyDecType_FromSequence(&PyDec_Type, sequence, context) + PyDecType_FromSequence((PyTypeObject *)_decimal_state_global->PyDec_Type, sequence, context) #define PyDec_FromSequenceExact(sequence, context) \ - PyDecType_FromSequenceExact(&PyDec_Type, sequence, context) + PyDecType_FromSequenceExact((PyTypeObject *)_decimal_state_global->PyDec_Type, sequence, context) /* class method */ static PyObject * @@ -2842,7 +2884,7 @@ /******************************************************************************/ /* Convert rationals for comparison */ -static PyObject *Rational = NULL; + static PyObject * multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context) { @@ -2969,7 +3011,7 @@ *wcmp = Py_NotImplemented; } } - else if (PyObject_IsInstance(w, Rational)) { + else if (PyObject_IsInstance(w, _decimal_state_global->Rational)) { *wcmp = numerator_as_decimal(w, context); if (*wcmp && !mpd_isspecial(MPD(v))) { *vcmp = multiply_by_denominator(v, w, context); @@ -3416,7 +3458,6 @@ } } -PyObject *DecimalTuple = NULL; /* Return the DecimalTuple representation of a PyDecObject. */ static PyObject * PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED) @@ -3499,7 +3540,7 @@ } } - result = PyObject_CallFunctionObjArgs(DecimalTuple, + result = PyObject_CallFunctionObjArgs(_decimal_state_global->DecimalTuple, sign, coeff, expt, NULL); out: @@ -4445,43 +4486,6 @@ {NULL} }; -static PyNumberMethods dec_number_methods = -{ - (binaryfunc) nm_mpd_qadd, - (binaryfunc) nm_mpd_qsub, - (binaryfunc) nm_mpd_qmul, - (binaryfunc) nm_mpd_qrem, - (binaryfunc) nm_mpd_qdivmod, - (ternaryfunc) nm_mpd_qpow, - (unaryfunc) nm_mpd_qminus, - (unaryfunc) nm_mpd_qplus, - (unaryfunc) nm_mpd_qabs, - (inquiry) nm_nonzero, - (unaryfunc) 0, /* no bit-complement */ - (binaryfunc) 0, /* no shiftl */ - (binaryfunc) 0, /* no shiftr */ - (binaryfunc) 0, /* no bit-and */ - (binaryfunc) 0, /* no bit-xor */ - (binaryfunc) 0, /* no bit-ior */ - (unaryfunc) nm_dec_as_long, - 0, /* nb_reserved */ - (unaryfunc) PyDec_AsFloat, - 0, /* binaryfunc nb_inplace_add; */ - 0, /* binaryfunc nb_inplace_subtract; */ - 0, /* binaryfunc nb_inplace_multiply; */ - 0, /* binaryfunc nb_inplace_remainder; */ - 0, /* ternaryfunc nb_inplace_power; */ - 0, /* binaryfunc nb_inplace_lshift; */ - 0, /* binaryfunc nb_inplace_rshift; */ - 0, /* binaryfunc nb_inplace_and; */ - 0, /* binaryfunc nb_inplace_xor; */ - 0, /* binaryfunc nb_inplace_or; */ - (binaryfunc) nm_mpd_qdivint, /* binaryfunc nb_floor_divide; */ - (binaryfunc) nm_mpd_qdiv, /* binaryfunc nb_true_divide; */ - 0, /* binaryfunc nb_inplace_floor_divide; */ - 0, /* binaryfunc nb_inplace_true_divide; */ -}; - static PyMethodDef dec_methods [] = { /* Unary arithmetic functions, optional context arg */ @@ -4573,51 +4577,46 @@ { NULL, NULL, 1 } }; -static PyTypeObject PyDec_Type = -{ - PyVarObject_HEAD_INIT(NULL, 0) - "decimal.Decimal", /* tp_name */ - sizeof(PyDecObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) dec_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc) 0, /* tp_getattr */ - (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc) dec_repr, /* tp_repr */ - &dec_number_methods, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc) dec_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) dec_str, /* tp_str */ - (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */ - (setattrofunc) 0, /* tp_setattro */ - (PyBufferProcs *) 0, /* tp_as_buffer */ +static PyType_Slot PyDec_Type_slots[] = { + {Py_tp_dealloc, (destructor) dec_dealloc}, + {Py_tp_repr, (reprfunc) dec_repr}, + {Py_nb_add, (binaryfunc) nm_mpd_qadd}, + {Py_nb_subtract, (binaryfunc) nm_mpd_qsub}, + {Py_nb_multiply, (binaryfunc) nm_mpd_qmul}, + {Py_nb_remainder, (binaryfunc) nm_mpd_qrem}, + {Py_nb_divmod, (binaryfunc) nm_mpd_qdivmod}, + {Py_nb_power, (ternaryfunc) nm_mpd_qpow}, + {Py_nb_negative, (unaryfunc) nm_mpd_qminus}, + {Py_nb_positive, (unaryfunc) nm_mpd_qplus}, + {Py_nb_absolute, (unaryfunc) nm_mpd_qabs}, + {Py_nb_bool, (inquiry) nm_nonzero}, + {Py_nb_int, (unaryfunc) nm_dec_as_long}, + {Py_nb_float, (unaryfunc) PyDec_AsFloat}, + {Py_nb_true_divide, (binaryfunc) nm_mpd_qdiv}, + {Py_nb_floor_divide, nm_mpd_qdivint}, + {Py_tp_hash, (hashfunc) dec_hash}, + {Py_tp_str, (reprfunc) dec_str}, + {Py_tp_getattro, (getattrofunc) PyObject_GenericGetAttr}, + {Py_tp_doc, doc_decimal}, + {Py_tp_richcompare, dec_richcompare}, + {Py_tp_methods, dec_methods}, + {Py_tp_getset, dec_getsets}, + {Py_tp_new, dec_new}, + {Py_tp_free, PyObject_Del}, + {0, 0} +}; + +static PyType_Spec PyDec_Type_spec = { + "decimal.Decimal", + sizeof(PyDecObject), + 0, (Py_TPFLAGS_DEFAULT| - Py_TPFLAGS_BASETYPE), /* tp_flags */ - doc_decimal, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - dec_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - dec_methods, /* tp_methods */ - 0, /* tp_members */ - dec_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - dec_new, /* tp_new */ - PyObject_Del, /* tp_free */ + Py_TPFLAGS_BASETYPE), + PyDec_Type_slots, }; + /******************************************************************************/ /* Context Object, Part 2 */ /******************************************************************************/ @@ -5259,53 +5258,33 @@ { "copy", (PyCFunction)context_copy, METH_NOARGS, doc_ctx_copy }, { "create_decimal", ctx_create_decimal, METH_VARARGS, doc_ctx_create_decimal }, { "create_decimal_from_float", ctx_from_float, METH_O, doc_ctx_create_decimal_from_float }, - { NULL, NULL, 1 } }; -static PyTypeObject PyDecContext_Type = -{ - PyVarObject_HEAD_INIT(NULL, 0) - "decimal.Context", /* tp_name */ - sizeof(PyDecContextObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) context_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc) 0, /* tp_getattr */ - (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc) context_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc) 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) context_repr, /* tp_str */ - (getattrofunc) context_getattr, /* tp_getattro */ - (setattrofunc) context_setattr, /* tp_setattro */ - (PyBufferProcs *) 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - doc_context, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - context_methods, /* tp_methods */ - 0, /* tp_members */ - context_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - context_init, /* tp_init */ - 0, /* tp_alloc */ - context_new, /* tp_new */ - PyObject_Del, /* tp_free */ +static PyType_Slot PyDecContext_Type_slots[] = { + {Py_tp_dealloc, (destructor) context_dealloc}, + {Py_tp_repr, (reprfunc) context_repr}, + {Py_tp_str, (reprfunc) context_repr}, + {Py_tp_getattro, (getattrofunc) context_getattr}, + {Py_tp_setattro, (setattrofunc) context_setattr}, + {Py_tp_doc, doc_context}, + {Py_tp_methods, context_methods}, + {Py_tp_getset, context_getsets}, + {Py_tp_init, context_init}, + {Py_tp_new, context_new}, + {Py_tp_free, PyObject_Del}, + {0, 0} }; +static PyType_Spec PyDecContext_Type_spec = { + "decimal.Context", + sizeof(PyDecContextObject), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + PyDecContext_Type_slots, +}; + + static PyMethodDef _decimal_methods [] = { @@ -5322,12 +5301,12 @@ PyModuleDef_HEAD_INIT, "decimal", doc__decimal, - -1, + sizeof(_decimal_state), _decimal_methods, NULL, - NULL, - NULL, - NULL + _decimal__traverse, + _decimal__clear, + _decimal__free }; struct ssize_constmap { const char *name; mpd_ssize_t val; }; @@ -5402,7 +5381,12 @@ struct ssize_constmap *ssize_cm; struct int_constmap *int_cm; int i; - + _decimal_state *state; + + /* Create the module */ + ASSIGN_PTR(m, PyModule_Create(&_decimal_module)); + PyState_AddModule(m, &_decimal_module); + state = _decimal__state(m); /* Init libmpdec */ mpd_traphandler = dec_traphandler; @@ -5412,21 +5396,31 @@ mpd_free = PyMem_Free; mpd_setminalloc(_Py_DEC_MINALLOC); + state->PyDec_Type = PyType_FromSpec(&PyDec_Type_spec); + state->PyDecContext_Type = + PyType_FromSpec(&PyDecContext_Type_spec); + state->PyDecContextManager_Type = + PyType_FromSpec(&PyDecContextManager_Type_spec); + state->PyDecSignalDictMixin_Type = + PyType_FromSpec(&PyDecSignalDictMixin_Type_spec); /* Init types */ - PyDec_Type.tp_base = &PyBaseObject_Type; - PyDecContext_Type.tp_base = &PyBaseObject_Type; - PyDecContextManager_Type.tp_base = &PyBaseObject_Type; - PyDecSignalDictMixin_Type.tp_base = &PyBaseObject_Type; - - CHECK_INT(PyType_Ready(&PyDec_Type)); - CHECK_INT(PyType_Ready(&PyDecContext_Type)); - CHECK_INT(PyType_Ready(&PyDecSignalDictMixin_Type)); - CHECK_INT(PyType_Ready(&PyDecContextManager_Type)); + ((PyTypeObject *)state->PyDec_Type)->tp_base = &PyBaseObject_Type; + ((PyTypeObject *)state->PyDecContext_Type)->tp_base = &PyBaseObject_Type; + ((PyTypeObject *)state->PyDecContextManager_Type)->tp_base = &PyBaseObject_Type; + ((PyTypeObject *)state->PyDecSignalDictMixin_Type)->tp_base = &PyBaseObject_Type; + + if(!state->PyDec_Type + || !state->PyDecContext_Type + || !state->PyDecContextManager_Type + || !state->PyDecSignalDictMixin_Type) { + goto error; + } ASSIGN_PTR(obj, PyUnicode_FromString("decimal")); - CHECK_INT(PyDict_SetItemString(PyDec_Type.tp_dict, "__module__", obj)); - CHECK_INT(PyDict_SetItemString(PyDecContext_Type.tp_dict, + CHECK_INT(PyDict_SetItemString(((PyTypeObject *)state->PyDec_Type)->tp_dict, + "__module__", obj)); + CHECK_INT(PyDict_SetItemString(((PyTypeObject *)state->PyDecContext_Type)->tp_dict, "__module__", obj)); Py_CLEAR(obj); @@ -5436,27 +5430,28 @@ ASSIGN_PTR(Number, PyObject_GetAttrString(numbers, "Number")); /* Register Decimal with the Number abstract base class */ ASSIGN_PTR(obj, PyObject_CallMethod(Number, "register", "(O)", - (PyObject *)&PyDec_Type)); + state->PyDec_Type)); Py_CLEAR(obj); /* Rational is a global variable used for fraction comparisons. */ - ASSIGN_PTR(Rational, PyObject_GetAttrString(numbers, "Rational")); + ASSIGN_PTR(state->Rational, PyObject_GetAttrString(numbers, "Rational")); /* Done with numbers, Number */ Py_CLEAR(numbers); Py_CLEAR(Number); /* DecimalTuple */ ASSIGN_PTR(collections, PyImport_ImportModule("collections")); - ASSIGN_PTR(DecimalTuple, PyObject_CallMethod(collections, + ASSIGN_PTR(state->DecimalTuple, + PyObject_CallMethod(collections, "namedtuple", "(ss)", "DecimalTuple", "sign digits exponent")); /* MutableMapping */ ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections, "MutableMapping")); /* Create SignalDict type */ - ASSIGN_PTR(PyDecSignalDict_Type, - (PyTypeObject *)PyObject_CallFunction( + ASSIGN_PTR(state->PyDecSignalDict_Type, + PyObject_CallFunction( (PyObject *)&PyType_Type, "s(OO){}", - "SignalDict", &PyDecSignalDictMixin_Type, + "SignalDict", state->PyDecSignalDictMixin_Type, MutableMapping)); /* Done with collections, MutableMapping */ @@ -5464,29 +5459,27 @@ Py_CLEAR(MutableMapping); - /* Create the module */ - ASSIGN_PTR(m, PyModule_Create(&_decimal_module)); /* Add types to the module */ - Py_INCREF(&PyDec_Type); - CHECK_INT(PyModule_AddObject(m, "Decimal", (PyObject *)&PyDec_Type)); - Py_INCREF(&PyDecContext_Type); + Py_INCREF(state->PyDec_Type); + CHECK_INT(PyModule_AddObject(m, "Decimal", state->PyDec_Type)); + Py_INCREF(state->PyDecContext_Type); CHECK_INT(PyModule_AddObject(m, "Context", - (PyObject *)&PyDecContext_Type)); - Py_INCREF(DecimalTuple); - CHECK_INT(PyModule_AddObject(m, "DecimalTuple", DecimalTuple)); + state->PyDecContext_Type)); + Py_INCREF(state->DecimalTuple); + CHECK_INT(PyModule_AddObject(m, "DecimalTuple", state->DecimalTuple)); /* Create top level exception */ - ASSIGN_PTR(DecimalException, PyErr_NewException( + ASSIGN_PTR(state->DecimalException, PyErr_NewException( "decimal.DecimalException", PyExc_ArithmeticError, NULL)); - Py_INCREF(DecimalException); - CHECK_INT(PyModule_AddObject(m, "DecimalException", DecimalException)); + Py_INCREF(state->DecimalException); + CHECK_INT(PyModule_AddObject(m, "DecimalException", state->DecimalException)); /* Create signal tuple */ - ASSIGN_PTR(SignalTuple, PyTuple_New(SIGNAL_MAP_LEN)); + ASSIGN_PTR(state->SignalTuple, PyTuple_New(SIGNAL_MAP_LEN)); /* Add exceptions that correspond to IEEE signals */ for (i = SIGNAL_MAP_LEN-1; i >= 0; i--) { @@ -5496,10 +5489,10 @@ switch (cm->flag) { case MPD_Float_operation: - base = PyTuple_Pack(2, DecimalException, PyExc_TypeError); + base = PyTuple_Pack(2, state->DecimalException, PyExc_TypeError); break; case MPD_Division_by_zero: - base = PyTuple_Pack(2, DecimalException, PyExc_ZeroDivisionError); + base = PyTuple_Pack(2, state->DecimalException, PyExc_ZeroDivisionError); break; case MPD_Overflow: base = PyTuple_Pack(2, signal_map[INEXACT].ex, @@ -5511,7 +5504,7 @@ signal_map[SUBNORMAL].ex); break; default: - base = PyTuple_Pack(1, DecimalException); + base = PyTuple_Pack(1, state->DecimalException); break; } @@ -5528,7 +5521,7 @@ /* add to signal tuple */ Py_INCREF(cm->ex); - PyTuple_SET_ITEM(SignalTuple, i, cm->ex); + PyTuple_SET_ITEM(state->SignalTuple, i, cm->ex); } /* @@ -5560,16 +5553,16 @@ /* Init default context template first */ - ASSIGN_PTR(default_context_template, - PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL)); - Py_INCREF(default_context_template); + ASSIGN_PTR(state->default_context_template, + PyObject_CallObject(state->PyDecContext_Type, NULL)); + Py_INCREF(state->default_context_template); CHECK_INT(PyModule_AddObject(m, "DefaultContext", - default_context_template)); + state->default_context_template)); #ifdef WITHOUT_THREADS /* Init module context */ - ASSIGN_PTR(module_context, - PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL)); + ASSIGN_PTR(state->module_context, + PyObject_CallObject(state->PyDecContext_Type, NULL)); Py_INCREF(Py_False); CHECK_INT(PyModule_AddObject(m, "HAVE_THREADS", Py_False)); #else @@ -5579,20 +5572,20 @@ #endif /* Init basic context template */ - ASSIGN_PTR(basic_context_template, - PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL)); - init_basic_context(basic_context_template); - Py_INCREF(basic_context_template); + ASSIGN_PTR(state->basic_context_template, + PyObject_CallObject(state->PyDecContext_Type, NULL)); + init_basic_context(state->basic_context_template); + Py_INCREF(state->basic_context_template); CHECK_INT(PyModule_AddObject(m, "BasicContext", - basic_context_template)); + state->basic_context_template)); /* Init extended context template */ - ASSIGN_PTR(extended_context_template, - PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL)); - init_extended_context(extended_context_template); - Py_INCREF(extended_context_template); + ASSIGN_PTR(state->extended_context_template, + PyObject_CallObject(state->PyDecContext_Type, NULL)); + init_extended_context(state->extended_context_template); + Py_INCREF(state->extended_context_template); CHECK_INT(PyModule_AddObject(m, "ExtendedContext", - extended_context_template)); + state->extended_context_template)); /* Init mpd_ssize_t constants */ @@ -5619,19 +5612,19 @@ Py_CLEAR(obj); /* GCOV_NOT_REACHED */ Py_CLEAR(numbers); /* GCOV_NOT_REACHED */ Py_CLEAR(Number); /* GCOV_NOT_REACHED */ - Py_CLEAR(Rational); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->Rational); /* GCOV_NOT_REACHED */ Py_CLEAR(collections); /* GCOV_NOT_REACHED */ Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */ - Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */ - Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->SignalTuple); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->DecimalTuple); /* GCOV_NOT_REACHED */ #ifdef WITHOUT_THREADS - Py_CLEAR(module_context); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->module_context); /* GCOV_NOT_REACHED */ #else - Py_CLEAR(default_context_template); /* GCOV_NOT_REACHED */ Py_CLEAR(tls_context_key); /* GCOV_NOT_REACHED */ #endif - Py_CLEAR(basic_context_template); /* GCOV_NOT_REACHED */ - Py_CLEAR(extended_context_template); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->default_context_template); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->basic_context_template); /* GCOV_NOT_REACHED */ + Py_CLEAR(state->extended_context_template); /* GCOV_NOT_REACHED */ Py_CLEAR(m); /* GCOV_NOT_REACHED */ return NULL; /* GCOV_NOT_REACHED */