mirror of
https://github.com/python/cpython.git
synced 2025-09-18 14:40:43 +00:00
Get rid of most of the rest of coerce (slot is still there for now).
This commit is contained in:
parent
79212998a8
commit
4886cc331f
19 changed files with 131 additions and 497 deletions
28
BROKEN
28
BROKEN
|
@ -110,3 +110,31 @@ Traceback (most recent call last):
|
||||||
File "../Lib/test/test_set.py", line 291, in test_remove
|
File "../Lib/test/test_set.py", line 291, in test_remove
|
||||||
self.assert_(self.thetype(self.word) in s)
|
self.assert_(self.thetype(self.word) in s)
|
||||||
AssertionError
|
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
|
||||||
|
|
||||||
|
|
|
@ -654,20 +654,6 @@ determination.
|
||||||
statement \samp{\var{o1} |= \var{o2}}.
|
statement \samp{\var{o1} |= \var{o2}}.
|
||||||
\end{cfuncdesc}
|
\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}
|
\begin{cfuncdesc}{PyObject*}{PyNumber_Int}{PyObject *o}
|
||||||
Returns the \var{o} converted to an integer object on success, or
|
Returns the \var{o} converted to an integer object on success, or
|
||||||
\NULL{} on failure. If the argument is outside the integer range
|
\NULL{} on failure. If the argument is outside the integer range
|
||||||
|
|
127
Doc/ref/ref3.tex
127
Doc/ref/ref3.tex
|
@ -1645,7 +1645,7 @@ sequence types should implement addition (meaning concatenation) and
|
||||||
multiplication (meaning repetition) by defining the methods
|
multiplication (meaning repetition) by defining the methods
|
||||||
\method{__add__()}, \method{__radd__()}, \method{__iadd__()},
|
\method{__add__()}, \method{__radd__()}, \method{__iadd__()},
|
||||||
\method{__mul__()}, \method{__rmul__()} and \method{__imul__()} described
|
\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
|
operators. It is recommended that both mappings and sequences
|
||||||
implement the \method{__contains__()} method to allow efficient use of
|
implement the \method{__contains__()} method to allow efficient use of
|
||||||
the \code{in} operator; for mappings, \code{in} should be equivalent
|
the \code{in} operator; for mappings, \code{in} should be equivalent
|
||||||
|
@ -1689,7 +1689,7 @@ through the values.
|
||||||
\ttindex{__imul__()}
|
\ttindex{__imul__()}
|
||||||
\ttindex{__contains__()}
|
\ttindex{__contains__()}
|
||||||
\ttindex{__iter__()}}
|
\ttindex{__iter__()}}
|
||||||
\withsubitem{(numeric object method)}{\ttindex{__coerce__()}}
|
\withsubitem{(numeric object method)}
|
||||||
|
|
||||||
\begin{methoddesc}[container object]{__len__}{self}
|
\begin{methoddesc}[container object]{__len__}{self}
|
||||||
Called to implement the built-in function
|
Called to implement the built-in function
|
||||||
|
@ -2012,129 +2012,6 @@ integer (int or long).
|
||||||
\versionadded{2.5}
|
\versionadded{2.5}
|
||||||
\end{methoddesc}
|
\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}}
|
\subsection{With Statement Context Managers\label{context-managers}}
|
||||||
|
|
||||||
\versionadded{2.5}
|
\versionadded{2.5}
|
||||||
|
|
|
@ -35,21 +35,6 @@ machine'' that calls the subroutines corresponding to each bytecode.
|
||||||
Any class which does not inherit from \class{object}. See
|
Any class which does not inherit from \class{object}. See
|
||||||
\emph{new-style class}.
|
\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}
|
\index{complex number}
|
||||||
\item[complex number]
|
\item[complex number]
|
||||||
An extension of the familiar real number system in which all numbers are
|
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__}
|
\index{__future__}
|
||||||
\item[__future__]
|
\item[__future__]
|
||||||
A pseudo module which programmers can use to enable new language
|
A pseudo module which programmers can use to enable new language
|
||||||
features which are not compatible with the current interpreter. For
|
features which are not compatible with the current interpreter.
|
||||||
example, the expression \code{11/4} currently evaluates to \code{2}.
|
To enable \code{new_feature}
|
||||||
If the module in which it is executed had enabled \emph{true division}
|
|
||||||
by executing:
|
|
||||||
|
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
from __future__ import division
|
from __future__ import new_feature
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
the expression \code{11/4} would evaluate to \code{2.75}. By
|
By importing the \ulink{\module{__future__}}{../lib/module-future.html}
|
||||||
importing the \ulink{\module{__future__}}{../lib/module-future.html}
|
|
||||||
module and evaluating its variables, you can see when a new feature
|
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:
|
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}
|
\index{integer division}
|
||||||
\item[integer division]
|
\item[integer division]
|
||||||
Mathematical division discarding any remainder. For example, the
|
Mathematical division including any remainder. The result will always
|
||||||
expression \code{11/4} currently evaluates to \code{2} in contrast
|
be a float. For example, the expression \code{11/4} evaluates to \code{2.75}.
|
||||||
to the \code{2.75} returned by float division. Also called
|
Integer division can be forced by using the \code{//} operator instead
|
||||||
{}\emph{floor division}. When dividing two integers the outcome will
|
of the \code{/} operator.
|
||||||
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__}.
|
|
||||||
|
|
||||||
\index{interactive}
|
\index{interactive}
|
||||||
\item[interactive]
|
\item[interactive]
|
||||||
|
|
|
@ -694,24 +694,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
expression: o1|o2.
|
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 *);
|
PyAPI_FUNC(Py_ssize_t) PyNumber_Index(PyObject *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -393,7 +393,6 @@ PyAPI_FUNC(long) PyObject_Hash(PyObject *);
|
||||||
PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);
|
PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);
|
||||||
PyAPI_FUNC(int) PyObject_Not(PyObject *);
|
PyAPI_FUNC(int) PyObject_Not(PyObject *);
|
||||||
PyAPI_FUNC(int) PyCallable_Check(PyObject *);
|
PyAPI_FUNC(int) PyCallable_Check(PyObject *);
|
||||||
PyAPI_FUNC(int) PyNumber_Coerce(PyObject **, PyObject **);
|
|
||||||
PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **);
|
PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **);
|
||||||
|
|
||||||
PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *);
|
PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *);
|
||||||
|
|
|
@ -196,17 +196,6 @@ class BuiltinTest(unittest.TestCase):
|
||||||
a.pop(); b.pop(); c.pop()
|
a.pop(); b.pop(); c.pop()
|
||||||
self.assertRaises(TypeError, cmp)
|
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):
|
def test_compile(self):
|
||||||
compile('print 1\n', '', 'exec')
|
compile('print 1\n', '', 'exec')
|
||||||
bom = '\xef\xbb\xbf'
|
bom = '\xef\xbb\xbf'
|
||||||
|
|
|
@ -92,9 +92,6 @@ class ComplexTest(unittest.TestCase):
|
||||||
self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
|
self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
|
||||||
self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
|
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):
|
def test_richcompare(self):
|
||||||
self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
|
self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
|
||||||
self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
|
self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
|
||||||
|
|
|
@ -2567,33 +2567,6 @@ def rich_comparisons():
|
||||||
verify(eval("x %s c[y]" % op) == eval("x %s y" % op),
|
verify(eval("x %s c[y]" % op) == eval("x %s y" % op),
|
||||||
"x=%d, y=%d" % (x, y))
|
"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():
|
def descrdoc():
|
||||||
if verbose: print "Testing descriptor doc strings..."
|
if verbose: print "Testing descriptor doc strings..."
|
||||||
def check(descr, what):
|
def check(descr, what):
|
||||||
|
@ -3961,11 +3934,8 @@ def notimplemented():
|
||||||
('__and__', 'x & y', 'x &= y'),
|
('__and__', 'x & y', 'x &= y'),
|
||||||
('__or__', 'x | y', 'x |= y'),
|
('__or__', 'x | y', 'x |= y'),
|
||||||
('__xor__', 'x ^ y', 'x ^= y'),
|
('__xor__', 'x ^ y', 'x ^= y'),
|
||||||
('__coerce__', 'coerce(x, y)', None)]:
|
]:
|
||||||
if name == '__coerce__':
|
rname = '__r' + name[2:]
|
||||||
rname = name
|
|
||||||
else:
|
|
||||||
rname = '__r' + name[2:]
|
|
||||||
A = metaclass('A', (), {name: specialmethod})
|
A = metaclass('A', (), {name: specialmethod})
|
||||||
B = metaclass('B', (), {rname: specialmethod})
|
B = metaclass('B', (), {rname: specialmethod})
|
||||||
a = A()
|
a = A()
|
||||||
|
@ -4043,7 +4013,6 @@ def test_main():
|
||||||
str_subclass_as_dict_key()
|
str_subclass_as_dict_key()
|
||||||
classic_comparisons()
|
classic_comparisons()
|
||||||
rich_comparisons()
|
rich_comparisons()
|
||||||
coercions()
|
|
||||||
descrdoc()
|
descrdoc()
|
||||||
setclass()
|
setclass()
|
||||||
setdict()
|
setdict()
|
||||||
|
|
81
Misc/NEWS
81
Misc/NEWS
|
@ -7,6 +7,87 @@ Python News
|
||||||
What's New in Python 3000?
|
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
|
Build
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -1188,7 +1188,6 @@ Operators
|
||||||
int(s) = __int__(s) long(s) = __long__(s)
|
int(s) = __int__(s) long(s) = __long__(s)
|
||||||
float(s) = __float__(s) complex(s) = __complex__(s)
|
float(s) = __float__(s) complex(s) = __complex__(s)
|
||||||
oct(s) = __oct__(s) hex(s) = __hex__(s)
|
oct(s) = __oct__(s) hex(s) = __hex__(s)
|
||||||
coerce(s,o) = __coerce__(s,o)
|
|
||||||
Right-hand-side equivalents for all binary operators exist;
|
Right-hand-side equivalents for all binary operators exist;
|
||||||
are called when class instance is on r-h-s of operator:
|
are called when class instance is on r-h-s of operator:
|
||||||
a + 3 calls __add__(a, 3)
|
a + 3 calls __add__(a, 3)
|
||||||
|
|
|
@ -339,8 +339,6 @@ PyNumber_Check(PyObject *o)
|
||||||
|
|
||||||
/* Binary operators */
|
/* Binary operators */
|
||||||
|
|
||||||
/* New style number protocol support */
|
|
||||||
|
|
||||||
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
|
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
|
||||||
#define NB_BINOP(nb_methods, slot) \
|
#define NB_BINOP(nb_methods, slot) \
|
||||||
(*(binaryfunc*)(& ((char*)nb_methods)[slot]))
|
(*(binaryfunc*)(& ((char*)nb_methods)[slot]))
|
||||||
|
@ -350,23 +348,11 @@ PyNumber_Check(PyObject *o)
|
||||||
/*
|
/*
|
||||||
Calling scheme used for binary operations:
|
Calling scheme used for binary operations:
|
||||||
|
|
||||||
v w Action
|
Order operations are tried until either a valid result or error:
|
||||||
-------------------------------------------------------------------
|
w.op(v,w)[*], v.op(v,w), w.op(v,w)
|
||||||
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)
|
|
||||||
|
|
||||||
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
|
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
|
||||||
v->ob_type
|
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 *
|
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:
|
Calling scheme used for ternary operations:
|
||||||
|
|
||||||
*** In some cases, w.op is called before v.op; see binary_op1. ***
|
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)
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
|
@ -573,65 +573,20 @@ complex_nonzero(PyComplexObject *v)
|
||||||
return v->cval.real != 0.0 || v->cval.imag != 0.0;
|
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 *
|
static PyObject *
|
||||||
complex_richcompare(PyObject *v, PyObject *w, int op)
|
complex_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
Py_complex i, j;
|
Py_complex i, j;
|
||||||
PyObject *res;
|
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. */
|
/* Make sure both arguments are complex. */
|
||||||
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
|
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
|
||||||
Py_DECREF(v);
|
|
||||||
Py_DECREF(w);
|
|
||||||
Py_INCREF(Py_NotImplemented);
|
Py_INCREF(Py_NotImplemented);
|
||||||
return Py_NotImplemented;
|
return Py_NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = ((PyComplexObject *)v)->cval;
|
i = ((PyComplexObject *)v)->cval;
|
||||||
j = ((PyComplexObject *)w)->cval;
|
j = ((PyComplexObject *)w)->cval;
|
||||||
Py_DECREF(v);
|
|
||||||
Py_DECREF(w);
|
|
||||||
|
|
||||||
if (op != Py_EQ && op != Py_NE) {
|
if (op != Py_EQ && op != Py_NE) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
@ -996,7 +951,7 @@ static PyNumberMethods complex_as_number = {
|
||||||
0, /* nb_and */
|
0, /* nb_and */
|
||||||
0, /* nb_xor */
|
0, /* nb_xor */
|
||||||
0, /* nb_or */
|
0, /* nb_or */
|
||||||
complex_coerce, /* nb_coerce */
|
(coercion)0, /* nb_coerce */
|
||||||
complex_int, /* nb_int */
|
complex_int, /* nb_int */
|
||||||
complex_long, /* nb_long */
|
complex_long, /* nb_long */
|
||||||
complex_float, /* nb_float */
|
complex_float, /* nb_float */
|
||||||
|
|
|
@ -842,31 +842,6 @@ float_nonzero(PyFloatObject *v)
|
||||||
return v->ob_fval != 0.0;
|
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 *
|
static PyObject *
|
||||||
float_long(PyObject *v)
|
float_long(PyObject *v)
|
||||||
{
|
{
|
||||||
|
@ -1119,7 +1094,7 @@ static PyNumberMethods float_as_number = {
|
||||||
0, /*nb_and*/
|
0, /*nb_and*/
|
||||||
0, /*nb_xor*/
|
0, /*nb_xor*/
|
||||||
0, /*nb_or*/
|
0, /*nb_or*/
|
||||||
float_coerce, /*nb_coerce*/
|
(coercion)0, /*nb_coerce*/
|
||||||
float_int, /*nb_int*/
|
float_int, /*nb_int*/
|
||||||
float_long, /*nb_long*/
|
float_long, /*nb_long*/
|
||||||
float_float, /*nb_float*/
|
float_float, /*nb_float*/
|
||||||
|
|
|
@ -580,7 +580,7 @@ i_divmod(register long x, register long y,
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
int_div(PyIntObject *x, PyIntObject *y)
|
int_floor_div(PyIntObject *x, PyIntObject *y)
|
||||||
{
|
{
|
||||||
long xi, yi;
|
long xi, yi;
|
||||||
long d, m;
|
long d, m;
|
||||||
|
@ -872,17 +872,6 @@ int_or(PyIntObject *v, PyIntObject *w)
|
||||||
return PyInt_FromLong(a | b);
|
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 *
|
static PyObject *
|
||||||
int_int(PyIntObject *v)
|
int_int(PyIntObject *v)
|
||||||
{
|
{
|
||||||
|
@ -1036,7 +1025,7 @@ static PyNumberMethods int_as_number = {
|
||||||
(binaryfunc)int_and, /*nb_and*/
|
(binaryfunc)int_and, /*nb_and*/
|
||||||
(binaryfunc)int_xor, /*nb_xor*/
|
(binaryfunc)int_xor, /*nb_xor*/
|
||||||
(binaryfunc)int_or, /*nb_or*/
|
(binaryfunc)int_or, /*nb_or*/
|
||||||
int_coerce, /*nb_coerce*/
|
0, /*nb_coerce*/
|
||||||
(unaryfunc)int_int, /*nb_int*/
|
(unaryfunc)int_int, /*nb_int*/
|
||||||
(unaryfunc)int_long, /*nb_long*/
|
(unaryfunc)int_long, /*nb_long*/
|
||||||
(unaryfunc)int_float, /*nb_float*/
|
(unaryfunc)int_float, /*nb_float*/
|
||||||
|
@ -1052,7 +1041,7 @@ static PyNumberMethods int_as_number = {
|
||||||
0, /*nb_inplace_and*/
|
0, /*nb_inplace_and*/
|
||||||
0, /*nb_inplace_xor*/
|
0, /*nb_inplace_xor*/
|
||||||
0, /*nb_inplace_or*/
|
0, /*nb_inplace_or*/
|
||||||
(binaryfunc)int_div, /* nb_floor_divide */
|
(binaryfunc)int_floor_div, /* nb_floor_divide */
|
||||||
int_true_divide, /* nb_true_divide */
|
int_true_divide, /* nb_true_divide */
|
||||||
0, /* nb_inplace_floor_divide */
|
0, /* nb_inplace_floor_divide */
|
||||||
0, /* nb_inplace_true_divide */
|
0, /* nb_inplace_true_divide */
|
||||||
|
|
|
@ -681,9 +681,7 @@ try_3way_compare(PyObject *v, PyObject *w)
|
||||||
b) have different types or a type without tp_compare; and
|
b) have different types or a type without tp_compare; and
|
||||||
c) don't have a user-defined tp_compare.
|
c) don't have a user-defined tp_compare.
|
||||||
tp_compare implementations in C assume that both arguments
|
tp_compare implementations in C assume that both arguments
|
||||||
have their type, so we give up if the coercion fails or if
|
have their type, so we give up if the coercion fails.
|
||||||
it yields types which are still incompatible (which can
|
|
||||||
happen with a user-defined nb_coerce).
|
|
||||||
*/
|
*/
|
||||||
c = PyNumber_CoerceEx(&v, &w);
|
c = PyNumber_CoerceEx(&v, &w);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
|
@ -1513,22 +1511,6 @@ PyNumber_CoerceEx(PyObject **pv, PyObject **pw)
|
||||||
return 1;
|
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 */
|
/* Test whether an object can be called */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -3326,34 +3326,6 @@ wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
|
||||||
return (*func)(other, self);
|
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 *
|
static PyObject *
|
||||||
wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)
|
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_xor, nb_xor, "__xor__", "__rxor__")
|
||||||
SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")
|
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_int, "__int__")
|
||||||
SLOT0(slot_nb_long, "__long__")
|
SLOT0(slot_nb_long, "__long__")
|
||||||
SLOT0(slot_nb_float, "__float__")
|
SLOT0(slot_nb_float, "__float__")
|
||||||
|
@ -4958,8 +4872,6 @@ static slotdef slotdefs[] = {
|
||||||
RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
|
RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
|
||||||
BINSLOT("__or__", nb_or, slot_nb_or, "|"),
|
BINSLOT("__or__", nb_or, slot_nb_or, "|"),
|
||||||
RBINSLOT("__ror__", 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,
|
UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,
|
||||||
"int(x)"),
|
"int(x)"),
|
||||||
UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,
|
UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,
|
||||||
|
|
|
@ -444,7 +444,6 @@ static PyNumberMethods PyHKEY_NumberMethods =
|
||||||
PyHKEY_binaryFailureFunc, /* nb_and */
|
PyHKEY_binaryFailureFunc, /* nb_and */
|
||||||
PyHKEY_binaryFailureFunc, /* nb_xor */
|
PyHKEY_binaryFailureFunc, /* nb_xor */
|
||||||
PyHKEY_binaryFailureFunc, /* nb_or */
|
PyHKEY_binaryFailureFunc, /* nb_or */
|
||||||
0, /* nb_coerce (allowed to be zero) */
|
|
||||||
PyHKEY_intFunc, /* nb_int */
|
PyHKEY_intFunc, /* nb_int */
|
||||||
PyHKEY_unaryFailureFunc, /* nb_long */
|
PyHKEY_unaryFailureFunc, /* nb_long */
|
||||||
PyHKEY_unaryFailureFunc, /* nb_float */
|
PyHKEY_unaryFailureFunc, /* nb_float */
|
||||||
|
|
|
@ -333,30 +333,6 @@ PyDoc_STRVAR(cmp_doc,
|
||||||
\n\
|
\n\
|
||||||
Return negative if x<y, zero if x==y, positive if x>y.");
|
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 *
|
static PyObject *
|
||||||
builtin_compile(PyObject *self, PyObject *args)
|
builtin_compile(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -2068,7 +2044,6 @@ static PyMethodDef builtin_methods[] = {
|
||||||
{"callable", builtin_callable, METH_O, callable_doc},
|
{"callable", builtin_callable, METH_O, callable_doc},
|
||||||
{"chr", builtin_chr, METH_VARARGS, chr_doc},
|
{"chr", builtin_chr, METH_VARARGS, chr_doc},
|
||||||
{"cmp", builtin_cmp, METH_VARARGS, cmp_doc},
|
{"cmp", builtin_cmp, METH_VARARGS, cmp_doc},
|
||||||
{"coerce", builtin_coerce, METH_VARARGS, coerce_doc},
|
|
||||||
{"compile", builtin_compile, METH_VARARGS, compile_doc},
|
{"compile", builtin_compile, METH_VARARGS, compile_doc},
|
||||||
{"delattr", builtin_delattr, METH_VARARGS, delattr_doc},
|
{"delattr", builtin_delattr, METH_VARARGS, delattr_doc},
|
||||||
{"dir", builtin_dir, METH_VARARGS, dir_doc},
|
{"dir", builtin_dir, METH_VARARGS, dir_doc},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue