@@ -1333,32 +1333,37 @@ context_setattr(PyObject *self, PyObject *name, PyObject *value)
13331333 return PyObject_GenericSetAttr (self , name , value );
13341334}
13351335
1336+ /* In the constructor and in localcontext() None means "not specified". */
1337+ #define NONE_TO_NULL (x ) ((x) == Py_None ? NULL : (x))
1338+
1339+ /* Set the given attributes. An attribute is left unchanged if the
1340+ corresponding argument is NULL. */
13361341static int
13371342context_setattrs (PyObject * self , PyObject * prec , PyObject * rounding ,
13381343 PyObject * emin , PyObject * emax , PyObject * capitals ,
13391344 PyObject * clamp , PyObject * status , PyObject * traps ) {
13401345
13411346 int ret ;
1342- if (prec != Py_None && context_setprec (self , prec , NULL ) < 0 ) {
1347+ if (prec != NULL && context_setprec (self , prec , NULL ) < 0 ) {
13431348 return -1 ;
13441349 }
1345- if (rounding != Py_None && context_setround (self , rounding , NULL ) < 0 ) {
1350+ if (rounding != NULL && context_setround (self , rounding , NULL ) < 0 ) {
13461351 return -1 ;
13471352 }
1348- if (emin != Py_None && context_setemin (self , emin , NULL ) < 0 ) {
1353+ if (emin != NULL && context_setemin (self , emin , NULL ) < 0 ) {
13491354 return -1 ;
13501355 }
1351- if (emax != Py_None && context_setemax (self , emax , NULL ) < 0 ) {
1356+ if (emax != NULL && context_setemax (self , emax , NULL ) < 0 ) {
13521357 return -1 ;
13531358 }
1354- if (capitals != Py_None && context_setcapitals (self , capitals , NULL ) < 0 ) {
1359+ if (capitals != NULL && context_setcapitals (self , capitals , NULL ) < 0 ) {
13551360 return -1 ;
13561361 }
1357- if (clamp != Py_None && context_setclamp (self , clamp , NULL ) < 0 ) {
1362+ if (clamp != NULL && context_setclamp (self , clamp , NULL ) < 0 ) {
13581363 return -1 ;
13591364 }
13601365
1361- if (traps != Py_None ) {
1366+ if (traps != NULL ) {
13621367 if (PyList_Check (traps )) {
13631368 ret = context_settraps_list (self , traps );
13641369 }
@@ -1374,7 +1379,7 @@ context_setattrs(PyObject *self, PyObject *prec, PyObject *rounding,
13741379 return ret ;
13751380 }
13761381 }
1377- if (status != Py_None ) {
1382+ if (status != NULL ) {
13781383 if (PyList_Check (status )) {
13791384 ret = context_setstatus_list (self , status );
13801385 }
@@ -1559,10 +1564,11 @@ context_init_impl(PyObject *self, PyObject *prec, PyObject *rounding,
15591564 PyObject * clamp , PyObject * status , PyObject * traps )
15601565/*[clinic end generated code: output=8bfdc59fbe862f44 input=45c704b93cd02959]*/
15611566{
1567+ /* The context has already been initialized with the default values. */
15621568 return context_setattrs (
1563- self , prec , rounding ,
1564- emin , emax , capitals ,
1565- clamp , status , traps
1569+ self , NONE_TO_NULL ( prec ), NONE_TO_NULL ( rounding ) ,
1570+ NONE_TO_NULL ( emin ), NONE_TO_NULL ( emax ), NONE_TO_NULL ( capitals ) ,
1571+ NONE_TO_NULL ( clamp ), NONE_TO_NULL ( status ), NONE_TO_NULL ( traps )
15661572 );
15671573}
15681574
@@ -1716,6 +1722,47 @@ _decimal_Context___copy___impl(PyObject *self, PyTypeObject *cls)
17161722 return context_copy (state , self );
17171723}
17181724
1725+ /*[clinic input]
1726+ @text_signature "($self, /, **changes)"
1727+ _decimal.Context.__replace__
1728+
1729+ cls: defining_class
1730+ *
1731+ prec: object = NULL
1732+ rounding: object = NULL
1733+ Emin as emin: object = NULL
1734+ Emax as emax: object = NULL
1735+ capitals: object = NULL
1736+ clamp: object = NULL
1737+ flags as status: object = NULL
1738+ traps: object = NULL
1739+
1740+ Return a copy of the context with the specified attributes replaced.
1741+ [clinic start generated code]*/
1742+
1743+ static PyObject *
1744+ _decimal_Context___replace___impl (PyObject * self , PyTypeObject * cls ,
1745+ PyObject * prec , PyObject * rounding ,
1746+ PyObject * emin , PyObject * emax ,
1747+ PyObject * capitals , PyObject * clamp ,
1748+ PyObject * status , PyObject * traps )
1749+ /*[clinic end generated code: output=375ef0392df682ec input=414d9d00b25af6f3]*/
1750+ {
1751+ decimal_state * state = PyType_GetModuleState (cls );
1752+
1753+ PyObject * result = context_copy (state , self );
1754+ if (result == NULL ) {
1755+ return NULL ;
1756+ }
1757+ if (context_setattrs (result , prec , rounding , emin , emax , capitals ,
1758+ clamp , status , traps ) < 0 )
1759+ {
1760+ Py_DECREF (result );
1761+ return NULL ;
1762+ }
1763+ return result ;
1764+ }
1765+
17191766/*[clinic input]
17201767_decimal.Context.__reduce__ = _decimal.Context.copy
17211768
@@ -2095,9 +2142,9 @@ _decimal_localcontext_impl(PyObject *module, PyObject *local, PyObject *prec,
20952142 }
20962143
20972144 int ret = context_setattrs (
2098- local_copy , prec , rounding ,
2099- Emin , Emax , capitals ,
2100- clamp , flags , traps
2145+ local_copy , NONE_TO_NULL ( prec ), NONE_TO_NULL ( rounding ) ,
2146+ NONE_TO_NULL ( Emin ), NONE_TO_NULL ( Emax ), NONE_TO_NULL ( capitals ) ,
2147+ NONE_TO_NULL ( clamp ), NONE_TO_NULL ( flags ), NONE_TO_NULL ( traps )
21012148 );
21022149 if (ret < 0 ) {
21032150 Py_DECREF (local_copy );
@@ -7557,6 +7604,7 @@ static PyMethodDef context_methods [] =
75577604
75587605 /* Miscellaneous */
75597606 _DECIMAL_CONTEXT___COPY___METHODDEF
7607+ _DECIMAL_CONTEXT___REPLACE___METHODDEF
75607608 _DECIMAL_CONTEXT___REDUCE___METHODDEF
75617609 _DECIMAL_CONTEXT_COPY_METHODDEF
75627610 _DECIMAL_CONTEXT_CREATE_DECIMAL_METHODDEF
0 commit comments