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

Skip to content

Commit 243d8a7

Browse files
author
Stefan Krah
committed
Merge 3.5.
2 parents caaf53e + 8c126f1 commit 243d8a7

2 files changed

Lines changed: 79 additions & 8 deletions

File tree

Lib/test/test_decimal.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,6 +5431,34 @@ def test_sizeof(self):
54315431
y = Decimal(10**(9*25)).__sizeof__()
54325432
self.assertEqual(y, x+4)
54335433

5434+
def test_internal_use_of_overridden_methods(self):
5435+
Decimal = C.Decimal
5436+
5437+
# Unsound subtyping
5438+
class X(float):
5439+
def as_integer_ratio(self):
5440+
return 1
5441+
def __abs__(self):
5442+
return self
5443+
5444+
class Y(float):
5445+
def __abs__(self):
5446+
return [1]*200
5447+
5448+
class I(int):
5449+
def bit_length(self):
5450+
return [1]*200
5451+
5452+
class Z(float):
5453+
def as_integer_ratio(self):
5454+
return (I(1), I(1))
5455+
def __abs__(self):
5456+
return self
5457+
5458+
for cls in X, Y, Z:
5459+
self.assertEqual(Decimal.from_float(cls(101.1)),
5460+
Decimal.from_float(101.1))
5461+
54345462
@requires_docstrings
54355463
@unittest.skipUnless(C, "test requires C version")
54365464
class SignatureTest(unittest.TestCase):

Modules/_decimal/_decimal.c

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,14 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong,
22072207
return dec;
22082208
}
22092209

2210+
/* External C-API functions */
2211+
static binaryfunc _py_long_multiply;
2212+
static binaryfunc _py_long_floor_divide;
2213+
static ternaryfunc _py_long_power;
2214+
static unaryfunc _py_float_abs;
2215+
static PyCFunction _py_long_bit_length;
2216+
static PyCFunction _py_float_as_integer_ratio;
2217+
22102218
/* Return a PyDecObject or a subtype from a PyFloatObject.
22112219
Conversion is exact. */
22122220
static PyObject *
@@ -2257,21 +2265,21 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
22572265
}
22582266

22592267
/* absolute value of the float */
2260-
tmp = PyObject_CallMethod(v, "__abs__", NULL);
2268+
tmp = _py_float_abs(v);
22612269
if (tmp == NULL) {
22622270
return NULL;
22632271
}
22642272

22652273
/* float as integer ratio: numerator/denominator */
2266-
n_d = PyObject_CallMethod(tmp, "as_integer_ratio", NULL);
2274+
n_d = _py_float_as_integer_ratio(tmp, NULL);
22672275
Py_DECREF(tmp);
22682276
if (n_d == NULL) {
22692277
return NULL;
22702278
}
22712279
n = PyTuple_GET_ITEM(n_d, 0);
22722280
d = PyTuple_GET_ITEM(n_d, 1);
22732281

2274-
tmp = PyObject_CallMethod(d, "bit_length", NULL);
2282+
tmp = _py_long_bit_length(d, NULL);
22752283
if (tmp == NULL) {
22762284
Py_DECREF(n_d);
22772285
return NULL;
@@ -3397,7 +3405,6 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
33973405
mpd_ssize_t exp;
33983406
PyObject *context;
33993407
uint32_t status = 0;
3400-
PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
34013408

34023409
if (mpd_isspecial(MPD(self))) {
34033410
if (mpd_isnan(MPD(self))) {
@@ -3444,14 +3451,14 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
34443451
goto error;
34453452
}
34463453

3447-
Py_SETREF(exponent, long_methods->nb_power(tmp, exponent, Py_None));
3454+
Py_SETREF(exponent, _py_long_power(tmp, exponent, Py_None));
34483455
Py_DECREF(tmp);
34493456
if (exponent == NULL) {
34503457
goto error;
34513458
}
34523459

34533460
if (exp >= 0) {
3454-
Py_SETREF(numerator, long_methods->nb_multiply(numerator, exponent));
3461+
Py_SETREF(numerator, _py_long_multiply(numerator, exponent));
34553462
if (numerator == NULL) {
34563463
goto error;
34573464
}
@@ -3467,8 +3474,8 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
34673474
if (tmp == NULL) {
34683475
goto error;
34693476
}
3470-
Py_SETREF(numerator, long_methods->nb_floor_divide(numerator, tmp));
3471-
Py_SETREF(denominator, long_methods->nb_floor_divide(denominator, tmp));
3477+
Py_SETREF(numerator, _py_long_floor_divide(numerator, tmp));
3478+
Py_SETREF(denominator, _py_long_floor_divide(denominator, tmp));
34723479
Py_DECREF(tmp);
34733480
if (numerator == NULL || denominator == NULL) {
34743481
goto error;
@@ -5611,6 +5618,32 @@ static struct int_constmap int_constants [] = {
56115618
#define CHECK_PTR(expr) \
56125619
do { if ((expr) == NULL) goto error; } while (0)
56135620

5621+
5622+
static PyCFunction
5623+
cfunc_noargs(PyTypeObject *t, const char *name)
5624+
{
5625+
struct PyMethodDef *m;
5626+
5627+
if (t->tp_methods == NULL) {
5628+
goto error;
5629+
}
5630+
5631+
for (m = t->tp_methods; m->ml_name != NULL; m++) {
5632+
if (strcmp(name, m->ml_name) == 0) {
5633+
if (!(m->ml_flags & METH_NOARGS)) {
5634+
goto error;
5635+
}
5636+
return m->ml_meth;
5637+
}
5638+
}
5639+
5640+
error:
5641+
PyErr_Format(PyExc_RuntimeError,
5642+
"internal error: could not find method %s", name);
5643+
return NULL;
5644+
}
5645+
5646+
56145647
PyMODINIT_FUNC
56155648
PyInit__decimal(void)
56165649
{
@@ -5635,6 +5668,16 @@ PyInit__decimal(void)
56355668
mpd_setminalloc(_Py_DEC_MINALLOC);
56365669

56375670

5671+
/* Init external C-API functions */
5672+
_py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
5673+
_py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
5674+
_py_long_power = PyLong_Type.tp_as_number->nb_power;
5675+
_py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
5676+
ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type,
5677+
"as_integer_ratio"));
5678+
ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length"));
5679+
5680+
56385681
/* Init types */
56395682
PyDec_Type.tp_base = &PyBaseObject_Type;
56405683
PyDecContext_Type.tp_base = &PyBaseObject_Type;

0 commit comments

Comments
 (0)