Get rid of most of the rest of coerce (slot is still there for now).

This commit is contained in:
Neal Norwitz 2006-08-21 17:06:07 +00:00
parent 79212998a8
commit 4886cc331f
19 changed files with 131 additions and 497 deletions

28
BROKEN
View file

@ -110,3 +110,31 @@ Traceback (most recent call last):
File "../Lib/test/test_set.py", line 291, in test_remove
self.assert_(self.thetype(self.word) in s)
AssertionError
////////////////////////////////////////////////////////////////////////
test_compare
////////////////////////////////////////////////////////////////////////
test test_compare failed -- Traceback (most recent call last):
File "/Users/nnorwitz/build/python/py3k.2/Lib/test/test_compare.py", line 28, in test_comparisons
self.assertEqual(a, b)
AssertionError: 2 != (2+0j)
////////////////////////////////////////////////////////////////////////
test_complex
////////////////////////////////////////////////////////////////////////
======================================================================
FAIL: test_pow (test.test_complex.ComplexTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/nnorwitz/build/python/py3k.2/Lib/test/test_complex.py", line 130, in test_pow
self.assertEqual(a ** 0j, 1)
AssertionError: (1+0j) != 1
======================================================================
FAIL: test_richcompare (test.test_complex.ComplexTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/nnorwitz/build/python/py3k.2/Lib/test/test_complex.py", line 96, in test_richcompare
self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
AssertionError: OverflowError not raised

View file

@ -654,20 +654,6 @@ determination.
statement \samp{\var{o1} |= \var{o2}}.
\end{cfuncdesc}
\begin{cfuncdesc}{int}{PyNumber_Coerce}{PyObject **p1, PyObject **p2}
This function takes the addresses of two variables of type
\ctype{PyObject*}. If the objects pointed to by \code{*\var{p1}}
and \code{*\var{p2}} have the same type, increment their reference
count and return \code{0} (success). If the objects can be converted
to a common numeric type, replace \code{*p1} and \code{*p2} by their
converted value (with 'new' reference counts), and return \code{0}.
If no conversion is possible, or if some other error occurs, return
\code{-1} (failure) and don't increment the reference counts. The
call \code{PyNumber_Coerce(\&o1, \&o2)} is equivalent to the Python
statement \samp{\var{o1}, \var{o2} = coerce(\var{o1}, \var{o2})}.
\bifuncindex{coerce}
\end{cfuncdesc}
\begin{cfuncdesc}{PyObject*}{PyNumber_Int}{PyObject *o}
Returns the \var{o} converted to an integer object on success, or
\NULL{} on failure. If the argument is outside the integer range

View file

@ -1645,7 +1645,7 @@ sequence types should implement addition (meaning concatenation) and
multiplication (meaning repetition) by defining the methods
\method{__add__()}, \method{__radd__()}, \method{__iadd__()},
\method{__mul__()}, \method{__rmul__()} and \method{__imul__()} described
below; they should not define \method{__coerce__()} or other numerical
below; they should not define other numerical
operators. It is recommended that both mappings and sequences
implement the \method{__contains__()} method to allow efficient use of
the \code{in} operator; for mappings, \code{in} should be equivalent
@ -1689,7 +1689,7 @@ through the values.
\ttindex{__imul__()}
\ttindex{__contains__()}
\ttindex{__iter__()}}
\withsubitem{(numeric object method)}{\ttindex{__coerce__()}}
\withsubitem{(numeric object method)}
\begin{methoddesc}[container object]{__len__}{self}
Called to implement the built-in function
@ -2012,129 +2012,6 @@ integer (int or long).
\versionadded{2.5}
\end{methoddesc}
\begin{methoddesc}[numeric object]{__coerce__}{self, other}
Called to implement ``mixed-mode'' numeric arithmetic. Should either
return a 2-tuple containing \var{self} and \var{other} converted to
a common numeric type, or \code{None} if conversion is impossible. When
the common type would be the type of \code{other}, it is sufficient to
return \code{None}, since the interpreter will also ask the other
object to attempt a coercion (but sometimes, if the implementation of
the other type cannot be changed, it is useful to do the conversion to
the other type here). A return value of \code{NotImplemented} is
equivalent to returning \code{None}.
\end{methoddesc}
\subsection{Coercion rules\label{coercion-rules}}
This section used to document the rules for coercion. As the language
has evolved, the coercion rules have become hard to document
precisely; documenting what one version of one particular
implementation does is undesirable. Instead, here are some informal
guidelines regarding coercion. In Python 3.0, coercion will not be
supported.
\begin{itemize}
\item
If the left operand of a \% operator is a string or Unicode object, no
coercion takes place and the string formatting operation is invoked
instead.
\item
It is no longer recommended to define a coercion operation.
Mixed-mode operations on types that don't define coercion pass the
original arguments to the operation.
\item
New-style classes (those derived from \class{object}) never invoke the
\method{__coerce__()} method in response to a binary operator; the only
time \method{__coerce__()} is invoked is when the built-in function
\function{coerce()} is called.
\item
For most intents and purposes, an operator that returns
\code{NotImplemented} is treated the same as one that is not
implemented at all.
\item
Below, \method{__op__()} and \method{__rop__()} are used to signify
the generic method names corresponding to an operator;
\method{__iop__()} is used for the corresponding in-place operator. For
example, for the operator `\code{+}', \method{__add__()} and
\method{__radd__()} are used for the left and right variant of the
binary operator, and \method{__iadd__()} for the in-place variant.
\item
For objects \var{x} and \var{y}, first \code{\var{x}.__op__(\var{y})}
is tried. If this is not implemented or returns \code{NotImplemented},
\code{\var{y}.__rop__(\var{x})} is tried. If this is also not
implemented or returns \code{NotImplemented}, a \exception{TypeError}
exception is raised. But see the following exception:
\item
Exception to the previous item: if the left operand is an instance of
a built-in type or a new-style class, and the right operand is an instance
of a proper subclass of that type or class and overrides the base's
\method{__rop__()} method, the right operand's \method{__rop__()} method
is tried \emph{before} the left operand's \method{__op__()} method.
This is done so that a subclass can completely override binary operators.
Otherwise, the left operand's \method{__op__()} method would always
accept the right operand: when an instance of a given class is expected,
an instance of a subclass of that class is always acceptable.
\item
When either operand type defines a coercion, this coercion is called
before that type's \method{__op__()} or \method{__rop__()} method is
called, but no sooner. If the coercion returns an object of a
different type for the operand whose coercion is invoked, part of the
process is redone using the new object.
\item
When an in-place operator (like `\code{+=}') is used, if the left
operand implements \method{__iop__()}, it is invoked without any
coercion. When the operation falls back to \method{__op__()} and/or
\method{__rop__()}, the normal coercion rules apply.
\item
In \var{x}\code{+}\var{y}, if \var{x} is a sequence that implements
sequence concatenation, sequence concatenation is invoked.
\item
In \var{x}\code{*}\var{y}, if one operator is a sequence that
implements sequence repetition, and the other is an integer
(\class{int} or \class{long}), sequence repetition is invoked.
\item
Rich comparisons (implemented by methods \method{__eq__()} and so on)
never use coercion. Three-way comparison (implemented by
\method{__cmp__()}) does use coercion under the same conditions as
other binary operations use it.
\item
In the current implementation, the built-in numeric types \class{int},
\class{long} and \class{float} do not use coercion; the type
\class{complex} however does use it. The difference can become
apparent when subclassing these types. Over time, the type
\class{complex} may be fixed to avoid coercion. All these types
implement a \method{__coerce__()} method, for use by the built-in
\function{coerce()} function.
\end{itemize}
\subsection{With Statement Context Managers\label{context-managers}}
\versionadded{2.5}

View file

@ -35,21 +35,6 @@ machine'' that calls the subroutines corresponding to each bytecode.
Any class which does not inherit from \class{object}. See
\emph{new-style class}.
\index{coercion}
\item[coercion]
The implicit conversion of an instance of one type to another during an
operation which involves two arguments of the same type. For example,
{}\code{int(3.15)} converts the floating point number to the integer
{}\code{3}, but in {}\code{3+4.5}, each argument is of a different type (one
int, one float), and both must be converted to the same type before they can
be added or it will raise a {}\code{TypeError}. Coercion between two
operands can be performed with the {}\code{coerce} builtin function; thus,
{}\code{3+4.5} is equivalent to calling {}\code{operator.add(*coerce(3,
4.5))} and results in {}\code{operator.add(3.0, 4.5)}. Without coercion,
all arguments of even compatible types would have to be normalized to the
same value by the programmer, e.g., {}\code{float(3)+4.5} rather than just
{}\code{3+4.5}.
\index{complex number}
\item[complex number]
An extension of the familiar real number system in which all numbers are
@ -106,17 +91,14 @@ fast style is characterized by the presence of many \keyword{try} and
\index{__future__}
\item[__future__]
A pseudo module which programmers can use to enable new language
features which are not compatible with the current interpreter. For
example, the expression \code{11/4} currently evaluates to \code{2}.
If the module in which it is executed had enabled \emph{true division}
by executing:
features which are not compatible with the current interpreter.
To enable \code{new_feature}
\begin{verbatim}
from __future__ import division
from __future__ import new_feature
\end{verbatim}
the expression \code{11/4} would evaluate to \code{2.75}. By
importing the \ulink{\module{__future__}}{../lib/module-future.html}
By importing the \ulink{\module{__future__}}{../lib/module-future.html}
module and evaluating its variables, you can see when a new feature
was first added to the language and when it will become the default:
@ -183,17 +165,10 @@ example as a key in a dictionary.
\index{integer division}
\item[integer division]
Mathematical division discarding any remainder. For example, the
expression \code{11/4} currently evaluates to \code{2} in contrast
to the \code{2.75} returned by float division. Also called
{}\emph{floor division}. When dividing two integers the outcome will
always be another integer (having the floor function applied to it).
However, if one of the operands is another numeric type (such as a
{}\class{float}), the result will be coerced (see \emph{coercion}) to
a common type. For example, an integer divided by a float will result
in a float value, possibly with a decimal fraction. Integer division
can be forced by using the \code{//} operator instead of the \code{/}
operator. See also \emph{__future__}.
Mathematical division including any remainder. The result will always
be a float. For example, the expression \code{11/4} evaluates to \code{2.75}.
Integer division can be forced by using the \code{//} operator instead
of the \code{/} operator.
\index{interactive}
\item[interactive]

View file

@ -694,24 +694,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
expression: o1|o2.
*/
/* Implemented elsewhere:
int PyNumber_Coerce(PyObject **p1, PyObject **p2);
This function takes the addresses of two variables of type
PyObject*.
If the objects pointed to by *p1 and *p2 have the same type,
increment their reference count and return 0 (success).
If the objects can be converted to a common numeric type,
replace *p1 and *p2 by their converted value (with 'new'
reference counts), and return 0.
If no conversion is possible, or if some other error occurs,
return -1 (failure) and don't increment the reference counts.
The call PyNumber_Coerce(&o1, &o2) is equivalent to the Python
statement o1, o2 = coerce(o1, o2).
*/
PyAPI_FUNC(Py_ssize_t) PyNumber_Index(PyObject *);
/*

View file

@ -393,7 +393,6 @@ PyAPI_FUNC(long) PyObject_Hash(PyObject *);
PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);
PyAPI_FUNC(int) PyObject_Not(PyObject *);
PyAPI_FUNC(int) PyCallable_Check(PyObject *);
PyAPI_FUNC(int) PyNumber_Coerce(PyObject **, PyObject **);
PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **);
PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *);

View file

@ -196,17 +196,6 @@ def test_cmp(self):
a.pop(); b.pop(); c.pop()
self.assertRaises(TypeError, cmp)
def test_coerce(self):
self.assert_(not fcmp(coerce(1, 1.1), (1.0, 1.1)))
self.assertEqual(coerce(1, 1L), (1L, 1L))
self.assert_(not fcmp(coerce(1L, 1.1), (1.0, 1.1)))
self.assertRaises(TypeError, coerce)
class BadNumber:
def __coerce__(self, other):
raise ValueError
self.assertRaises(ValueError, coerce, 42, BadNumber())
self.assertRaises(OverflowError, coerce, 0.5, int("12345" * 1000))
def test_compile(self):
compile('print 1\n', '', 'exec')
bom = '\xef\xbb\xbf'

View file

@ -92,9 +92,6 @@ def test_floordiv(self):
self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
def test_coerce(self):
self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
def test_richcompare(self):
self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)

View file

@ -2567,33 +2567,6 @@ def __ge__(self, other):
verify(eval("x %s c[y]" % op) == eval("x %s y" % op),
"x=%d, y=%d" % (x, y))
def coercions():
if verbose: print "Testing coercions..."
class I(int): pass
coerce(I(0), 0)
coerce(0, I(0))
class L(long): pass
coerce(L(0), 0)
coerce(L(0), 0L)
coerce(0, L(0))
coerce(0L, L(0))
class F(float): pass
coerce(F(0), 0)
coerce(F(0), 0L)
coerce(F(0), 0.)
coerce(0, F(0))
coerce(0L, F(0))
coerce(0., F(0))
class C(complex): pass
coerce(C(0), 0)
coerce(C(0), 0L)
coerce(C(0), 0.)
coerce(C(0), 0j)
coerce(0, C(0))
coerce(0L, C(0))
coerce(0., C(0))
coerce(0j, C(0))
def descrdoc():
if verbose: print "Testing descriptor doc strings..."
def check(descr, what):
@ -3961,11 +3934,8 @@ def check(expr, x, y):
('__and__', 'x & y', 'x &= y'),
('__or__', 'x | y', 'x |= y'),
('__xor__', 'x ^ y', 'x ^= y'),
('__coerce__', 'coerce(x, y)', None)]:
if name == '__coerce__':
rname = name
else:
rname = '__r' + name[2:]
]:
rname = '__r' + name[2:]
A = metaclass('A', (), {name: specialmethod})
B = metaclass('B', (), {rname: specialmethod})
a = A()
@ -4043,7 +4013,6 @@ def test_main():
str_subclass_as_dict_key()
classic_comparisons()
rich_comparisons()
coercions()
descrdoc()
setclass()
setdict()

View file

@ -7,6 +7,87 @@ Python News
What's New in Python 3000?
==========================
*Release date: XX-XXX-200X*
TO DO
-----
- See PEP 3000.
- Test merging certain changes from the 2.5 HEAD code.
- Weed really old/weird stuff from the library.
- Unify range() and xrange().
- Revamp the dict API: keys(), values(), items() return iterators, etc.
- Add the bytes type.
- Rework the standard I/O library to use bytes for binary files.
- Make strings all Unicode.
- Get rid of classic class implementation.
- Get rid of various compatibility-related flags (e.g. division flags).
Core and Builtins
-----------------
- __coerce__ has been removed.
- Classic classes are a thing of the past. All classes are new style.
- Exceptions *must* derive from BaseException.
- Integer division always returns a float. The -Q option is no more.
All the following are gone:
* PyNumber_Divide and PyNumber_InPlaceDivide
* __div__, __rdiv__, and __idiv__
* nb_divide, nb_inplace_divide
* operator.div, operator.idiv, operator.__div__, operator.__idiv__
(Only __truediv__ and __floordiv__ remain, not sure how to handle them
if we want to re-use __div__ and friends. If we do, it will make
it harder to write code for both 2.x and 3.x.)
- 'as' and 'with' are keywords.
- Absolute import is the default behavior for 'import foo' etc.
- Removed these Python builtins:
apply(), coerce(), input(), raw_input()
- Removed these Python slots:
__coerce__, __div__, __idiv__, __rdiv__
- Removed these attributes from Python modules:
* operator module: div, idiv, __div__, __idiv__
*** PyNumber_CoerceEx() and nb_coerce still need to be removed.
- Removed these C APIs:
PyNumber_Coerce(),
- Removed these C slots/fields:
nb_divide, nb_inplace_divide
- Removed these macros:
staticforward, statichere, PyArg_GetInt, PyArg_NoArgs
- Removed these typedefs:
intargfunc, intintargfunc, intobjargproc, intintobjargproc,
getreadbufferproc, getwritebufferproc, getsegcountproc, getcharbufferproc
- Removed these opcodes:
BINARY_DIVIDE, INPLACE_DIVIDE
Extension Modules
-----------------
Library
-------
Build
-----

View file

@ -1188,7 +1188,6 @@ Operators
int(s) = __int__(s) long(s) = __long__(s)
float(s) = __float__(s) complex(s) = __complex__(s)
oct(s) = __oct__(s) hex(s) = __hex__(s)
coerce(s,o) = __coerce__(s,o)
Right-hand-side equivalents for all binary operators exist;
are called when class instance is on r-h-s of operator:
a + 3 calls __add__(a, 3)

View file

@ -339,8 +339,6 @@ PyNumber_Check(PyObject *o)
/* Binary operators */
/* New style number protocol support */
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
#define NB_BINOP(nb_methods, slot) \
(*(binaryfunc*)(& ((char*)nb_methods)[slot]))
@ -350,23 +348,11 @@ PyNumber_Check(PyObject *o)
/*
Calling scheme used for binary operations:
v w Action
-------------------------------------------------------------------
new new w.op(v,w)[*], v.op(v,w), w.op(v,w)
new old v.op(v,w), coerce(v,w), v.op(v,w)
old new w.op(v,w), coerce(v,w), v.op(v,w)
old old coerce(v,w), v.op(v,w)
Order operations are tried until either a valid result or error:
w.op(v,w)[*], v.op(v,w), w.op(v,w)
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
v->ob_type
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
*/
static PyObject *
@ -434,29 +420,8 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
/*
Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
v w z Action
-------------------------------------------------------------------
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old old coerce(v,w,z), v.op(v,w,z)
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
* coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
only if z != Py_None; if z == Py_None, then it is treated as absent
variable and only coerce(v,w) is tried.
Order operations are tried until either a valid result or error:
v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
*/
static PyObject *

View file

@ -573,65 +573,20 @@ complex_nonzero(PyComplexObject *v)
return v->cval.real != 0.0 || v->cval.imag != 0.0;
}
static int
complex_coerce(PyObject **pv, PyObject **pw)
{
Py_complex cval;
cval.imag = 0.;
if (PyInt_Check(*pw)) {
cval.real = (double)PyInt_AsLong(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyLong_Check(*pw)) {
cval.real = PyLong_AsDouble(*pw);
if (cval.real == -1.0 && PyErr_Occurred())
return -1;
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyFloat_Check(*pw)) {
cval.real = PyFloat_AsDouble(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyComplex_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
complex_richcompare(PyObject *v, PyObject *w, int op)
{
int c;
Py_complex i, j;
PyObject *res;
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return NULL;
if (c > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
/* Make sure both arguments are complex. */
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
Py_DECREF(v);
Py_DECREF(w);
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
i = ((PyComplexObject *)v)->cval;
j = ((PyComplexObject *)w)->cval;
Py_DECREF(v);
Py_DECREF(w);
if (op != Py_EQ && op != Py_NE) {
PyErr_SetString(PyExc_TypeError,
@ -996,7 +951,7 @@ static PyNumberMethods complex_as_number = {
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
complex_coerce, /* nb_coerce */
(coercion)0, /* nb_coerce */
complex_int, /* nb_int */
complex_long, /* nb_long */
complex_float, /* nb_float */

View file

@ -842,31 +842,6 @@ float_nonzero(PyFloatObject *v)
return v->ob_fval != 0.0;
}
static int
float_coerce(PyObject **pv, PyObject **pw)
{
if (PyInt_Check(*pw)) {
long x = PyInt_AsLong(*pw);
*pw = PyFloat_FromDouble((double)x);
Py_INCREF(*pv);
return 0;
}
else if (PyLong_Check(*pw)) {
double x = PyLong_AsDouble(*pw);
if (x == -1.0 && PyErr_Occurred())
return -1;
*pw = PyFloat_FromDouble(x);
Py_INCREF(*pv);
return 0;
}
else if (PyFloat_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
float_long(PyObject *v)
{
@ -1119,7 +1094,7 @@ static PyNumberMethods float_as_number = {
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
float_coerce, /*nb_coerce*/
(coercion)0, /*nb_coerce*/
float_int, /*nb_int*/
float_long, /*nb_long*/
float_float, /*nb_float*/

View file

@ -580,7 +580,7 @@ i_divmod(register long x, register long y,
}
static PyObject *
int_div(PyIntObject *x, PyIntObject *y)
int_floor_div(PyIntObject *x, PyIntObject *y)
{
long xi, yi;
long d, m;
@ -872,17 +872,6 @@ int_or(PyIntObject *v, PyIntObject *w)
return PyInt_FromLong(a | b);
}
static int
int_coerce(PyObject **pv, PyObject **pw)
{
if (PyInt_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
int_int(PyIntObject *v)
{
@ -1036,7 +1025,7 @@ static PyNumberMethods int_as_number = {
(binaryfunc)int_and, /*nb_and*/
(binaryfunc)int_xor, /*nb_xor*/
(binaryfunc)int_or, /*nb_or*/
int_coerce, /*nb_coerce*/
0, /*nb_coerce*/
(unaryfunc)int_int, /*nb_int*/
(unaryfunc)int_long, /*nb_long*/
(unaryfunc)int_float, /*nb_float*/
@ -1052,7 +1041,7 @@ static PyNumberMethods int_as_number = {
0, /*nb_inplace_and*/
0, /*nb_inplace_xor*/
0, /*nb_inplace_or*/
(binaryfunc)int_div, /* nb_floor_divide */
(binaryfunc)int_floor_div, /* nb_floor_divide */
int_true_divide, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */

View file

@ -681,9 +681,7 @@ try_3way_compare(PyObject *v, PyObject *w)
b) have different types or a type without tp_compare; and
c) don't have a user-defined tp_compare.
tp_compare implementations in C assume that both arguments
have their type, so we give up if the coercion fails or if
it yields types which are still incompatible (which can
happen with a user-defined nb_coerce).
have their type, so we give up if the coercion fails.
*/
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
@ -1513,22 +1511,6 @@ PyNumber_CoerceEx(PyObject **pv, PyObject **pw)
return 1;
}
/* Coerce two numeric types to the "larger" one.
Increment the reference count on each argument.
Return -1 and raise an exception if no coercion is possible
(and then no reference count is incremented).
*/
int
PyNumber_Coerce(PyObject **pv, PyObject **pw)
{
int err = PyNumber_CoerceEx(pv, pw);
if (err <= 0)
return err;
PyErr_SetString(PyExc_TypeError, "number coercion failed");
return -1;
}
/* Test whether an object can be called */
int

View file

@ -3326,34 +3326,6 @@ wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
return (*func)(other, self);
}
static PyObject *
wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped)
{
coercion func = (coercion)wrapped;
PyObject *other, *res;
int ok;
if (!check_num_args(args, 1))
return NULL;
other = PyTuple_GET_ITEM(args, 0);
ok = func(&self, &other);
if (ok < 0)
return NULL;
if (ok > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
res = PyTuple_New(2);
if (res == NULL) {
Py_DECREF(self);
Py_DECREF(other);
return NULL;
}
PyTuple_SET_ITEM(res, 0, self);
PyTuple_SET_ITEM(res, 1, other);
return res;
}
static PyObject *
wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)
{
@ -4247,64 +4219,6 @@ SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__")
SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__")
SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")
static int
slot_nb_coerce(PyObject **a, PyObject **b)
{
static PyObject *coerce_str;
PyObject *self = *a, *other = *b;
if (self->ob_type->tp_as_number != NULL &&
self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
PyObject *r;
r = call_maybe(
self, "__coerce__", &coerce_str, "(O)", other);
if (r == NULL)
return -1;
if (r == Py_NotImplemented) {
Py_DECREF(r);
}
else {
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
PyErr_SetString(PyExc_TypeError,
"__coerce__ didn't return a 2-tuple");
Py_DECREF(r);
return -1;
}
*a = PyTuple_GET_ITEM(r, 0);
Py_INCREF(*a);
*b = PyTuple_GET_ITEM(r, 1);
Py_INCREF(*b);
Py_DECREF(r);
return 0;
}
}
if (other->ob_type->tp_as_number != NULL &&
other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
PyObject *r;
r = call_maybe(
other, "__coerce__", &coerce_str, "(O)", self);
if (r == NULL)
return -1;
if (r == Py_NotImplemented) {
Py_DECREF(r);
return 1;
}
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
PyErr_SetString(PyExc_TypeError,
"__coerce__ didn't return a 2-tuple");
Py_DECREF(r);
return -1;
}
*a = PyTuple_GET_ITEM(r, 1);
Py_INCREF(*a);
*b = PyTuple_GET_ITEM(r, 0);
Py_INCREF(*b);
Py_DECREF(r);
return 0;
}
return 1;
}
SLOT0(slot_nb_int, "__int__")
SLOT0(slot_nb_long, "__long__")
SLOT0(slot_nb_float, "__float__")
@ -4958,8 +4872,6 @@ static slotdef slotdefs[] = {
RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
BINSLOT("__or__", nb_or, slot_nb_or, "|"),
RBINSLOT("__ror__", nb_or, slot_nb_or, "|"),
NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc,
"x.__coerce__(y) <==> coerce(x, y)"),
UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,
"int(x)"),
UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,

View file

@ -444,7 +444,6 @@ static PyNumberMethods PyHKEY_NumberMethods =
PyHKEY_binaryFailureFunc, /* nb_and */
PyHKEY_binaryFailureFunc, /* nb_xor */
PyHKEY_binaryFailureFunc, /* nb_or */
0, /* nb_coerce (allowed to be zero) */
PyHKEY_intFunc, /* nb_int */
PyHKEY_unaryFailureFunc, /* nb_long */
PyHKEY_unaryFailureFunc, /* nb_float */

View file

@ -333,30 +333,6 @@ PyDoc_STRVAR(cmp_doc,
\n\
Return negative if x<y, zero if x==y, positive if x>y.");
static PyObject *
builtin_coerce(PyObject *self, PyObject *args)
{
PyObject *v, *w;
PyObject *res;
if (!PyArg_UnpackTuple(args, "coerce", 2, 2, &v, &w))
return NULL;
if (PyNumber_Coerce(&v, &w) < 0)
return NULL;
res = PyTuple_Pack(2, v, w);
Py_DECREF(v);
Py_DECREF(w);
return res;
}
PyDoc_STRVAR(coerce_doc,
"coerce(x, y) -> (x1, y1)\n\
\n\
Return a tuple consisting of the two numeric arguments converted to\n\
a common type, using the same rules as used by arithmetic operations.\n\
If coercion is not possible, raise TypeError.");
static PyObject *
builtin_compile(PyObject *self, PyObject *args)
{
@ -2068,7 +2044,6 @@ static PyMethodDef builtin_methods[] = {
{"callable", builtin_callable, METH_O, callable_doc},
{"chr", builtin_chr, METH_VARARGS, chr_doc},
{"cmp", builtin_cmp, METH_VARARGS, cmp_doc},
{"coerce", builtin_coerce, METH_VARARGS, coerce_doc},
{"compile", builtin_compile, METH_VARARGS, compile_doc},
{"delattr", builtin_delattr, METH_VARARGS, delattr_doc},
{"dir", builtin_dir, METH_VARARGS, dir_doc},