- patch #1600346 submitted by Tomer Filiba

- Renamed nb_nonzero slots to nb_bool
- Renamed __nonzero__ methods to __bool__
- update core, lib, docs, and tests to match
This commit is contained in:
Jack Diederich 2006-11-28 19:15:13 +00:00
parent dfc9d4f7aa
commit 4dafcc4ece
31 changed files with 118 additions and 82 deletions

View file

@ -165,7 +165,7 @@ def __rcmp__(self, other):
other = ToComplex(other) other = ToComplex(other)
return cmp(other, self) return cmp(other, self)
def __nonzero__(self): def __bool__(self):
return not (self.re == self.im == 0) return not (self.re == self.im == 0)
abs = radius = __abs__ abs = radius = __abs__

View file

@ -223,7 +223,7 @@ def __rcmp__(b, a):
return cmp(Rat(a), b) return cmp(Rat(a), b)
# a != 0 # a != 0
def __nonzero__(a): def __bool__(a):
return a.__num != 0 return a.__num != 0
# coercion # coercion

View file

@ -55,7 +55,7 @@ and support truth tests, identity tests, and boolean operations:
Return the outcome of \keyword{not} \var{o}. (Note that there is no Return the outcome of \keyword{not} \var{o}. (Note that there is no
\method{__not__()} method for object instances; only the interpreter \method{__not__()} method for object instances; only the interpreter
core defines this operation. The result is affected by the core defines this operation. The result is affected by the
\method{__nonzero__()} and \method{__len__()} methods.) \method{__bool__()} and \method{__len__()} methods.)
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{truth}{o} \begin{funcdesc}{truth}{o}

View file

@ -51,7 +51,7 @@ The following values are considered false:
\item any empty mapping, for example, \code{\{\}}. \item any empty mapping, for example, \code{\{\}}.
\item instances of user-defined classes, if the class defines a \item instances of user-defined classes, if the class defines a
\method{__nonzero__()} or \method{__len__()} method, when that \method{__bool__()} or \method{__len__()} method, when that
method returns the integer zero or \class{bool} value method returns the integer zero or \class{bool} value
\code{False}.\footnote{Additional \code{False}.\footnote{Additional
information on these special methods may be found in the information on these special methods may be found in the

View file

@ -162,13 +162,13 @@ the module interface) that compare the cost of using
missing and present object attributes. missing and present object attributes.
\begin{verbatim} \begin{verbatim}
% timeit.py 'try:' ' str.__nonzero__' 'except AttributeError:' ' pass' % timeit.py 'try:' ' str.__bool__' 'except AttributeError:' ' pass'
100000 loops, best of 3: 15.7 usec per loop 100000 loops, best of 3: 15.7 usec per loop
% timeit.py 'if hasattr(str, "__nonzero__"): pass' % timeit.py 'if hasattr(str, "__bool__"): pass'
100000 loops, best of 3: 4.26 usec per loop 100000 loops, best of 3: 4.26 usec per loop
% timeit.py 'try:' ' int.__nonzero__' 'except AttributeError:' ' pass' % timeit.py 'try:' ' int.__bool__' 'except AttributeError:' ' pass'
1000000 loops, best of 3: 1.43 usec per loop 1000000 loops, best of 3: 1.43 usec per loop
% timeit.py 'if hasattr(int, "__nonzero__"): pass' % timeit.py 'if hasattr(int, "__bool__"): pass'
100000 loops, best of 3: 2.23 usec per loop 100000 loops, best of 3: 2.23 usec per loop
\end{verbatim} \end{verbatim}
@ -176,7 +176,7 @@ missing and present object attributes.
>>> import timeit >>> import timeit
>>> s = """\ >>> s = """\
... try: ... try:
... str.__nonzero__ ... str.__bool__
... except AttributeError: ... except AttributeError:
... pass ... pass
... """ ... """
@ -184,14 +184,14 @@ missing and present object attributes.
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) >>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
17.09 usec/pass 17.09 usec/pass
>>> s = """\ >>> s = """\
... if hasattr(str, '__nonzero__'): pass ... if hasattr(str, '__bool__'): pass
... """ ... """
>>> t = timeit.Timer(stmt=s) >>> t = timeit.Timer(stmt=s)
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) >>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
4.85 usec/pass 4.85 usec/pass
>>> s = """\ >>> s = """\
... try: ... try:
... int.__nonzero__ ... int.__bool__
... except AttributeError: ... except AttributeError:
... pass ... pass
... """ ... """
@ -199,7 +199,7 @@ missing and present object attributes.
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) >>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
1.97 usec/pass 1.97 usec/pass
>>> s = """\ >>> s = """\
... if hasattr(int, '__nonzero__'): pass ... if hasattr(int, '__bool__'): pass
... """ ... """
>>> t = timeit.Timer(stmt=s) >>> t = timeit.Timer(stmt=s)
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) >>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

View file

@ -375,7 +375,7 @@ This module offers the following functions:
also accept an integer, however, use of the handle object is also accept an integer, however, use of the handle object is
encouraged. encouraged.
Handle objects provide semantics for \method{__nonzero__()} - thus Handle objects provide semantics for \method{__bool__()} - thus
\begin{verbatim} \begin{verbatim}
if handle: if handle:
print "Yes" print "Yes"

View file

@ -171,7 +171,7 @@ Hacks}{http://xmlrpc-c.sourceforge.net/hacks.php} page.
This class may be initialized from any Python value; the instance This class may be initialized from any Python value; the instance
returned depends only on its truth value. It supports various Python returned depends only on its truth value. It supports various Python
operators through \method{__cmp__()}, \method{__repr__()}, operators through \method{__cmp__()}, \method{__repr__()},
\method{__int__()}, and \method{__nonzero__()} methods, all \method{__int__()}, and \method{__bool__()} methods, all
implemented in the obvious ways. implemented in the obvious ways.
It also has the following method, supported mainly for internal use by It also has the following method, supported mainly for internal use by

View file

@ -1313,13 +1313,13 @@ of that object]{2.5}
\withsubitem{(object method)}{\ttindex{__cmp__()}} \withsubitem{(object method)}{\ttindex{__cmp__()}}
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[object]{__nonzero__}{self} \begin{methoddesc}[object]{__bool__}{self}
Called to implement truth value testing, and the built-in operation Called to implement truth value testing, and the built-in operation
\code{bool()}; should return \code{False} or \code{True}, or their \code{bool()}; should return \code{False} or \code{True}.
integer equivalents \code{0} or \code{1}.
When this method is not defined, \method{__len__()} is When this method is not defined, \method{__len__()} is
called, if it is defined (see below). If a class defines neither called, if it is defined (see below) and \code{True} is returned when
\method{__len__()} nor \method{__nonzero__()}, all its instances are the length is not zero. If a class defines neither
\method{__len__()} nor \method{__bool__()}, all its instances are
considered true. considered true.
\withsubitem{(mapping object method)}{\ttindex{__len__()}} \withsubitem{(mapping object method)}{\ttindex{__len__()}}
\end{methoddesc} \end{methoddesc}
@ -1693,9 +1693,9 @@ through the values.
Called to implement the built-in function Called to implement the built-in function
\function{len()}\bifuncindex{len}. Should return the length of the \function{len()}\bifuncindex{len}. Should return the length of the
object, an integer \code{>=} 0. Also, an object that doesn't define a object, an integer \code{>=} 0. Also, an object that doesn't define a
\method{__nonzero__()} method and whose \method{__len__()} method \method{__bool__()} method and whose \method{__len__()} method
returns zero is considered to be false in a Boolean context. returns zero is considered to be false in a Boolean context.
\withsubitem{(object method)}{\ttindex{__nonzero__()}} \withsubitem{(object method)}{\ttindex{__bool__()}}
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[container object]{__getitem__}{self, key} \begin{methoddesc}[container object]{__getitem__}{self, key}

View file

@ -160,7 +160,7 @@ typedef struct {
unaryfunc nb_negative; unaryfunc nb_negative;
unaryfunc nb_positive; unaryfunc nb_positive;
unaryfunc nb_absolute; unaryfunc nb_absolute;
inquiry nb_nonzero; inquiry nb_bool;
unaryfunc nb_invert; unaryfunc nb_invert;
binaryfunc nb_lshift; binaryfunc nb_lshift;
binaryfunc nb_rshift; binaryfunc nb_rshift;

View file

@ -633,14 +633,14 @@ def _check_nans(self, other = None, context=None):
return other return other
return 0 return 0
def __nonzero__(self): def __bool__(self):
"""Is the number non-zero? """Is the number non-zero?
0 if self == 0 0 if self == 0
1 if self != 0 1 if self != 0
""" """
if self._is_special: if self._is_special:
return 1 return True
return sum(self._int) != 0 return sum(self._int) != 0
def __cmp__(self, other, context=None): def __cmp__(self, other, context=None):
@ -759,7 +759,7 @@ def __hash__(self):
i = int(self) i = int(self)
if self == Decimal(i): if self == Decimal(i):
return hash(i) return hash(i)
assert self.__nonzero__() # '-0' handled by integer case assert self.__bool__() # '-0' handled by integer case
return hash(str(self.normalize())) return hash(str(self.normalize()))
def as_tuple(self): def as_tuple(self):

View file

@ -335,24 +335,51 @@ def test_picklevalues(self):
def test_convert_to_bool(self): def test_convert_to_bool(self):
# Verify that TypeError occurs when bad things are returned # Verify that TypeError occurs when bad things are returned
# from __nonzero__(). This isn't really a bool test, but # from __bool__(). This isn't really a bool test, but
# it's related. # it's related.
check = lambda o: self.assertRaises(TypeError, bool, o) check = lambda o: self.assertRaises(TypeError, bool, o)
class Foo(object): class Foo(object):
def __nonzero__(self): def __bool__(self):
return self return self
check(Foo()) check(Foo())
class Bar(object): class Bar(object):
def __nonzero__(self): def __bool__(self):
return "Yes" return "Yes"
check(Bar()) check(Bar())
class Baz(int): class Baz(int):
def __nonzero__(self): def __bool__(self):
return self return self
check(Baz()) check(Baz())
# __bool__() must return a bool not an int
class Spam(int):
def __bool__(self):
return 1
check(Spam())
class Eggs:
def __len__(self):
return -1
self.assertRaises(ValueError, bool, Eggs())
def test_sane_len(self):
# this test just tests our assumptions about __len__
# this will start failing if __len__ changes assertions
for badval in ['illegal', -1, 1 << 32]:
class A:
def __len__(self):
return badval
try:
bool(A())
except (Exception), e_bool:
pass
try:
len(A())
except (Exception), e_len:
pass
self.assertEqual(str(e_bool), str(e_len))
def test_main(): def test_main():
test_support.run_unittest(BoolTest) test_support.run_unittest(BoolTest)

View file

@ -94,7 +94,7 @@ def write(self, line):
] ]
class TestFailingBool: class TestFailingBool:
def __nonzero__(self): def __bool__(self):
raise RuntimeError raise RuntimeError
class TestFailingIter: class TestFailingIter:

View file

@ -990,7 +990,7 @@ def checkSameDec(operation, useOther=False):
checkSameDec("__mod__", True) checkSameDec("__mod__", True)
checkSameDec("__mul__", True) checkSameDec("__mul__", True)
checkSameDec("__neg__") checkSameDec("__neg__")
checkSameDec("__nonzero__") checkSameDec("__bool__")
checkSameDec("__pos__") checkSameDec("__pos__")
checkSameDec("__pow__", True) checkSameDec("__pow__", True)
checkSameDec("__radd__", True) checkSameDec("__radd__", True)

View file

@ -417,8 +417,8 @@ def ints():
if verbose: print "Testing int operations..." if verbose: print "Testing int operations..."
numops(100, 3) numops(100, 3)
# The following crashes in Python 2.2 # The following crashes in Python 2.2
vereq((1).__nonzero__(), 1) vereq((1).__bool__(), True)
vereq((0).__nonzero__(), 0) vereq((0).__bool__(), False)
# This returns 'NotImplemented' in Python 2.2 # This returns 'NotImplemented' in Python 2.2
class C(int): class C(int):
def __add__(self, other): def __add__(self, other):
@ -1682,7 +1682,7 @@ def __getitem__(self, i):
class Proxy(object): class Proxy(object):
def __init__(self, x): def __init__(self, x):
self.x = x self.x = x
def __nonzero__(self): def __bool__(self):
return not not self.x return not not self.x
def __hash__(self): def __hash__(self):
return hash(self.x) return hash(self.x)
@ -1722,7 +1722,7 @@ def __contains__(self, value):
class DProxy(object): class DProxy(object):
def __init__(self, x): def __init__(self, x):
self.x = x self.x = x
def __nonzero__(self): def __bool__(self):
return not not self.x return not not self.x
def __hash__(self): def __hash__(self):
return hash(self.x) return hash(self.x)

View file

@ -327,10 +327,10 @@ def test_builtin_filter(self):
class Boolean: class Boolean:
def __init__(self, truth): def __init__(self, truth):
self.truth = truth self.truth = truth
def __nonzero__(self): def __bool__(self):
return self.truth return self.truth
bTrue = Boolean(1) bTrue = Boolean(True)
bFalse = Boolean(0) bFalse = Boolean(False)
class Seq: class Seq:
def __init__(self, *args): def __init__(self, *args):

View file

@ -319,7 +319,7 @@ def test_sub(self):
def test_truth(self): def test_truth(self):
class C(object): class C(object):
def __nonzero__(self): def __bool__(self):
raise SyntaxError raise SyntaxError
self.failUnlessRaises(TypeError, operator.truth) self.failUnlessRaises(TypeError, operator.truth)
self.failUnlessRaises(SyntaxError, operator.truth, C()) self.failUnlessRaises(SyntaxError, operator.truth, C())

View file

@ -51,7 +51,7 @@ def __setitem__(self, i, v):
def __hash__(self): def __hash__(self):
raise TypeError, "Vectors cannot be hashed" raise TypeError, "Vectors cannot be hashed"
def __nonzero__(self): def __bool__(self):
raise TypeError, "Vectors cannot be used in Boolean contexts" raise TypeError, "Vectors cannot be used in Boolean contexts"
def __cmp__(self, other): def __cmp__(self, other):
@ -133,7 +133,7 @@ def test_mixed(self):
for ops in opmap.itervalues(): for ops in opmap.itervalues():
for op in ops: for op in ops:
# calls __nonzero__, which should fail # calls __bool__, which should fail
self.assertRaises(TypeError, bool, op(a, b)) self.assertRaises(TypeError, bool, op(a, b))
class NumberTest(unittest.TestCase): class NumberTest(unittest.TestCase):
@ -208,13 +208,13 @@ def __cmp__(self, other): raise RuntimeError, "expected"
self.assertRaises(RuntimeError, cmp, a, b) self.assertRaises(RuntimeError, cmp, a, b)
def test_not(self): def test_not(self):
# Check that exceptions in __nonzero__ are properly # Check that exceptions in __bool__ are properly
# propagated by the not operator # propagated by the not operator
import operator import operator
class Exc(Exception): class Exc(Exception):
pass pass
class Bad: class Bad:
def __nonzero__(self): def __bool__(self):
raise Exc raise Exc
def do(bad): def do(bad):

View file

@ -38,7 +38,7 @@ class Node(xml.dom.Node):
prefix = EMPTY_PREFIX # non-null only for NS elements and attributes prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
def __nonzero__(self): def __bool__(self):
return True return True
def toxml(self, encoding = None): def toxml(self, encoding = None):

View file

@ -36,6 +36,8 @@ TO DO
Core and Builtins Core and Builtins
----------------- -----------------
- Renamed nb_nonzero to nb_bool and __nonzero__ to __bool__
- Classic classes are a thing of the past. All classes are new style. - Classic classes are a thing of the past. All classes are new style.
- Exceptions *must* derive from BaseException. - Exceptions *must* derive from BaseException.

View file

@ -4017,7 +4017,7 @@ static PyMethodDef Simple_methods[] = {
{ NULL, NULL }, { NULL, NULL },
}; };
static int Simple_nonzero(CDataObject *self) static int Simple_bool(CDataObject *self)
{ {
return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
} }
@ -4032,7 +4032,7 @@ static PyNumberMethods Simple_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
(inquiry)Simple_nonzero, /* nb_nonzero */ (inquiry)Simple_bool, /* nb_bool */
}; };
#if (PY_VERSION_HEX < 0x02040000) #if (PY_VERSION_HEX < 0x02040000)
@ -4364,7 +4364,7 @@ static PySequenceMethods Pointer_as_sequence = {
}; };
static int static int
Pointer_nonzero(CDataObject *self) Pointer_bool(CDataObject *self)
{ {
return *(void **)self->b_ptr != NULL; return *(void **)self->b_ptr != NULL;
} }
@ -4379,7 +4379,7 @@ static PyNumberMethods Pointer_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
(inquiry)Pointer_nonzero, /* nb_nonzero */ (inquiry)Pointer_bool, /* nb_bool */
}; };
PyTypeObject Pointer_Type = { PyTypeObject Pointer_Type = {

View file

@ -1958,7 +1958,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
} }
static int static int
delta_nonzero(PyDateTime_Delta *self) delta_bool(PyDateTime_Delta *self)
{ {
return (GET_TD_DAYS(self) != 0 return (GET_TD_DAYS(self) != 0
|| GET_TD_SECONDS(self) != 0 || GET_TD_SECONDS(self) != 0
@ -2083,7 +2083,7 @@ static PyNumberMethods delta_as_number = {
(unaryfunc)delta_negative, /* nb_negative */ (unaryfunc)delta_negative, /* nb_negative */
(unaryfunc)delta_positive, /* nb_positive */ (unaryfunc)delta_positive, /* nb_positive */
(unaryfunc)delta_abs, /* nb_absolute */ (unaryfunc)delta_abs, /* nb_absolute */
(inquiry)delta_nonzero, /* nb_nonzero */ (inquiry)delta_bool, /* nb_bool */
0, /*nb_invert*/ 0, /*nb_invert*/
0, /*nb_lshift*/ 0, /*nb_lshift*/
0, /*nb_rshift*/ 0, /*nb_rshift*/
@ -2653,7 +2653,7 @@ static PyNumberMethods date_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
0, /* nb_nonzero */ 0, /* nb_bool */
}; };
static PyTypeObject PyDateTime_DateType = { static PyTypeObject PyDateTime_DateType = {
@ -3324,7 +3324,7 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
} }
static int static int
time_nonzero(PyDateTime_Time *self) time_bool(PyDateTime_Time *self)
{ {
int offset; int offset;
int none; int none;
@ -3418,7 +3418,7 @@ static PyNumberMethods time_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
(inquiry)time_nonzero, /* nb_nonzero */ (inquiry)time_bool, /* nb_bool */
}; };
static PyTypeObject PyDateTime_TimeType = { static PyTypeObject PyDateTime_TimeType = {
@ -4501,7 +4501,7 @@ static PyNumberMethods datetime_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
0, /* nb_nonzero */ 0, /* nb_bool */
}; };
static PyTypeObject PyDateTime_DateTimeType = { static PyTypeObject PyDateTime_DateTimeType = {

View file

@ -112,7 +112,7 @@ static PyNumberMethods bool_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
0, /* nb_nonzero */ 0, /* nb_bool */
0, /* nb_invert */ 0, /* nb_invert */
0, /* nb_lshift */ 0, /* nb_lshift */
0, /* nb_rshift */ 0, /* nb_rshift */

View file

@ -568,7 +568,7 @@ complex_abs(PyComplexObject *v)
} }
static int static int
complex_nonzero(PyComplexObject *v) complex_bool(PyComplexObject *v)
{ {
return v->cval.real != 0.0 || v->cval.imag != 0.0; return v->cval.real != 0.0 || v->cval.imag != 0.0;
} }
@ -938,7 +938,7 @@ static PyNumberMethods complex_as_number = {
(unaryfunc)complex_neg, /* nb_negative */ (unaryfunc)complex_neg, /* nb_negative */
(unaryfunc)complex_pos, /* nb_positive */ (unaryfunc)complex_pos, /* nb_positive */
(unaryfunc)complex_abs, /* nb_absolute */ (unaryfunc)complex_abs, /* nb_absolute */
(inquiry)complex_nonzero, /* nb_nonzero */ (inquiry)complex_bool, /* nb_bool */
0, /* nb_invert */ 0, /* nb_invert */
0, /* nb_lshift */ 0, /* nb_lshift */
0, /* nb_rshift */ 0, /* nb_rshift */

View file

@ -837,7 +837,7 @@ float_abs(PyFloatObject *v)
} }
static int static int
float_nonzero(PyFloatObject *v) float_bool(PyFloatObject *v)
{ {
return v->ob_fval != 0.0; return v->ob_fval != 0.0;
} }
@ -1087,7 +1087,7 @@ static PyNumberMethods float_as_number = {
(unaryfunc)float_neg, /*nb_negative*/ (unaryfunc)float_neg, /*nb_negative*/
(unaryfunc)float_pos, /*nb_positive*/ (unaryfunc)float_pos, /*nb_positive*/
(unaryfunc)float_abs, /*nb_absolute*/ (unaryfunc)float_abs, /*nb_absolute*/
(inquiry)float_nonzero, /*nb_nonzero*/ (inquiry)float_bool, /*nb_bool*/
0, /*nb_invert*/ 0, /*nb_invert*/
0, /*nb_lshift*/ 0, /*nb_lshift*/
0, /*nb_rshift*/ 0, /*nb_rshift*/

View file

@ -780,7 +780,7 @@ int_abs(PyIntObject *v)
} }
static int static int
int_nonzero(PyIntObject *v) int_bool(PyIntObject *v)
{ {
return v->ob_ival != 0; return v->ob_ival != 0;
} }
@ -1034,14 +1034,14 @@ static PyNumberMethods int_as_number = {
(unaryfunc)int_neg, /*nb_negative*/ (unaryfunc)int_neg, /*nb_negative*/
(unaryfunc)int_pos, /*nb_positive*/ (unaryfunc)int_pos, /*nb_positive*/
(unaryfunc)int_abs, /*nb_absolute*/ (unaryfunc)int_abs, /*nb_absolute*/
(inquiry)int_nonzero, /*nb_nonzero*/ (inquiry)int_bool, /*nb_bool*/
(unaryfunc)int_invert, /*nb_invert*/ (unaryfunc)int_invert, /*nb_invert*/
(binaryfunc)int_lshift, /*nb_lshift*/ (binaryfunc)int_lshift, /*nb_lshift*/
(binaryfunc)int_rshift, /*nb_rshift*/ (binaryfunc)int_rshift, /*nb_rshift*/
(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*/
0, /*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*/

View file

@ -2886,7 +2886,7 @@ long_abs(PyLongObject *v)
} }
static int static int
long_nonzero(PyLongObject *v) long_bool(PyLongObject *v)
{ {
return ABS(v->ob_size) != 0; return ABS(v->ob_size) != 0;
} }
@ -3307,7 +3307,7 @@ static PyNumberMethods long_as_number = {
(unaryfunc) long_neg, /*nb_negative*/ (unaryfunc) long_neg, /*nb_negative*/
(unaryfunc) long_pos, /*tp_positive*/ (unaryfunc) long_pos, /*tp_positive*/
(unaryfunc) long_abs, /*tp_absolute*/ (unaryfunc) long_abs, /*tp_absolute*/
(inquiry) long_nonzero, /*tp_nonzero*/ (inquiry) long_bool, /*tp_bool*/
(unaryfunc) long_invert, /*nb_invert*/ (unaryfunc) long_invert, /*nb_invert*/
long_lshift, /*nb_lshift*/ long_lshift, /*nb_lshift*/
(binaryfunc) long_rshift, /*nb_rshift*/ (binaryfunc) long_rshift, /*nb_rshift*/

View file

@ -1246,8 +1246,8 @@ PyObject_IsTrue(PyObject *v)
if (v == Py_None) if (v == Py_None)
return 0; return 0;
else if (v->ob_type->tp_as_number != NULL && else if (v->ob_type->tp_as_number != NULL &&
v->ob_type->tp_as_number->nb_nonzero != NULL) v->ob_type->tp_as_number->nb_bool != NULL)
res = (*v->ob_type->tp_as_number->nb_nonzero)(v); res = (*v->ob_type->tp_as_number->nb_bool)(v);
else if (v->ob_type->tp_as_mapping != NULL && else if (v->ob_type->tp_as_mapping != NULL &&
v->ob_type->tp_as_mapping->mp_length != NULL) v->ob_type->tp_as_mapping->mp_length != NULL)
res = (*v->ob_type->tp_as_mapping->mp_length)(v); res = (*v->ob_type->tp_as_mapping->mp_length)(v);

View file

@ -1784,7 +1784,7 @@ static PyNumberMethods set_as_number = {
0, /*nb_negative*/ 0, /*nb_negative*/
0, /*nb_positive*/ 0, /*nb_positive*/
0, /*nb_absolute*/ 0, /*nb_absolute*/
0, /*nb_nonzero*/ 0, /*nb_bool*/
0, /*nb_invert*/ 0, /*nb_invert*/
0, /*nb_lshift*/ 0, /*nb_lshift*/
0, /*nb_rshift*/ 0, /*nb_rshift*/
@ -1894,7 +1894,7 @@ static PyNumberMethods frozenset_as_number = {
0, /*nb_negative*/ 0, /*nb_negative*/
0, /*nb_positive*/ 0, /*nb_positive*/
0, /*nb_absolute*/ 0, /*nb_absolute*/
0, /*nb_nonzero*/ 0, /*nb_bool*/
0, /*nb_invert*/ 0, /*nb_invert*/
0, /*nb_lshift*/ 0, /*nb_lshift*/
0, /*nb_rshift*/ 0, /*nb_rshift*/

View file

@ -2928,7 +2928,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
COPYNUM(nb_negative); COPYNUM(nb_negative);
COPYNUM(nb_positive); COPYNUM(nb_positive);
COPYNUM(nb_absolute); COPYNUM(nb_absolute);
COPYNUM(nb_nonzero); COPYNUM(nb_bool);
COPYNUM(nb_invert); COPYNUM(nb_invert);
COPYNUM(nb_lshift); COPYNUM(nb_lshift);
COPYNUM(nb_rshift); COPYNUM(nb_rshift);
@ -4206,32 +4206,39 @@ SLOT0(slot_nb_positive, "__pos__")
SLOT0(slot_nb_absolute, "__abs__") SLOT0(slot_nb_absolute, "__abs__")
static int static int
slot_nb_nonzero(PyObject *self) slot_nb_bool(PyObject *self)
{ {
PyObject *func, *args; PyObject *func, *args;
static PyObject *nonzero_str, *len_str; static PyObject *bool_str, *len_str;
int result = -1; int result = -1;
int from_len = 0;
func = lookup_maybe(self, "__nonzero__", &nonzero_str); func = lookup_maybe(self, "__bool__", &bool_str);
if (func == NULL) { if (func == NULL) {
if (PyErr_Occurred()) if (PyErr_Occurred())
return -1; return -1;
func = lookup_maybe(self, "__len__", &len_str); func = lookup_maybe(self, "__len__", &len_str);
if (func == NULL) if (func == NULL)
return PyErr_Occurred() ? -1 : 1; return PyErr_Occurred() ? -1 : 1;
from_len = 1;
} }
args = PyTuple_New(0); args = PyTuple_New(0);
if (args != NULL) { if (args != NULL) {
PyObject *temp = PyObject_Call(func, args, NULL); PyObject *temp = PyObject_Call(func, args, NULL);
Py_DECREF(args); Py_DECREF(args);
if (temp != NULL) { if (temp != NULL) {
if (PyInt_CheckExact(temp) || PyBool_Check(temp)) if (from_len) {
/* enforced by slot_nb_len */
result = PyObject_IsTrue(temp); result = PyObject_IsTrue(temp);
}
else if (PyBool_Check(temp)) {
result = PyObject_IsTrue(temp);
}
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"__nonzero__ should return " "__bool__ should return "
"bool or int, returned %s", "bool, returned %s",
temp->ob_type->tp_name); temp->ob_type->tp_name);
result = -1; result = -1;
} }
Py_DECREF(temp); Py_DECREF(temp);
@ -4887,7 +4894,7 @@ static slotdef slotdefs[] = {
UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"), UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"),
UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc,
"abs(x)"), "abs(x)"),
UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred, UNSLOT("__bool__", nb_bool, slot_nb_bool, wrap_inquirypred,
"x != 0"), "x != 0"),
UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"),
BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"), BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"),

View file

@ -499,7 +499,7 @@ WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
static int static int
proxy_nonzero(PyWeakReference *proxy) proxy_bool(PyWeakReference *proxy)
{ {
PyObject *o = PyWeakref_GET_OBJECT(proxy); PyObject *o = PyWeakref_GET_OBJECT(proxy);
if (!proxy_checkref(proxy)) if (!proxy_checkref(proxy))
@ -596,7 +596,7 @@ static PyNumberMethods proxy_as_number = {
proxy_neg, /*nb_negative*/ proxy_neg, /*nb_negative*/
proxy_pos, /*nb_positive*/ proxy_pos, /*nb_positive*/
proxy_abs, /*nb_absolute*/ proxy_abs, /*nb_absolute*/
(inquiry)proxy_nonzero, /*nb_nonzero*/ (inquiry)proxy_bool, /*nb_bool*/
proxy_invert, /*nb_invert*/ proxy_invert, /*nb_invert*/
proxy_lshift, /*nb_lshift*/ proxy_lshift, /*nb_lshift*/
proxy_rshift, /*nb_rshift*/ proxy_rshift, /*nb_rshift*/

View file

@ -305,7 +305,7 @@ PyDoc_STRVAR(PyHKEY_doc,
"handle - The integer Win32 handle.\n" "handle - The integer Win32 handle.\n"
"\n" "\n"
"Operations:\n" "Operations:\n"
"__nonzero__ - Handles with an open object return true, otherwise false.\n" "__bool__ - Handles with an open object return true, otherwise false.\n"
"__int__ - Converting a handle to an integer returns the Win32 handle.\n" "__int__ - Converting a handle to an integer returns the Win32 handle.\n"
"__cmp__ - Handle objects are compared using the handle value."); "__cmp__ - Handle objects are compared using the handle value.");
@ -375,7 +375,7 @@ PyHKEY_deallocFunc(PyObject *ob)
} }
static int static int
PyHKEY_nonzeroFunc(PyObject *ob) PyHKEY_boolFunc(PyObject *ob)
{ {
return ((PyHKEYObject *)ob)->hkey != 0; return ((PyHKEYObject *)ob)->hkey != 0;
} }
@ -437,7 +437,7 @@ static PyNumberMethods PyHKEY_NumberMethods =
PyHKEY_unaryFailureFunc, /* nb_negative */ PyHKEY_unaryFailureFunc, /* nb_negative */
PyHKEY_unaryFailureFunc, /* nb_positive */ PyHKEY_unaryFailureFunc, /* nb_positive */
PyHKEY_unaryFailureFunc, /* nb_absolute */ PyHKEY_unaryFailureFunc, /* nb_absolute */
PyHKEY_nonzeroFunc, /* nb_nonzero */ PyHKEY_boolFunc, /* nb_bool */
PyHKEY_unaryFailureFunc, /* nb_invert */ PyHKEY_unaryFailureFunc, /* nb_invert */
PyHKEY_binaryFailureFunc, /* nb_lshift */ PyHKEY_binaryFailureFunc, /* nb_lshift */
PyHKEY_binaryFailureFunc, /* nb_rshift */ PyHKEY_binaryFailureFunc, /* nb_rshift */