From 5a20bf0c19e7ef816922cd4ce60a1775c86d70b0 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 21 Aug 2025 06:51:39 +0300 Subject: [PATCH] gh-73487: Convert _decimal to use Argument Clinic (part 6) --- Makefile.pre.in | 2 +- Modules/_decimal/_decimal.c | 345 +++++++++++++++------- Modules/_decimal/clinic/_decimal.c.h | 416 ++++++++++++++++++++++++++- Modules/_decimal/docstrings.h | 129 --------- PCbuild/_decimal.vcxproj | 1 - PCbuild/_decimal.vcxproj.filters | 3 - 6 files changed, 659 insertions(+), 237 deletions(-) delete mode 100644 Modules/_decimal/docstrings.h diff --git a/Makefile.pre.in b/Makefile.pre.in index bcf19654adfb35..5b2799bdb94ad5 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -3355,7 +3355,7 @@ MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/uni MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h MODULE__CTYPES_TEST_DEPS=$(srcdir)/Modules/_ctypes/_ctypes_test_generated.c.h MODULE__CTYPES_MALLOC_CLOSURE=@MODULE__CTYPES_MALLOC_CLOSURE@ -MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h @LIBMPDEC_INTERNAL@ +MODULE__DECIMAL_DEPS=@LIBMPDEC_INTERNAL@ MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/pyexpat.c @LIBEXPAT_INTERNAL@ MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 7d4801f4c752d9..de7200af8c158b 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -50,8 +50,6 @@ #include // isascii() #include -#include "docstrings.h" - #ifdef EXTRA_FUNCTIONALITY #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD #else @@ -1390,15 +1388,29 @@ context_setattrs(PyObject *self, PyObject *prec, PyObject *rounding, return 0; } +/*[clinic input] +_decimal.Context.clear_traps + +Set all traps to False. +[clinic start generated code]*/ + static PyObject * -context_clear_traps(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Context_clear_traps_impl(PyObject *self) +/*[clinic end generated code: output=b47cfa6e32407d40 input=3872e80637148035]*/ { CTX(self)->traps = 0; Py_RETURN_NONE; } +/*[clinic input] +_decimal.Context.clear_flags + +Reset all flags to False. +[clinic start generated code]*/ + static PyObject * -context_clear_flags(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Context_clear_flags_impl(PyObject *self) +/*[clinic end generated code: output=c86719a70177d0b6 input=a06055e2f3e7edb1]*/ { CTX(self)->status = 0; Py_RETURN_NONE; @@ -1496,32 +1508,37 @@ context_dealloc(PyObject *self) Py_DECREF(tp); } -static int -context_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = { - "prec", "rounding", "Emin", "Emax", "capitals", "clamp", - "flags", "traps", NULL - }; - PyObject *prec = Py_None; - PyObject *rounding = Py_None; - PyObject *emin = Py_None; - PyObject *emax = Py_None; - PyObject *capitals = Py_None; - PyObject *clamp = Py_None; - PyObject *status = Py_None; - PyObject *traps = Py_None; - - assert(PyTuple_Check(args)); - - if (!PyArg_ParseTupleAndKeywords( - args, kwds, - "|OOOOOOOO", kwlist, - &prec, &rounding, &emin, &emax, &capitals, &clamp, &status, &traps - )) { - return -1; - } +/*[clinic input] +_decimal.Context.__init__ as context_init + prec: object = None + rounding: object = None + Emin as emin: object = None + Emax as emax: object = None + capitals: object = None + clamp: object = None + flags as status: object = None + traps: object = None + +Create context. + +The context affects almost all operations and controls rounding, +Over/Underflow, raising of exceptions and much more. A new context +can be constructed as follows: + + >>> c = Context(prec=28, Emin=-425000000, Emax=425000000, + ... rounding=ROUND_HALF_EVEN, capitals=1, clamp=1, + ... traps=[InvalidOperation, DivisionByZero, Overflow], + ... flags=[]) + >>> +[clinic start generated code]*/ + +static int +context_init_impl(PyObject *self, PyObject *prec, PyObject *rounding, + PyObject *emin, PyObject *emax, PyObject *capitals, + PyObject *clamp, PyObject *status, PyObject *traps) +/*[clinic end generated code: output=8bfdc59fbe862f44 input=45c704b93cd02959]*/ +{ return context_setattrs( self, prec, rounding, emin, emax, capitals, @@ -1631,8 +1648,15 @@ _decimal_IEEEContext_impl(PyObject *module, Py_ssize_t bits) return NULL; } +/*[clinic input] +_decimal.Context.copy + +Return a duplicate of the context with all flags cleared. +[clinic start generated code]*/ + static PyObject * -context_copy(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Context_copy_impl(PyObject *self) +/*[clinic end generated code: output=f99649a60a9c10f8 input=2589aa46b77cbc28]*/ { PyObject *copy; @@ -1649,6 +1673,12 @@ context_copy(PyObject *self, PyObject *Py_UNUSED(dummy)) return copy; } +static PyObject * +context_copy(PyObject *self, PyObject *Py_UNUSED(dummy)) +{ + return _decimal_Context_copy_impl(self); +} + static PyObject * context_reduce(PyObject *self, PyObject *Py_UNUSED(dummy)) { @@ -3048,11 +3078,26 @@ _decimal_Decimal_from_number_impl(PyTypeObject *type, PyObject *number) } /* create_decimal_from_float */ + +/*[clinic input] +_decimal.Context.create_decimal_from_float + + self as context: self + f: object + / + +Create a new Decimal instance from float f. + +Unlike the Decimal.from_float() class method, this function observes +the context limits. +[clinic start generated code]*/ + static PyObject * -ctx_from_float(PyObject *context, PyObject *v) +_decimal_Context_create_decimal_from_float(PyObject *context, PyObject *f) +/*[clinic end generated code: output=c660c343f6f7158b input=05a8c54b7a5b457b]*/ { decimal_state *state = get_module_state_from_ctx(context); - return PyDec_FromFloat(state, v, context); + return PyDec_FromFloat(state, f, context); } /* Apply the context to the input operand. Return a new PyDecObject. */ @@ -3194,16 +3239,24 @@ dec_new_impl(PyTypeObject *type, PyObject *value, PyObject *context) return PyDecType_FromObjectExact(type, value, context); } -static PyObject * -ctx_create_decimal(PyObject *context, PyObject *args) -{ - PyObject *v = NULL; +/*[clinic input] +_decimal.Context.create_decimal - if (!PyArg_ParseTuple(args, "|O", &v)) { - return NULL; - } + self as context: self + num: object(c_default="NULL") = "0" + / + +Create a new Decimal instance from num, using self as the context. + +Unlike the Decimal constructor, this function observes the context +limits. +[clinic start generated code]*/ - return PyDec_FromObject(v, context); +static PyObject * +_decimal_Context_create_decimal_impl(PyObject *context, PyObject *num) +/*[clinic end generated code: output=85e08ae02f3b34da input=d2c4946cf7804fbe]*/ +{ + return PyDec_FromObject(num, context); } @@ -6503,20 +6556,27 @@ _decimal_Context_subtract_impl(PyObject *context, PyObject *x, PyObject *y) /*[clinic end generated code: output=fa8847e07b7c2bcc input=6767683ec68f7a1a]*/ DecCtx_BinaryFunc(mpd_qsub) +/*[clinic input] +_decimal.Context.divmod + + self as context: self + x: object + y: object + / + +Return quotient and remainder of the division x / y. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_qdivmod(PyObject *context, PyObject *args) +_decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y) +/*[clinic end generated code: output=5dbf5410e3f302af input=4d8eee07823c752a]*/ { - PyObject *v, *w; PyObject *a, *b; PyObject *q, *r; uint32_t status = 0; PyObject *ret; - if (!PyArg_ParseTuple(args, "OO", &v, &w)) { - return NULL; - } - - CONVERT_BINOP_RAISE(&a, &b, v, w, context); + CONVERT_BINOP_RAISE(&a, &b, x, y, context); decimal_state *state = get_module_state_from_ctx(context); q = dec_alloc(state); if (q == NULL) { @@ -6764,52 +6824,95 @@ _decimal_Context_is_zero(PyObject *context, PyObject *x) /*[clinic end generated code: output=24150f3c2422ebf8 input=bf08197d142a8027]*/ DecCtx_BoolFunc_NO_CTX(mpd_iszero) +/*[clinic input] +_decimal.Context.is_canonical = _decimal.Context.is_normal + +Return True if x is canonical, False otherwise. +[clinic start generated code]*/ + static PyObject * -ctx_iscanonical(PyObject *context, PyObject *v) +_decimal_Context_is_canonical(PyObject *context, PyObject *x) +/*[clinic end generated code: output=b5b522b930a41186 input=1bf2129808e55eb9]*/ { decimal_state *state = get_module_state_from_ctx(context); - if (!PyDec_Check(state, v)) { + if (!PyDec_Check(state, x)) { PyErr_SetString(PyExc_TypeError, "argument must be a Decimal"); return NULL; } - return mpd_iscanonical(MPD(v)) ? incr_true() : incr_false(); + return mpd_iscanonical(MPD(x)) ? incr_true() : incr_false(); } /* Functions with a single decimal argument */ +/*[clinic input] +_decimal.Context._apply = _decimal.Context.is_normal + +Apply self to Decimal x. +[clinic start generated code]*/ + static PyObject * -PyDecContext_Apply(PyObject *context, PyObject *v) +_decimal_Context__apply(PyObject *context, PyObject *x) +/*[clinic end generated code: output=8db39d294602492e input=12b34468ca4a4c30]*/ { PyObject *result, *a; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); result = dec_apply(a, context); Py_DECREF(a); return result; } +#ifdef EXTRA_FUNCTIONALITY +/*[clinic input] +_decimal.Context.apply = _decimal.Context._apply + +Apply self to Decimal x. +[clinic start generated code]*/ + static PyObject * -ctx_canonical(PyObject *context, PyObject *v) +_decimal_Context_apply(PyObject *context, PyObject *x) +/*[clinic end generated code: output=4d39653645a6df44 input=388e66ca82733516]*/ +{ + return _decimal_Context__apply(context, v); +} +#endif + +/*[clinic input] +_decimal.Context.canonical = _decimal.Context.is_normal + +Return a new instance of x. +[clinic start generated code]*/ + +static PyObject * +_decimal_Context_canonical(PyObject *context, PyObject *x) +/*[clinic end generated code: output=28fa845499e5d485 input=025ecb106ac15bff]*/ { decimal_state *state = get_module_state_from_ctx(context); - if (!PyDec_Check(state, v)) { + if (!PyDec_Check(state, x)) { PyErr_SetString(PyExc_TypeError, "argument must be a Decimal"); return NULL; } - return Py_NewRef(v); + return Py_NewRef(x); } +/*[clinic input] +_decimal.Context.copy_abs = _decimal.Context.is_normal + +Return a copy of x with the sign set to 0. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_qcopy_abs(PyObject *context, PyObject *v) +_decimal_Context_copy_abs(PyObject *context, PyObject *x) +/*[clinic end generated code: output=a9035e6606261b30 input=4aa2f612625f0f73]*/ { PyObject *result, *a; uint32_t status = 0; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); decimal_state *state = get_module_state_from_ctx(context); result = dec_alloc(state); if (result == NULL) { @@ -6827,22 +6930,36 @@ ctx_mpd_qcopy_abs(PyObject *context, PyObject *v) return result; } +/*[clinic input] +_decimal.Context.copy_decimal = _decimal.Context.is_normal + +Return a copy of Decimal x. +[clinic start generated code]*/ + static PyObject * -ctx_copy_decimal(PyObject *context, PyObject *v) +_decimal_Context_copy_decimal(PyObject *context, PyObject *x) +/*[clinic end generated code: output=b9ec251a2a568a14 input=4db4f942f45fb7c9]*/ { PyObject *result; - CONVERT_OP_RAISE(&result, v, context); + CONVERT_OP_RAISE(&result, x, context); return result; } +/*[clinic input] +_decimal.Context.copy_negate = _decimal.Context.is_normal + +Return a copy of x with the sign inverted. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_qcopy_negate(PyObject *context, PyObject *v) +_decimal_Context_copy_negate(PyObject *context, PyObject *x) +/*[clinic end generated code: output=5fe136d7bac13391 input=2e6e213e2ed0efda]*/ { PyObject *result, *a; uint32_t status = 0; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); decimal_state *state = get_module_state_from_ctx(context); result = dec_alloc(state); if (result == NULL) { @@ -6882,13 +6999,20 @@ _decimal_Context_logical_invert(PyObject *context, PyObject *x) /*[clinic end generated code: output=b863a5cdb986f684 input=1fa8dcc59c557fcc]*/ DecCtx_UnaryFunc(mpd_qinvert) +/*[clinic input] +_decimal.Context.number_class = _decimal.Context.is_normal + +Return an indication of the class of x. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_class(PyObject *context, PyObject *v) +_decimal_Context_number_class(PyObject *context, PyObject *x) +/*[clinic end generated code: output=2b39fa98dd723c6f input=1ead8462f1800e4e]*/ { PyObject *a; const char *cp; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); cp = mpd_class(MPD(a), CTX(context)); Py_DECREF(a); @@ -6896,15 +7020,22 @@ ctx_mpd_class(PyObject *context, PyObject *v) return PyUnicode_FromString(cp); } +/*[clinic input] +_decimal.Context.to_sci_string = _decimal.Context.is_normal + +Convert a number to a string using scientific notation. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_to_sci(PyObject *context, PyObject *v) +_decimal_Context_to_sci_string(PyObject *context, PyObject *x) +/*[clinic end generated code: output=7d461d24824c6f15 input=ed442677c66d342d]*/ { PyObject *result; PyObject *a; mpd_ssize_t size; char *s; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); size = mpd_to_sci_size(&s, MPD(a), CtxCaps(context)); Py_DECREF(a); @@ -6919,15 +7050,22 @@ ctx_mpd_to_sci(PyObject *context, PyObject *v) return result; } +/*[clinic input] +_decimal.Context.to_eng_string = _decimal.Context.is_normal + +Convert a number to a string, using engineering notation. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_to_eng(PyObject *context, PyObject *v) +_decimal_Context_to_eng_string(PyObject *context, PyObject *x) +/*[clinic end generated code: output=3a54b9de0b01708f input=a574385e2e3e3bc0]*/ { PyObject *result; PyObject *a; mpd_ssize_t size; char *s; - CONVERT_OP_RAISE(&a, v, context); + CONVERT_OP_RAISE(&a, x, context); size = mpd_to_eng_size(&s, MPD(a), CtxCaps(context)); Py_DECREF(a); @@ -6973,19 +7111,21 @@ _decimal_Context_compare_total_mag_impl(PyObject *context, PyObject *x, /*[clinic end generated code: output=7c376de9f94feeaf input=2b982e69f932dcb2]*/ DecCtx_BinaryFunc_NO_CTX(mpd_compare_total_mag) +/*[clinic input] +_decimal.Context.copy_sign = _decimal.Context.compare_total + +Copy the sign from y to x. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_qcopy_sign(PyObject *context, PyObject *args) +_decimal_Context_copy_sign_impl(PyObject *context, PyObject *x, PyObject *y) +/*[clinic end generated code: output=fff3c5c474acf78e input=c0682aeaffc7cfdf]*/ { - PyObject *v, *w; PyObject *a, *b; PyObject *result; uint32_t status = 0; - if (!PyArg_ParseTuple(args, "OO", &v, &w)) { - return NULL; - } - - CONVERT_BINOP_RAISE(&a, &b, v, w, context); + CONVERT_BINOP_RAISE(&a, &b, x, y, context); decimal_state *state = get_module_state_from_ctx(context); result = dec_alloc(state); if (result == NULL) { @@ -7073,18 +7213,21 @@ _decimal_Context_shift_impl(PyObject *context, PyObject *x, PyObject *y) /*[clinic end generated code: output=78625878a264b3e5 input=1ab44ff0854420ce]*/ DecCtx_BinaryFunc(mpd_qshift) +/*[clinic input] +_decimal.Context.same_quantum = _decimal.Context.add + +Return True if the two operands have the same exponent. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_same_quantum(PyObject *context, PyObject *args) +_decimal_Context_same_quantum_impl(PyObject *context, PyObject *x, + PyObject *y) +/*[clinic end generated code: output=137acab27ece605c input=194cd156e398eaf9]*/ { - PyObject *v, *w; PyObject *a, *b; PyObject *result; - if (!PyArg_ParseTuple(args, "OO", &v, &w)) { - return NULL; - } - - CONVERT_BINOP_RAISE(&a, &b, v, w, context); + CONVERT_BINOP_RAISE(&a, &b, x, y, context); result = mpd_same_quantum(MPD(a), MPD(b)) ? incr_true() : incr_false(); Py_DECREF(a); @@ -7117,7 +7260,7 @@ static PyMethodDef context_methods [] = _DECIMAL_CONTEXT_COMPARE_SIGNAL_METHODDEF _DECIMAL_CONTEXT_DIVIDE_METHODDEF _DECIMAL_CONTEXT_DIVIDE_INT_METHODDEF - { "divmod", ctx_mpd_qdivmod, METH_VARARGS, doc_ctx_divmod }, + _DECIMAL_CONTEXT_DIVMOD_METHODDEF _DECIMAL_CONTEXT_MAX_METHODDEF _DECIMAL_CONTEXT_MAX_MAG_METHODDEF _DECIMAL_CONTEXT_MIN_METHODDEF @@ -7141,7 +7284,7 @@ static PyMethodDef context_methods [] = _DECIMAL_CONTEXT_RADIX_METHODDEF /* Boolean functions */ - { "is_canonical", ctx_iscanonical, METH_O, doc_ctx_is_canonical }, + _DECIMAL_CONTEXT_IS_CANONICAL_METHODDEF _DECIMAL_CONTEXT_IS_FINITE_METHODDEF _DECIMAL_CONTEXT_IS_INFINITE_METHODDEF _DECIMAL_CONTEXT_IS_NAN_METHODDEF @@ -7153,35 +7296,33 @@ static PyMethodDef context_methods [] = _DECIMAL_CONTEXT_IS_ZERO_METHODDEF /* Functions with a single decimal argument */ - { "_apply", PyDecContext_Apply, METH_O, NULL }, /* alias for apply */ -#ifdef EXTRA_FUNCTIONALITY - { "apply", PyDecContext_Apply, METH_O, doc_ctx_apply }, -#endif - { "canonical", ctx_canonical, METH_O, doc_ctx_canonical }, - { "copy_abs", ctx_mpd_qcopy_abs, METH_O, doc_ctx_copy_abs }, - { "copy_decimal", ctx_copy_decimal, METH_O, doc_ctx_copy_decimal }, - { "copy_negate", ctx_mpd_qcopy_negate, METH_O, doc_ctx_copy_negate }, + _DECIMAL_CONTEXT__APPLY_METHODDEF + _DECIMAL_CONTEXT_APPLY_METHODDEF + _DECIMAL_CONTEXT_CANONICAL_METHODDEF + _DECIMAL_CONTEXT_COPY_ABS_METHODDEF + _DECIMAL_CONTEXT_COPY_DECIMAL_METHODDEF + _DECIMAL_CONTEXT_COPY_NEGATE_METHODDEF _DECIMAL_CONTEXT_LOGB_METHODDEF _DECIMAL_CONTEXT_LOGICAL_INVERT_METHODDEF - { "number_class", ctx_mpd_class, METH_O, doc_ctx_number_class }, - { "to_sci_string", ctx_mpd_to_sci, METH_O, doc_ctx_to_sci_string }, - { "to_eng_string", ctx_mpd_to_eng, METH_O, doc_ctx_to_eng_string }, + _DECIMAL_CONTEXT_NUMBER_CLASS_METHODDEF + _DECIMAL_CONTEXT_TO_SCI_STRING_METHODDEF + _DECIMAL_CONTEXT_TO_ENG_STRING_METHODDEF /* Functions with two decimal arguments */ _DECIMAL_CONTEXT_COMPARE_TOTAL_METHODDEF _DECIMAL_CONTEXT_COMPARE_TOTAL_MAG_METHODDEF - { "copy_sign", ctx_mpd_qcopy_sign, METH_VARARGS, doc_ctx_copy_sign }, + _DECIMAL_CONTEXT_COPY_SIGN_METHODDEF _DECIMAL_CONTEXT_LOGICAL_AND_METHODDEF _DECIMAL_CONTEXT_LOGICAL_OR_METHODDEF _DECIMAL_CONTEXT_LOGICAL_XOR_METHODDEF _DECIMAL_CONTEXT_ROTATE_METHODDEF - { "same_quantum", ctx_mpd_same_quantum, METH_VARARGS, doc_ctx_same_quantum }, + _DECIMAL_CONTEXT_SAME_QUANTUM_METHODDEF _DECIMAL_CONTEXT_SCALEB_METHODDEF _DECIMAL_CONTEXT_SHIFT_METHODDEF /* Set context values */ - { "clear_flags", context_clear_flags, METH_NOARGS, doc_ctx_clear_flags }, - { "clear_traps", context_clear_traps, METH_NOARGS, doc_ctx_clear_traps }, + _DECIMAL_CONTEXT_CLEAR_FLAGS_METHODDEF + _DECIMAL_CONTEXT_CLEAR_TRAPS_METHODDEF #ifdef CONFIG_32 /* Unsafe set functions with relaxed range checks */ @@ -7193,9 +7334,9 @@ static PyMethodDef context_methods [] = /* Miscellaneous */ { "__copy__", context_copy, METH_NOARGS, NULL }, { "__reduce__", context_reduce, METH_NOARGS, NULL }, - { "copy", 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 }, + _DECIMAL_CONTEXT_COPY_METHODDEF + _DECIMAL_CONTEXT_CREATE_DECIMAL_METHODDEF + _DECIMAL_CONTEXT_CREATE_DECIMAL_FROM_FLOAT_METHODDEF { NULL, NULL, 1 } }; @@ -7208,7 +7349,7 @@ static PyType_Slot context_slots[] = { {Py_tp_repr, context_repr}, {Py_tp_getattro, context_getattr}, {Py_tp_setattro, context_setattr}, - {Py_tp_doc, (void *)doc_context}, + {Py_tp_doc, (void *)context_init__doc__}, {Py_tp_methods, context_methods}, {Py_tp_getset, context_getsets}, {Py_tp_init, context_init}, diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index 06dd1b1b762060..0f7a7f78cd73e5 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -51,6 +51,166 @@ _decimal_Context_Etop(PyObject *self, PyObject *Py_UNUSED(ignored)) return _decimal_Context_Etop_impl(self); } +PyDoc_STRVAR(_decimal_Context_clear_traps__doc__, +"clear_traps($self, /)\n" +"--\n" +"\n" +"Set all traps to False."); + +#define _DECIMAL_CONTEXT_CLEAR_TRAPS_METHODDEF \ + {"clear_traps", (PyCFunction)_decimal_Context_clear_traps, METH_NOARGS, _decimal_Context_clear_traps__doc__}, + +static PyObject * +_decimal_Context_clear_traps_impl(PyObject *self); + +static PyObject * +_decimal_Context_clear_traps(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_clear_traps_impl(self); +} + +PyDoc_STRVAR(_decimal_Context_clear_flags__doc__, +"clear_flags($self, /)\n" +"--\n" +"\n" +"Reset all flags to False."); + +#define _DECIMAL_CONTEXT_CLEAR_FLAGS_METHODDEF \ + {"clear_flags", (PyCFunction)_decimal_Context_clear_flags, METH_NOARGS, _decimal_Context_clear_flags__doc__}, + +static PyObject * +_decimal_Context_clear_flags_impl(PyObject *self); + +static PyObject * +_decimal_Context_clear_flags(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_clear_flags_impl(self); +} + +PyDoc_STRVAR(context_init__doc__, +"Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None,\n" +" clamp=None, flags=None, traps=None)\n" +"--\n" +"\n" +"Create context.\n" +"\n" +"The context affects almost all operations and controls rounding,\n" +"Over/Underflow, raising of exceptions and much more. A new context\n" +"can be constructed as follows:\n" +"\n" +" >>> c = Context(prec=28, Emin=-425000000, Emax=425000000,\n" +" ... rounding=ROUND_HALF_EVEN, capitals=1, clamp=1,\n" +" ... traps=[InvalidOperation, DivisionByZero, Overflow],\n" +" ... flags=[])\n" +" >>>"); + +static int +context_init_impl(PyObject *self, PyObject *prec, PyObject *rounding, + PyObject *emin, PyObject *emax, PyObject *capitals, + PyObject *clamp, PyObject *status, PyObject *traps); + +static int +context_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 8 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(prec), &_Py_ID(rounding), &_Py_ID(Emin), &_Py_ID(Emax), &_Py_ID(capitals), &_Py_ID(clamp), &_Py_ID(flags), &_Py_ID(traps), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"prec", "rounding", "Emin", "Emax", "capitals", "clamp", "flags", "traps", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Context", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[8]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *prec = Py_None; + PyObject *rounding = Py_None; + PyObject *emin = Py_None; + PyObject *emax = Py_None; + PyObject *capitals = Py_None; + PyObject *clamp = Py_None; + PyObject *status = Py_None; + PyObject *traps = Py_None; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, + /*minpos*/ 0, /*maxpos*/ 8, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (fastargs[0]) { + prec = fastargs[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[1]) { + rounding = fastargs[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[2]) { + emin = fastargs[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[3]) { + emax = fastargs[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[4]) { + capitals = fastargs[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[5]) { + clamp = fastargs[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[6]) { + status = fastargs[6]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + traps = fastargs[7]; +skip_optional_pos: + return_value = context_init_impl(self, prec, rounding, emin, emax, capitals, clamp, status, traps); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_IEEEContext__doc__, "IEEEContext($module, bits, /)\n" "--\n" @@ -90,6 +250,24 @@ _decimal_IEEEContext(PyObject *module, PyObject *arg) return return_value; } +PyDoc_STRVAR(_decimal_Context_copy__doc__, +"copy($self, /)\n" +"--\n" +"\n" +"Return a duplicate of the context with all flags cleared."); + +#define _DECIMAL_CONTEXT_COPY_METHODDEF \ + {"copy", (PyCFunction)_decimal_Context_copy, METH_NOARGS, _decimal_Context_copy__doc__}, + +static PyObject * +_decimal_Context_copy_impl(PyObject *self); + +static PyObject * +_decimal_Context_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_copy_impl(self); +} + PyDoc_STRVAR(_decimal_getcontext__doc__, "getcontext($module, /)\n" "--\n" @@ -311,6 +489,18 @@ _decimal_Decimal_from_number(PyObject *type, PyObject *number) return return_value; } +PyDoc_STRVAR(_decimal_Context_create_decimal_from_float__doc__, +"create_decimal_from_float($self, f, /)\n" +"--\n" +"\n" +"Create a new Decimal instance from float f.\n" +"\n" +"Unlike the Decimal.from_float() class method, this function observes\n" +"the context limits."); + +#define _DECIMAL_CONTEXT_CREATE_DECIMAL_FROM_FLOAT_METHODDEF \ + {"create_decimal_from_float", (PyCFunction)_decimal_Context_create_decimal_from_float, METH_O, _decimal_Context_create_decimal_from_float__doc__}, + PyDoc_STRVAR(dec_new__doc__, "Decimal(value=\'0\', context=None)\n" "--\n" @@ -385,6 +575,41 @@ dec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) return return_value; } +PyDoc_STRVAR(_decimal_Context_create_decimal__doc__, +"create_decimal($self, num=\'0\', /)\n" +"--\n" +"\n" +"Create a new Decimal instance from num, using self as the context.\n" +"\n" +"Unlike the Decimal constructor, this function observes the context\n" +"limits."); + +#define _DECIMAL_CONTEXT_CREATE_DECIMAL_METHODDEF \ + {"create_decimal", _PyCFunction_CAST(_decimal_Context_create_decimal), METH_FASTCALL, _decimal_Context_create_decimal__doc__}, + +static PyObject * +_decimal_Context_create_decimal_impl(PyObject *context, PyObject *num); + +static PyObject * +_decimal_Context_create_decimal(PyObject *context, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *num = NULL; + + if (!_PyArg_CheckPositional("create_decimal", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + num = args[0]; +skip_optional: + return_value = _decimal_Context_create_decimal_impl(context, num); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal___format____doc__, "__format__($self, format_spec, override=, /)\n" "--\n" @@ -4011,6 +4236,36 @@ _decimal_Context_subtract(PyObject *context, PyObject *const *args, Py_ssize_t n return return_value; } +PyDoc_STRVAR(_decimal_Context_divmod__doc__, +"divmod($self, x, y, /)\n" +"--\n" +"\n" +"Return quotient and remainder of the division x / y."); + +#define _DECIMAL_CONTEXT_DIVMOD_METHODDEF \ + {"divmod", _PyCFunction_CAST(_decimal_Context_divmod), METH_FASTCALL, _decimal_Context_divmod__doc__}, + +static PyObject * +_decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y); + +static PyObject * +_decimal_Context_divmod(PyObject *context, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *x; + PyObject *y; + + if (!_PyArg_CheckPositional("divmod", nargs, 2, 2)) { + goto exit; + } + x = args[0]; + y = args[1]; + return_value = _decimal_Context_divmod_impl(context, x, y); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Context_power__doc__, "power($self, /, a, b, modulo=None)\n" "--\n" @@ -4225,6 +4480,73 @@ PyDoc_STRVAR(_decimal_Context_is_zero__doc__, #define _DECIMAL_CONTEXT_IS_ZERO_METHODDEF \ {"is_zero", (PyCFunction)_decimal_Context_is_zero, METH_O, _decimal_Context_is_zero__doc__}, +PyDoc_STRVAR(_decimal_Context_is_canonical__doc__, +"is_canonical($self, x, /)\n" +"--\n" +"\n" +"Return True if x is canonical, False otherwise."); + +#define _DECIMAL_CONTEXT_IS_CANONICAL_METHODDEF \ + {"is_canonical", (PyCFunction)_decimal_Context_is_canonical, METH_O, _decimal_Context_is_canonical__doc__}, + +PyDoc_STRVAR(_decimal_Context__apply__doc__, +"_apply($self, x, /)\n" +"--\n" +"\n" +"Apply self to Decimal x."); + +#define _DECIMAL_CONTEXT__APPLY_METHODDEF \ + {"_apply", (PyCFunction)_decimal_Context__apply, METH_O, _decimal_Context__apply__doc__}, + +#if defined(EXTRA_FUNCTIONALITY) + +PyDoc_STRVAR(_decimal_Context_apply__doc__, +"apply($self, x, /)\n" +"--\n" +"\n" +"Apply self to Decimal x."); + +#define _DECIMAL_CONTEXT_APPLY_METHODDEF \ + {"apply", (PyCFunction)_decimal_Context_apply, METH_O, _decimal_Context_apply__doc__}, + +#endif /* defined(EXTRA_FUNCTIONALITY) */ + +PyDoc_STRVAR(_decimal_Context_canonical__doc__, +"canonical($self, x, /)\n" +"--\n" +"\n" +"Return a new instance of x."); + +#define _DECIMAL_CONTEXT_CANONICAL_METHODDEF \ + {"canonical", (PyCFunction)_decimal_Context_canonical, METH_O, _decimal_Context_canonical__doc__}, + +PyDoc_STRVAR(_decimal_Context_copy_abs__doc__, +"copy_abs($self, x, /)\n" +"--\n" +"\n" +"Return a copy of x with the sign set to 0."); + +#define _DECIMAL_CONTEXT_COPY_ABS_METHODDEF \ + {"copy_abs", (PyCFunction)_decimal_Context_copy_abs, METH_O, _decimal_Context_copy_abs__doc__}, + +PyDoc_STRVAR(_decimal_Context_copy_decimal__doc__, +"copy_decimal($self, x, /)\n" +"--\n" +"\n" +"Return a copy of Decimal x."); + +#define _DECIMAL_CONTEXT_COPY_DECIMAL_METHODDEF \ + {"copy_decimal", (PyCFunction)_decimal_Context_copy_decimal, METH_O, _decimal_Context_copy_decimal__doc__}, + +PyDoc_STRVAR(_decimal_Context_copy_negate__doc__, +"copy_negate($self, x, /)\n" +"--\n" +"\n" +"Return a copy of x with the sign inverted."); + +#define _DECIMAL_CONTEXT_COPY_NEGATE_METHODDEF \ + {"copy_negate", (PyCFunction)_decimal_Context_copy_negate, METH_O, _decimal_Context_copy_negate__doc__}, + PyDoc_STRVAR(_decimal_Context_logb__doc__, "logb($self, x, /)\n" "--\n" @@ -4243,6 +4565,33 @@ PyDoc_STRVAR(_decimal_Context_logical_invert__doc__, #define _DECIMAL_CONTEXT_LOGICAL_INVERT_METHODDEF \ {"logical_invert", (PyCFunction)_decimal_Context_logical_invert, METH_O, _decimal_Context_logical_invert__doc__}, +PyDoc_STRVAR(_decimal_Context_number_class__doc__, +"number_class($self, x, /)\n" +"--\n" +"\n" +"Return an indication of the class of x."); + +#define _DECIMAL_CONTEXT_NUMBER_CLASS_METHODDEF \ + {"number_class", (PyCFunction)_decimal_Context_number_class, METH_O, _decimal_Context_number_class__doc__}, + +PyDoc_STRVAR(_decimal_Context_to_sci_string__doc__, +"to_sci_string($self, x, /)\n" +"--\n" +"\n" +"Convert a number to a string using scientific notation."); + +#define _DECIMAL_CONTEXT_TO_SCI_STRING_METHODDEF \ + {"to_sci_string", (PyCFunction)_decimal_Context_to_sci_string, METH_O, _decimal_Context_to_sci_string__doc__}, + +PyDoc_STRVAR(_decimal_Context_to_eng_string__doc__, +"to_eng_string($self, x, /)\n" +"--\n" +"\n" +"Convert a number to a string, using engineering notation."); + +#define _DECIMAL_CONTEXT_TO_ENG_STRING_METHODDEF \ + {"to_eng_string", (PyCFunction)_decimal_Context_to_eng_string, METH_O, _decimal_Context_to_eng_string__doc__}, + PyDoc_STRVAR(_decimal_Context_compare_total__doc__, "compare_total($self, x, y, /)\n" "--\n" @@ -4305,6 +4654,36 @@ _decimal_Context_compare_total_mag(PyObject *context, PyObject *const *args, Py_ return return_value; } +PyDoc_STRVAR(_decimal_Context_copy_sign__doc__, +"copy_sign($self, x, y, /)\n" +"--\n" +"\n" +"Copy the sign from y to x."); + +#define _DECIMAL_CONTEXT_COPY_SIGN_METHODDEF \ + {"copy_sign", _PyCFunction_CAST(_decimal_Context_copy_sign), METH_FASTCALL, _decimal_Context_copy_sign__doc__}, + +static PyObject * +_decimal_Context_copy_sign_impl(PyObject *context, PyObject *x, PyObject *y); + +static PyObject * +_decimal_Context_copy_sign(PyObject *context, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *x; + PyObject *y; + + if (!_PyArg_CheckPositional("copy_sign", nargs, 2, 2)) { + goto exit; + } + x = args[0]; + y = args[1]; + return_value = _decimal_Context_copy_sign_impl(context, x, y); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Context_logical_and__doc__, "logical_and($self, x, y, /)\n" "--\n" @@ -4486,4 +4865,39 @@ _decimal_Context_shift(PyObject *context, PyObject *const *args, Py_ssize_t narg exit: return return_value; } -/*[clinic end generated code: output=db00589bcc7a168d input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_decimal_Context_same_quantum__doc__, +"same_quantum($self, x, y, /)\n" +"--\n" +"\n" +"Return True if the two operands have the same exponent."); + +#define _DECIMAL_CONTEXT_SAME_QUANTUM_METHODDEF \ + {"same_quantum", _PyCFunction_CAST(_decimal_Context_same_quantum), METH_FASTCALL, _decimal_Context_same_quantum__doc__}, + +static PyObject * +_decimal_Context_same_quantum_impl(PyObject *context, PyObject *x, + PyObject *y); + +static PyObject * +_decimal_Context_same_quantum(PyObject *context, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *x; + PyObject *y; + + if (!_PyArg_CheckPositional("same_quantum", nargs, 2, 2)) { + goto exit; + } + x = args[0]; + y = args[1]; + return_value = _decimal_Context_same_quantum_impl(context, x, y); + +exit: + return return_value; +} + +#ifndef _DECIMAL_CONTEXT_APPLY_METHODDEF + #define _DECIMAL_CONTEXT_APPLY_METHODDEF +#endif /* !defined(_DECIMAL_CONTEXT_APPLY_METHODDEF) */ +/*[clinic end generated code: output=1e10ddd6610e17dc input=a9049054013a1b77]*/ diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h deleted file mode 100644 index d9be7d9edf6c9e..00000000000000 --- a/Modules/_decimal/docstrings.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2001 Python Software Foundation. All Rights Reserved. - * Modified and extended by Stefan Krah. - */ - - -#ifndef DOCSTRINGS_H -#define DOCSTRINGS_H - - -#include "pymacro.h" - -/******************************************************************************/ -/* Context Object and Methods */ -/******************************************************************************/ - -PyDoc_STRVAR(doc_context, -"Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)\n--\n\n\ -The context affects almost all operations and controls rounding,\n\ -Over/Underflow, raising of exceptions and much more. A new context\n\ -can be constructed as follows:\n\ -\n\ - >>> c = Context(prec=28, Emin=-425000000, Emax=425000000,\n\ - ... rounding=ROUND_HALF_EVEN, capitals=1, clamp=1,\n\ - ... traps=[InvalidOperation, DivisionByZero, Overflow],\n\ - ... flags=[])\n\ - >>>\n\ -\n\ -\n"); - -#ifdef EXTRA_FUNCTIONALITY -PyDoc_STRVAR(doc_ctx_apply, -"apply($self, x, /)\n--\n\n\ -Apply self to Decimal x.\n\ -\n"); -#endif - -PyDoc_STRVAR(doc_ctx_clear_flags, -"clear_flags($self, /)\n--\n\n\ -Reset all flags to False.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_clear_traps, -"clear_traps($self, /)\n--\n\n\ -Set all traps to False.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_copy, -"copy($self, /)\n--\n\n\ -Return a duplicate of the context with all flags cleared.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_copy_decimal, -"copy_decimal($self, x, /)\n--\n\n\ -Return a copy of Decimal x.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_create_decimal, -"create_decimal($self, num=\"0\", /)\n--\n\n\ -Create a new Decimal instance from num, using self as the context. Unlike the\n\ -Decimal constructor, this function observes the context limits.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_create_decimal_from_float, -"create_decimal_from_float($self, f, /)\n--\n\n\ -Create a new Decimal instance from float f. Unlike the Decimal.from_float()\n\ -class method, this function observes the context limits.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_canonical, -"canonical($self, x, /)\n--\n\n\ -Return a new instance of x.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_copy_abs, -"copy_abs($self, x, /)\n--\n\n\ -Return a copy of x with the sign set to 0.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_copy_negate, -"copy_negate($self, x, /)\n--\n\n\ -Return a copy of x with the sign inverted.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_copy_sign, -"copy_sign($self, x, y, /)\n--\n\n\ -Copy the sign from y to x.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_divmod, -"divmod($self, x, y, /)\n--\n\n\ -Return quotient and remainder of the division x / y.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_is_canonical, -"is_canonical($self, x, /)\n--\n\n\ -Return True if x is canonical, False otherwise.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_normalize, -"normalize($self, x, /)\n--\n\n\ -Reduce x to its simplest form. Alias for reduce(x).\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_number_class, -"number_class($self, x, /)\n--\n\n\ -Return an indication of the class of x.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_same_quantum, -"same_quantum($self, x, y, /)\n--\n\n\ -Return True if the two operands have the same exponent.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_to_eng_string, -"to_eng_string($self, x, /)\n--\n\n\ -Convert a number to a string, using engineering notation.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_to_sci_string, -"to_sci_string($self, x, /)\n--\n\n\ -Convert a number to a string using scientific notation.\n\ -\n"); - - -#endif /* DOCSTRINGS_H */ - - - diff --git a/PCbuild/_decimal.vcxproj b/PCbuild/_decimal.vcxproj index ee7421484b5312..3ba49370d583dd 100644 --- a/PCbuild/_decimal.vcxproj +++ b/PCbuild/_decimal.vcxproj @@ -108,7 +108,6 @@ - diff --git a/PCbuild/_decimal.vcxproj.filters b/PCbuild/_decimal.vcxproj.filters index e4bdb64ec1fb9f..7cb6b867a47c78 100644 --- a/PCbuild/_decimal.vcxproj.filters +++ b/PCbuild/_decimal.vcxproj.filters @@ -18,9 +18,6 @@ - - Header Files - Header Files\libmpdec