diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 27102588076cc2..c5a08e05e70287 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -566,6 +566,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(Emax)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(Emin)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(FINISHED)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(False)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(JSONDecodeError)); @@ -848,11 +850,13 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cancel)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capath)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capitals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(category)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cb_type)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(certfile)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(chain)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(check_same_thread)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(clamp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(clear)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(close)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(closed)); @@ -892,6 +896,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(covariant)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ctx)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d_parameter_type)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data)); @@ -1113,6 +1118,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module_globals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(modules)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(modulo)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(month)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(msg)); @@ -1181,6 +1187,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos2)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(posix)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(prec)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(preserve_exc)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(print_file_and_line)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority)); @@ -1303,6 +1310,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traceback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trailers)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(translate)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traps)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(true)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(truncate)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(twice)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 2d6130c216993f..9e49e4497750a0 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -57,6 +57,8 @@ struct _Py_global_strings { struct { STRUCT_FOR_ID(CANCELLED) + STRUCT_FOR_ID(Emax) + STRUCT_FOR_ID(Emin) STRUCT_FOR_ID(FINISHED) STRUCT_FOR_ID(False) STRUCT_FOR_ID(JSONDecodeError) @@ -339,11 +341,13 @@ struct _Py_global_strings { STRUCT_FOR_ID(callback) STRUCT_FOR_ID(cancel) STRUCT_FOR_ID(capath) + STRUCT_FOR_ID(capitals) STRUCT_FOR_ID(category) STRUCT_FOR_ID(cb_type) STRUCT_FOR_ID(certfile) STRUCT_FOR_ID(chain) STRUCT_FOR_ID(check_same_thread) + STRUCT_FOR_ID(clamp) STRUCT_FOR_ID(clear) STRUCT_FOR_ID(close) STRUCT_FOR_ID(closed) @@ -383,6 +387,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(coro) STRUCT_FOR_ID(count) STRUCT_FOR_ID(covariant) + STRUCT_FOR_ID(ctx) STRUCT_FOR_ID(cwd) STRUCT_FOR_ID(d_parameter_type) STRUCT_FOR_ID(data) @@ -604,6 +609,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(module) STRUCT_FOR_ID(module_globals) STRUCT_FOR_ID(modules) + STRUCT_FOR_ID(modulo) STRUCT_FOR_ID(month) STRUCT_FOR_ID(mro) STRUCT_FOR_ID(msg) @@ -672,6 +678,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(pos1) STRUCT_FOR_ID(pos2) STRUCT_FOR_ID(posix) + STRUCT_FOR_ID(prec) STRUCT_FOR_ID(preserve_exc) STRUCT_FOR_ID(print_file_and_line) STRUCT_FOR_ID(priority) @@ -794,6 +801,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(traceback) STRUCT_FOR_ID(trailers) STRUCT_FOR_ID(translate) + STRUCT_FOR_ID(traps) STRUCT_FOR_ID(true) STRUCT_FOR_ID(truncate) STRUCT_FOR_ID(twice) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 9e72c7df77b945..5c65cb218dedbb 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -564,6 +564,8 @@ extern "C" { #define _Py_str_identifiers_INIT { \ INIT_ID(CANCELLED), \ + INIT_ID(Emax), \ + INIT_ID(Emin), \ INIT_ID(FINISHED), \ INIT_ID(False), \ INIT_ID(JSONDecodeError), \ @@ -846,11 +848,13 @@ extern "C" { INIT_ID(callback), \ INIT_ID(cancel), \ INIT_ID(capath), \ + INIT_ID(capitals), \ INIT_ID(category), \ INIT_ID(cb_type), \ INIT_ID(certfile), \ INIT_ID(chain), \ INIT_ID(check_same_thread), \ + INIT_ID(clamp), \ INIT_ID(clear), \ INIT_ID(close), \ INIT_ID(closed), \ @@ -890,6 +894,7 @@ extern "C" { INIT_ID(coro), \ INIT_ID(count), \ INIT_ID(covariant), \ + INIT_ID(ctx), \ INIT_ID(cwd), \ INIT_ID(d_parameter_type), \ INIT_ID(data), \ @@ -1111,6 +1116,7 @@ extern "C" { INIT_ID(module), \ INIT_ID(module_globals), \ INIT_ID(modules), \ + INIT_ID(modulo), \ INIT_ID(month), \ INIT_ID(mro), \ INIT_ID(msg), \ @@ -1179,6 +1185,7 @@ extern "C" { INIT_ID(pos1), \ INIT_ID(pos2), \ INIT_ID(posix), \ + INIT_ID(prec), \ INIT_ID(preserve_exc), \ INIT_ID(print_file_and_line), \ INIT_ID(priority), \ @@ -1301,6 +1308,7 @@ extern "C" { INIT_ID(traceback), \ INIT_ID(trailers), \ INIT_ID(translate), \ + INIT_ID(traps), \ INIT_ID(true), \ INIT_ID(truncate), \ INIT_ID(twice), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 02c62f68ff0801..4905007b95f8fa 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -16,6 +16,14 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(Emax); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(Emin); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(FINISHED); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1144,6 +1152,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(capitals); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(category); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1164,6 +1176,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(clamp); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(clear); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1320,6 +1336,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(ctx); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(cwd); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2204,6 +2224,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(modulo); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(month); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2476,6 +2500,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(prec); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(preserve_exc); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2964,6 +2992,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(traps); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(true); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 46cedf83df1f00..52ed5a532efd27 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -63,8 +63,9 @@ /*[clinic input] module _decimal class _decimal.Decimal "PyObject *" "&dec_spec" +class _decimal.Context "PyObject *" "&ctx_spec" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e0e1f68f1f413f5f]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8c3aa7cfde934d7b]*/ struct PyDecContextObject; struct DecCondMap; @@ -1566,17 +1567,26 @@ init_extended_context(PyObject *v) } /* Factory function for creating IEEE interchange format contexts */ + +/*[clinic input] +_decimal.IEEEContext + + bits: Py_ssize_t + / + +Return a context, initialized as one of the IEEE interchange formats. + +The argument must be a multiple of 32 and less than +IEEE_CONTEXT_MAX_BITS. +[clinic start generated code]*/ + static PyObject * -ieee_context(PyObject *module, PyObject *v) +_decimal_IEEEContext_impl(PyObject *module, Py_ssize_t bits) +/*[clinic end generated code: output=19a35f320fe19789 input=5cff864d899eb2d7]*/ { PyObject *context; - mpd_ssize_t bits; mpd_context_t ctx; - bits = PyLong_AsSsize_t(v); - if (bits == -1 && PyErr_Occurred()) { - return NULL; - } if (bits <= 0 || bits > INT_MAX) { goto error; } @@ -1775,7 +1785,7 @@ current_context(decimal_state *modstate) /* Return a new reference to the current context */ static PyObject * -PyDec_GetCurrentContext(PyObject *self, PyObject *Py_UNUSED(dummy)) +PyDec_GetCurrentContext(PyObject *self) { PyObject *context; decimal_state *state = get_module_state(self); @@ -1871,7 +1881,7 @@ current_context(decimal_state *state) /* Return a new reference to the current context */ static PyObject * -PyDec_GetCurrentContext(PyObject *self, PyObject *Py_UNUSED(dummy)) +PyDec_GetCurrentContext(PyObject *self) { decimal_state *state = get_module_state(self); return current_context(state); @@ -1910,36 +1920,73 @@ PyDec_SetCurrentContext(PyObject *self, PyObject *v) } #endif +/*[clinic input] +_decimal.getcontext + +Get the current default context. +[clinic start generated code]*/ + +static PyObject * +_decimal_getcontext_impl(PyObject *module) +/*[clinic end generated code: output=5982062c4d39e3dd input=7ac316fe42a1b6f5]*/ +{ + return PyDec_GetCurrentContext(module); +} + +/*[clinic input] +_decimal.setcontext + + context: object + / + +Set a new default context. +[clinic start generated code]*/ + +static PyObject * +_decimal_setcontext(PyObject *module, PyObject *context) +/*[clinic end generated code: output=8065f870be2852ce input=b57d7ee786b022a6]*/ +{ + return PyDec_SetCurrentContext(module, context); +} + /* Context manager object for the 'with' statement. The manager * owns one reference to the global (outer) context and one * to the local (inner) context. */ + +/*[clinic input] +@text_signature "($module, /, ctx=None, **kwargs)" +_decimal.localcontext + + ctx as local: object = None + * + prec: object = None + rounding: object = None + Emin: object = None + Emax: object = None + capitals: object = None + clamp: object = None + flags: object = None + traps: object = None + +Return a context manager for a copy of the supplied context. + +That will set the default context to a copy of ctx on entry to the +with-statement and restore the previous default context when exiting +the with-statement. If no context is specified, a copy of the current +default context is used. +[clinic start generated code]*/ + static PyObject * -ctxmanager_new(PyObject *m, PyObject *args, PyObject *kwds) +_decimal_localcontext_impl(PyObject *module, PyObject *local, PyObject *prec, + PyObject *rounding, PyObject *Emin, + PyObject *Emax, PyObject *capitals, + PyObject *clamp, PyObject *flags, PyObject *traps) +/*[clinic end generated code: output=9bf4e47742a809b0 input=490307b9689c3856]*/ { - static char *kwlist[] = { - "ctx", "prec", "rounding", - "Emin", "Emax", "capitals", - "clamp", "flags", "traps", - NULL - }; - PyObject *local = Py_None; PyObject *global; - 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 *flags = Py_None; - PyObject *traps = Py_None; - - decimal_state *state = get_module_state(m); + decimal_state *state = get_module_state(module); CURRENT_CONTEXT(state, global); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOOOO", kwlist, &local, - &prec, &rounding, &Emin, &Emax, &capitals, &clamp, &flags, &traps)) { - return NULL; - } if (local == Py_None) { local = global; } @@ -3569,15 +3616,27 @@ pydec_format(PyObject *dec, PyObject *context, PyObject *fmt, decimal_state *sta } /* Formatted representation of a PyDecObject. */ + +/*[clinic input] +_decimal.Decimal.__format__ + + self as dec: self + format_spec as fmtarg: unicode + override: object = NULL + / + +Formats the Decimal according to format_spec. +[clinic start generated code]*/ + static PyObject * -dec_format(PyObject *dec, PyObject *args) +_decimal_Decimal___format___impl(PyObject *dec, PyObject *fmtarg, + PyObject *override) +/*[clinic end generated code: output=4b3640b7f0c8b6a5 input=e53488e49a0fff00]*/ { PyObject *result = NULL; - PyObject *override = NULL; PyObject *dot = NULL; PyObject *sep = NULL; PyObject *grouping = NULL; - PyObject *fmtarg; PyObject *context; mpd_spec_t spec; char *fmt; @@ -3585,42 +3644,29 @@ dec_format(PyObject *dec, PyObject *args) uint32_t status = 0; int replace_fillchar = 0; Py_ssize_t size; - - decimal_state *state = get_module_state_by_def(Py_TYPE(dec)); CURRENT_CONTEXT(state, context); - if (!PyArg_ParseTuple(args, "O|O", &fmtarg, &override)) { + fmt = (char *)PyUnicode_AsUTF8AndSize(fmtarg, &size); + if (fmt == NULL) { return NULL; } - if (PyUnicode_Check(fmtarg)) { - fmt = (char *)PyUnicode_AsUTF8AndSize(fmtarg, &size); - if (fmt == NULL) { + if (size > 0 && fmt[size-1] == 'N') { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Format specifier 'N' is deprecated", 1) < 0) { return NULL; } + } - if (size > 0 && fmt[size-1] == 'N') { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Format specifier 'N' is deprecated", 1) < 0) { - return NULL; - } - } - - if (size > 0 && fmt[0] == '\0') { - /* NUL fill character: must be replaced with a valid UTF-8 char - before calling mpd_parse_fmt_str(). */ - replace_fillchar = 1; - fmt = dec_strdup(fmt, size); - if (fmt == NULL) { - return NULL; - } - fmt[0] = '_'; + if (size > 0 && fmt[0] == '\0') { + /* NUL fill character: must be replaced with a valid UTF-8 char + before calling mpd_parse_fmt_str(). */ + replace_fillchar = 1; + fmt = dec_strdup(fmt, size); + if (fmt == NULL) { + return NULL; } - } - else { - PyErr_SetString(PyExc_TypeError, - "format arg must be str"); - return NULL; + fmt[0] = '_'; } if (!mpd_parse_fmt_str(&spec, fmt, CtxCaps(context))) { @@ -5389,7 +5435,7 @@ static PyMethodDef dec_methods [] = /* Special methods */ { "__copy__", dec_copy, METH_NOARGS, NULL }, { "__deepcopy__", dec_copy, METH_O, NULL }, - { "__format__", dec_format, METH_VARARGS, NULL }, + _DECIMAL_DECIMAL___FORMAT___METHODDEF { "__reduce__", dec_reduce, METH_NOARGS, NULL }, { "__round__", PyDec_Round, METH_VARARGS, NULL }, { "__ceil__", dec_ceil, METH_NOARGS, NULL }, @@ -5686,20 +5732,41 @@ ctx_mpd_qdivmod(PyObject *context, PyObject *args) } /* Binary or ternary arithmetic functions */ + +/*[clinic input] +_decimal.Context.power + + self as context: self + a as base: object + b as exp: object + modulo as mod: object = None + +Compute a**b. + +If 'a' is negative, then 'b' must be integral. The result will be +inexact unless 'a' is integral and the result is finite and can be +expressed exactly in 'precision' digits. In the Python version the +result is always correctly rounded, in the C version the result is +almost always correctly rounded. + +If modulo is given, compute (a**b) % modulo. The following +restrictions hold: + + * all three arguments must be integral + * 'b' must be nonnegative + * at least one of 'a' or 'b' must be nonzero + * modulo must be nonzero and less than 10**prec in absolute value +[clinic start generated code]*/ + static PyObject * -ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds) +_decimal_Context_power_impl(PyObject *context, PyObject *base, PyObject *exp, + PyObject *mod) +/*[clinic end generated code: output=d2e68694ec545245 input=e9aef844813de243]*/ { - static char *kwlist[] = {"a", "b", "modulo", NULL}; - PyObject *base, *exp, *mod = Py_None; PyObject *a, *b, *c = NULL; PyObject *result; uint32_t status = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, - &base, &exp, &mod)) { - return NULL; - } - CONVERT_BINOP_RAISE(&a, &b, base, exp, context); if (mod != Py_None) { @@ -6020,7 +6087,7 @@ static PyMethodDef context_methods [] = { "subtract", ctx_mpd_qsub, METH_VARARGS, doc_ctx_subtract }, /* Binary or ternary arithmetic functions */ - { "power", _PyCFunction_CAST(ctx_mpd_qpow), METH_VARARGS|METH_KEYWORDS, doc_ctx_power }, + _DECIMAL_CONTEXT_POWER_METHODDEF /* Ternary arithmetic functions */ { "fma", ctx_mpd_qfma, METH_VARARGS, doc_ctx_fma }, @@ -6117,10 +6184,10 @@ static PyType_Spec context_spec = { static PyMethodDef _decimal_methods [] = { - { "getcontext", PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext}, - { "setcontext", PyDec_SetCurrentContext, METH_O, doc_setcontext}, - { "localcontext", _PyCFunction_CAST(ctxmanager_new), METH_VARARGS|METH_KEYWORDS, doc_localcontext}, - { "IEEEContext", ieee_context, METH_O, doc_ieee_context}, + _DECIMAL_GETCONTEXT_METHODDEF + _DECIMAL_SETCONTEXT_METHODDEF + _DECIMAL_LOCALCONTEXT_METHODDEF + _DECIMAL_IEEECONTEXT_METHODDEF { NULL, NULL, 1, NULL } }; diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index 441515edbf60f6..7a2bcce1e9316b 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -6,8 +6,206 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +PyDoc_STRVAR(_decimal_IEEEContext__doc__, +"IEEEContext($module, bits, /)\n" +"--\n" +"\n" +"Return a context, initialized as one of the IEEE interchange formats.\n" +"\n" +"The argument must be a multiple of 32 and less than\n" +"IEEE_CONTEXT_MAX_BITS."); + +#define _DECIMAL_IEEECONTEXT_METHODDEF \ + {"IEEEContext", (PyCFunction)_decimal_IEEEContext, METH_O, _decimal_IEEEContext__doc__}, + +static PyObject * +_decimal_IEEEContext_impl(PyObject *module, Py_ssize_t bits); + +static PyObject * +_decimal_IEEEContext(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_ssize_t bits; + + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bits = ival; + } + return_value = _decimal_IEEEContext_impl(module, bits); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_getcontext__doc__, +"getcontext($module, /)\n" +"--\n" +"\n" +"Get the current default context."); + +#define _DECIMAL_GETCONTEXT_METHODDEF \ + {"getcontext", (PyCFunction)_decimal_getcontext, METH_NOARGS, _decimal_getcontext__doc__}, + +static PyObject * +_decimal_getcontext_impl(PyObject *module); + +static PyObject * +_decimal_getcontext(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_getcontext_impl(module); +} + +PyDoc_STRVAR(_decimal_setcontext__doc__, +"setcontext($module, context, /)\n" +"--\n" +"\n" +"Set a new default context."); + +#define _DECIMAL_SETCONTEXT_METHODDEF \ + {"setcontext", (PyCFunction)_decimal_setcontext, METH_O, _decimal_setcontext__doc__}, + +PyDoc_STRVAR(_decimal_localcontext__doc__, +"localcontext($module, /, ctx=None, **kwargs)\n" +"--\n" +"\n" +"Return a context manager for a copy of the supplied context.\n" +"\n" +"That will set the default context to a copy of ctx on entry to the\n" +"with-statement and restore the previous default context when exiting\n" +"the with-statement. If no context is specified, a copy of the current\n" +"default context is used."); + +#define _DECIMAL_LOCALCONTEXT_METHODDEF \ + {"localcontext", _PyCFunction_CAST(_decimal_localcontext), METH_FASTCALL|METH_KEYWORDS, _decimal_localcontext__doc__}, + +static PyObject * +_decimal_localcontext_impl(PyObject *module, PyObject *local, PyObject *prec, + PyObject *rounding, PyObject *Emin, + PyObject *Emax, PyObject *capitals, + PyObject *clamp, PyObject *flags, PyObject *traps); + +static PyObject * +_decimal_localcontext(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 9 + 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(ctx), &_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[] = {"ctx", "prec", "rounding", "Emin", "Emax", "capitals", "clamp", "flags", "traps", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "localcontext", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[9]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *local = Py_None; + 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 *flags = Py_None; + PyObject *traps = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + local = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + prec = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + rounding = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + Emin = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + Emax = args[4]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[5]) { + capitals = args[5]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[6]) { + clamp = args[6]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[7]) { + flags = args[7]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + traps = args[8]; +skip_optional_kwonly: + return_value = _decimal_localcontext_impl(module, local, prec, rounding, Emin, Emax, capitals, clamp, flags, traps); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal_from_float__doc__, "from_float($type, f, /)\n" "--\n" @@ -71,6 +269,45 @@ _decimal_Decimal_from_number(PyObject *type, PyObject *number) return return_value; } +PyDoc_STRVAR(_decimal_Decimal___format____doc__, +"__format__($self, format_spec, override=, /)\n" +"--\n" +"\n" +"Formats the Decimal according to format_spec."); + +#define _DECIMAL_DECIMAL___FORMAT___METHODDEF \ + {"__format__", _PyCFunction_CAST(_decimal_Decimal___format__), METH_FASTCALL, _decimal_Decimal___format____doc__}, + +static PyObject * +_decimal_Decimal___format___impl(PyObject *dec, PyObject *fmtarg, + PyObject *override); + +static PyObject * +_decimal_Decimal___format__(PyObject *dec, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *fmtarg; + PyObject *override = NULL; + + if (!_PyArg_CheckPositional("__format__", nargs, 1, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("__format__", "argument 1", "str", args[0]); + goto exit; + } + fmtarg = args[0]; + if (nargs < 2) { + goto skip_optional; + } + override = args[1]; +skip_optional: + return_value = _decimal_Decimal___format___impl(dec, fmtarg, override); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal_as_integer_ratio__doc__, "as_integer_ratio($self, /)\n" "--\n" @@ -846,4 +1083,86 @@ _decimal_Decimal_quantize(PyObject *self, PyObject *const *args, Py_ssize_t narg exit: return return_value; } -/*[clinic end generated code: output=f33166d1bf53e613 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_decimal_Context_power__doc__, +"power($self, /, a, b, modulo=None)\n" +"--\n" +"\n" +"Compute a**b.\n" +"\n" +"If \'a\' is negative, then \'b\' must be integral. The result will be\n" +"inexact unless \'a\' is integral and the result is finite and can be\n" +"expressed exactly in \'precision\' digits. In the Python version the\n" +"result is always correctly rounded, in the C version the result is\n" +"almost always correctly rounded.\n" +"\n" +"If modulo is given, compute (a**b) % modulo. The following\n" +"restrictions hold:\n" +"\n" +" * all three arguments must be integral\n" +" * \'b\' must be nonnegative\n" +" * at least one of \'a\' or \'b\' must be nonzero\n" +" * modulo must be nonzero and less than 10**prec in absolute value"); + +#define _DECIMAL_CONTEXT_POWER_METHODDEF \ + {"power", _PyCFunction_CAST(_decimal_Context_power), METH_FASTCALL|METH_KEYWORDS, _decimal_Context_power__doc__}, + +static PyObject * +_decimal_Context_power_impl(PyObject *context, PyObject *base, PyObject *exp, + PyObject *mod); + +static PyObject * +_decimal_Context_power(PyObject *context, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + 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_LATIN1_CHR('a'), _Py_LATIN1_CHR('b'), &_Py_ID(modulo), }, + }; + #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[] = {"a", "b", "modulo", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "power", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *base; + PyObject *exp; + PyObject *mod = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + base = args[0]; + exp = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + mod = args[2]; +skip_optional_pos: + return_value = _decimal_Context_power_impl(context, base, exp, mod); + +exit: + return return_value; +} +/*[clinic end generated code: output=6bb5c926552c2760 input=a9049054013a1b77]*/ diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h index bd1c1d5295d717..3ecfd34122ab6b 100644 --- a/Modules/_decimal/docstrings.h +++ b/Modules/_decimal/docstrings.h @@ -19,32 +19,6 @@ PyDoc_STRVAR(doc__decimal, "C decimal arithmetic module"); -PyDoc_STRVAR(doc_getcontext, -"getcontext($module, /)\n--\n\n\ -Get the current default context.\n\ -\n"); - -PyDoc_STRVAR(doc_setcontext, -"setcontext($module, context, /)\n--\n\n\ -Set a new default context.\n\ -\n"); - -PyDoc_STRVAR(doc_localcontext, -"localcontext($module, /, ctx=None, **kwargs)\n--\n\n\ -Return a context manager that will set the default context to a copy of ctx\n\ -on entry to the with-statement and restore the previous default context when\n\ -exiting the with-statement. If no context is specified, a copy of the current\n\ -default context is used.\n\ -\n"); - -PyDoc_STRVAR(doc_ieee_context, -"IEEEContext($module, bits, /)\n--\n\n\ -Return a context object initialized to the proper values for one of the\n\ -IEEE interchange formats. The argument must be a multiple of 32 and less\n\ -than IEEE_CONTEXT_MAX_BITS.\n\ -\n"); - - /******************************************************************************/ /* Decimal Object and Methods */ /******************************************************************************/ @@ -619,24 +593,6 @@ Plus corresponds to the unary prefix plus operator in Python, but applies\n\ the context to the result.\n\ \n"); -PyDoc_STRVAR(doc_ctx_power, -"power($self, /, a, b, modulo=None)\n--\n\n\ -Compute a**b. If 'a' is negative, then 'b' must be integral. The result\n\ -will be inexact unless 'a' is integral and the result is finite and can\n\ -be expressed exactly in 'precision' digits. In the Python version the\n\ -result is always correctly rounded, in the C version the result is almost\n\ -always correctly rounded.\n\ -\n\ -If modulo is given, compute (a**b) % modulo. The following restrictions\n\ -hold:\n\ -\n\ - * all three arguments must be integral\n\ - * 'b' must be nonnegative\n\ - * at least one of 'a' or 'b' must be nonzero\n\ - * modulo must be nonzero and less than 10**prec in absolute value\n\ -\n\ -\n"); - PyDoc_STRVAR(doc_ctx_quantize, "quantize($self, x, y, /)\n--\n\n\ Return a value equal to x (rounded), having the exponent of y.\n\