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

Skip to content

Commit 180d7b4

Browse files
committed
* Python/ceval.c, Include/ceval.h: promote MakePendingCalls to
global: Py_MakePendingCalls. Also guard against recursive calls * Include/classobject.h, Objects/classobject.c, Python/{ceval.c,bltinmodule.c}: entirely redone operator overloading. The rules for class instances are now much more relaxed than for other built-in types (whose coerce must still return two objects of the same type)
1 parent fe3f1a2 commit 180d7b4

2 files changed

Lines changed: 48 additions & 10 deletions

File tree

Python/bltinmodule.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ builtin_coerce(self, args)
243243

244244
if (!getargs(args, "(OO)", &v, &w))
245245
return NULL;
246+
if (is_instanceobject(v) || is_instanceobject(w))
247+
return instancebinop(v, w, "__coerce__", "__rcoerce__");
246248
if (coerce(&v, &w) < 0)
247249
return NULL;
248250
res = mkvalue("(OO)", v, w);
@@ -314,9 +316,11 @@ builtin_divmod(self, args)
314316
object *v, *w, *x;
315317
if (!getargs(args, "(OO)", &v, &w))
316318
return NULL;
319+
if (is_instanceobject(v) || is_instanceobject(w))
320+
return instancebinop(v, w, "__divmod__", "__rdivmod__");
317321
if (v->ob_type->tp_as_number == NULL ||
318322
w->ob_type->tp_as_number == NULL) {
319-
err_setstr(TypeError, "divmod() requires numeric arguments");
323+
err_setstr(TypeError, "divmod() requires numeric or class instance arguments");
320324
return NULL;
321325
}
322326
if (coerce(&v, &w) != 0)
@@ -876,11 +880,16 @@ builtin_pow(self, args)
876880
{
877881
object *v, *w, *z, *x;
878882
z = None;
879-
if (!getargs(args, "(OO)", &v, &w)) {
880-
err_clear();
881-
if (!getargs(args, "(OOO)", &v, &w, &z)) {
882-
return NULL;
883-
}
883+
if (!newgetargs(args, "OO|O", &v, &w, &z))
884+
return NULL;
885+
if (z == None) {
886+
if (is_instanceobject(v) || is_instanceobject(w))
887+
return instancebinop(v, w, "__pow__", "__rpow__");
888+
}
889+
else {
890+
/* XXX The ternary version doesn't do coercions */
891+
if (is_instanceobject(v))
892+
return v->ob_type->tp_as_number->nb_power(v, w, z);
884893
}
885894
if (v->ob_type->tp_as_number == NULL ||
886895
(z!=None && z->ob_type->tp_as_number == NULL) ||

Python/ceval.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,28 +196,37 @@ Py_AddPendingCall(func, arg)
196196
int (*func) PROTO((ANY *));
197197
ANY *arg;
198198
{
199+
static int busy = 0;
199200
int i, j;
200201
/* XXX Begin critical section */
201202
/* XXX If you want this to be safe against nested
202203
XXX asynchronous calls, you'll have to work harder! */
204+
if (busy)
205+
return -1;
206+
busy = 1;
203207
i = pendinglast;
204208
j = (i + 1) % NPENDINGCALLS;
205209
if (j == pendingfirst)
206210
return -1; /* Queue full */
207211
pendingcalls[i].func = func;
208212
pendingcalls[i].arg = arg;
209213
pendinglast = j;
214+
busy = 0;
210215
/* XXX End critical section */
211216
return 0;
212217
}
213218

214-
static int
215-
MakePendingCalls()
219+
int
220+
Py_MakePendingCalls()
216221
{
222+
static int busy = 0;
217223
#ifdef WITH_THREAD
218224
if (get_thread_ident() != main_thread)
219225
return 0;
220226
#endif
227+
if (busy)
228+
return 0;
229+
busy = 1;
221230
for (;;) {
222231
int i;
223232
int (*func) PROTO((ANY *));
@@ -228,9 +237,12 @@ MakePendingCalls()
228237
func = pendingcalls[i].func;
229238
arg = pendingcalls[i].arg;
230239
pendingfirst = (i + 1) % NPENDINGCALLS;
231-
if (func(arg) < 0)
240+
if (func(arg) < 0) {
241+
busy = 0;
232242
return -1;
243+
}
233244
}
245+
busy = 0;
234246
return 0;
235247
}
236248

@@ -398,7 +410,7 @@ eval_code(co, globals, locals, owner, arg)
398410
So we do it only every Nth instruction. */
399411

400412
if (pendingfirst != pendinglast) {
401-
if (MakePendingCalls() < 0) {
413+
if (Py_MakePendingCalls() < 0) {
402414
why = WHY_EXCEPTION;
403415
goto on_error;
404416
}
@@ -1736,10 +1748,18 @@ flushline()
17361748
}
17371749

17381750

1751+
#define BINOP(opname, ropname) \
1752+
do { \
1753+
if (is_instanceobject(v) || is_instanceobject(w)) \
1754+
return instancebinop(v, w, opname, ropname); \
1755+
} while (0)
1756+
1757+
17391758
static object *
17401759
or(v, w)
17411760
object *v, *w;
17421761
{
1762+
BINOP("__or__", "__ror__");
17431763
if (v->ob_type->tp_as_number != NULL) {
17441764
object *x;
17451765
object * (*f) FPROTO((object *, object *));
@@ -1760,6 +1780,7 @@ static object *
17601780
xor(v, w)
17611781
object *v, *w;
17621782
{
1783+
BINOP("__xor__", "__rxor__");
17631784
if (v->ob_type->tp_as_number != NULL) {
17641785
object *x;
17651786
object * (*f) FPROTO((object *, object *));
@@ -1780,6 +1801,7 @@ static object *
17801801
and(v, w)
17811802
object *v, *w;
17821803
{
1804+
BINOP("__and__", "__rand__");
17831805
if (v->ob_type->tp_as_number != NULL) {
17841806
object *x;
17851807
object * (*f) FPROTO((object *, object *));
@@ -1800,6 +1822,7 @@ static object *
18001822
lshift(v, w)
18011823
object *v, *w;
18021824
{
1825+
BINOP("__lshift__", "__rshift__");
18031826
if (v->ob_type->tp_as_number != NULL) {
18041827
object *x;
18051828
object * (*f) FPROTO((object *, object *));
@@ -1820,6 +1843,7 @@ static object *
18201843
rshift(v, w)
18211844
object *v, *w;
18221845
{
1846+
BINOP("__rshift__", "__rrshift__");
18231847
if (v->ob_type->tp_as_number != NULL) {
18241848
object *x;
18251849
object * (*f) FPROTO((object *, object *));
@@ -1840,6 +1864,7 @@ static object *
18401864
add(v, w)
18411865
object *v, *w;
18421866
{
1867+
BINOP("__add__", "__radd__");
18431868
if (v->ob_type->tp_as_sequence != NULL)
18441869
return (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
18451870
else if (v->ob_type->tp_as_number != NULL) {
@@ -1859,6 +1884,7 @@ static object *
18591884
sub(v, w)
18601885
object *v, *w;
18611886
{
1887+
BINOP("__sub__", "__rsub__");
18621888
if (v->ob_type->tp_as_number != NULL) {
18631889
object *x;
18641890
if (coerce(&v, &w) != 0)
@@ -1878,6 +1904,7 @@ mul(v, w)
18781904
{
18791905
typeobject *tp;
18801906
tp = v->ob_type;
1907+
BINOP("__mul__", "__rmul__");
18811908
if (tp->tp_as_number != NULL &&
18821909
w->ob_type->tp_as_sequence != NULL &&
18831910
!is_instanceobject(v)) {
@@ -1921,6 +1948,7 @@ static object *
19211948
divide(v, w)
19221949
object *v, *w;
19231950
{
1951+
BINOP("__div__", "__rdiv__");
19241952
if (v->ob_type->tp_as_number != NULL) {
19251953
object *x;
19261954
if (coerce(&v, &w) != 0)
@@ -1938,6 +1966,7 @@ static object *
19381966
rem(v, w)
19391967
object *v, *w;
19401968
{
1969+
BINOP("__mod__", "__rmod__");
19411970
if (v->ob_type->tp_as_number != NULL) {
19421971
object *x;
19431972
if (coerce(&v, &w) != 0)

0 commit comments

Comments
 (0)