From f31aac146e865dc27c4b378d29db7570a5a9e33a Mon Sep 17 00:00:00 2001 From: Lisandro Dalcin Date: Wed, 28 Apr 2010 12:04:13 -0300 Subject: [PATCH] Py3: __cmp__ is gone, __bool__ instead of __nonzero__ --- Cython/Compiler/AnalysedTreeTransforms.py | 3 +- Cython/Compiler/TypeSlots.py | 94 +++++++++++++---------- tests/run/autotestdict.pyx | 16 ++++ tests/run/type_slots_nonzero_bool.pyx | 43 +++++++++++ 4 files changed, 113 insertions(+), 43 deletions(-) create mode 100644 tests/run/type_slots_nonzero_bool.pyx diff --git a/Cython/Compiler/AnalysedTreeTransforms.py b/Cython/Compiler/AnalysedTreeTransforms.py index 6c4e1182..18ca5bd8 100644 --- a/Cython/Compiler/AnalysedTreeTransforms.py +++ b/Cython/Compiler/AnalysedTreeTransforms.py @@ -11,7 +11,8 @@ import Symtab class AutoTestDictTransform(ScopeTrackingTransform): # Handles autotestdict directive - blacklist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__', + blacklist = ['__cinit__', '__dealloc__', '__richcmp__', + '__nonzero__', '__bool__', '__len__', '__contains__'] def visit_ModuleNode(self, node): diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index 232c51d2..ee02c17a 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -126,16 +126,17 @@ class SlotDescriptor(object): # slot_name string Member name of the slot in the type object # is_initialised_dynamically Is initialised by code in the module init function # flag Py_TPFLAGS_XXX value indicating presence of slot - # py3k Indicates presence of slot in Python 3 + # py3 Indicates presence of slot in Python 3 # py2 Indicates presence of slot in Python 2 - # ifdef Full #ifdef string that slot is wrapped in. Using this causes py3k, py2 and flags to be ignored.) + # ifdef Full #ifdef string that slot is wrapped in. Using this causes py3, py2 and flags to be ignored.) - def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True, py2 = True, ifdef = None): + def __init__(self, slot_name, dynamic=0, + flag=None, py3=True, py2=True, ifdef=None): self.slot_name = slot_name self.is_initialised_dynamically = dynamic self.flag = flag - self.py3k = py3k - self.py2 = py2 + self.py3 = py3 + self.py2 = py2 self.ifdef = ifdef def generate(self, scope, code): @@ -144,26 +145,26 @@ class SlotDescriptor(object): else: value = self.slot_code(scope) flag = self.flag - py3k = self.py3k - py2 = self.py2 + py3 = self.py3 + py2 = self.py2 if self.ifdef: code.putln("#if %s" % self.ifdef) else: - if not py3k: + if not py3: code.putln("#if PY_MAJOR_VERSION < 3") elif not py2: code.putln("#if PY_MAJOR_VERSION >= 3") if flag: code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag) - if py3k == '': + if py3 == '': code.putln("#if PY_MAJOR_VERSION >= 3") code.putln("0, /*reserved*/") code.putln("#else") code.putln("%s, /*%s*/" % (value, self.slot_name)) - if py3k == '': + if py3 == '': code.putln("#endif") - if flag or (not py3k or not py2) or self.ifdef: + if flag or (not py3 or not py2) or self.ifdef: code.putln("#endif") # Some C implementations have trouble statically @@ -188,8 +189,8 @@ class FixedSlot(SlotDescriptor): # # value string - def __init__(self, slot_name, value, py3k=True, py2=True, ifdef=None): - SlotDescriptor.__init__(self, slot_name, py3k=py3k, py2=py2, ifdef=ifdef) + def __init__(self, slot_name, value, flag=None, py3=True, py2=True, ifdef=None): + SlotDescriptor.__init__(self, slot_name, flag=flag, py3=py3, py2=py2, ifdef=ifdef) self.value = value def slot_code(self, scope): @@ -199,8 +200,8 @@ class FixedSlot(SlotDescriptor): class EmptySlot(FixedSlot): # Descriptor for a type slot whose value is always 0. - def __init__(self, slot_name, py3k=True, py2=True, ifdef=None): - FixedSlot.__init__(self, slot_name, "0", py3k=py3k, py2=py2, ifdef=ifdef) + def __init__(self, slot_name, flag=None, py3=True, py2=True, ifdef=None): + FixedSlot.__init__(self, slot_name, "0", flag=flag, py3=py3, py2=py2, ifdef=ifdef) class MethodSlot(SlotDescriptor): @@ -208,22 +209,31 @@ class MethodSlot(SlotDescriptor): # # signature Signature # method_name string The __xxx__ name of the method - # default string or None Default value of the slot + # alternatives [string] Alternative list of __xxx__ names for the method - def __init__(self, signature, slot_name, method_name, default = None, flag = None, py3k=True, py2=True, ifdef=None): - SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k, py2=py2, ifdef=ifdef) + def __init__(self, signature, slot_name, method_name, fallback=None, + flag=None, py3=True, py2=True, ifdef=None): + SlotDescriptor.__init__(self, slot_name, flag=flag, py3=py3, py2=py2, ifdef=ifdef) self.signature = signature self.slot_name = slot_name self.method_name = method_name - self.default = default + self.alternatives = [] method_name_to_slot[method_name] = self + # + if fallback: + self.alternatives.append(fallback) + for alt in (self.py2, self.py3): + if isinstance(alt, (tuple, list)): + slot_name, method_name = alt + self.alternatives.append(method_name) + method_name_to_slot[method_name] = self def slot_code(self, scope): entry = scope.lookup_here(self.method_name) if entry and entry.func_cname: return entry.func_cname - if self.default is not None: - entry = scope.lookup_here(self.default) + for method_name in self.alternatives: + entry = scope.lookup_here(method_name) if entry and entry.func_cname: return entry.func_cname return "0" @@ -235,8 +245,8 @@ class InternalMethodSlot(SlotDescriptor): # # slot_name string Member name of the slot in the type object - def __init__(self, slot_name, py2 = True): - SlotDescriptor.__init__(self, slot_name, py2 = py2) + def __init__(self, slot_name, **kargs): + SlotDescriptor.__init__(self, slot_name, **kargs) def slot_code(self, scope): return scope.mangle_internal(self.slot_name) @@ -246,8 +256,8 @@ class GCDependentSlot(InternalMethodSlot): # Descriptor for a slot whose value depends on whether # the type participates in GC. - def __init__(self, slot_name): - InternalMethodSlot.__init__(self, slot_name) + def __init__(self, slot_name, **kargs): + InternalMethodSlot.__init__(self, slot_name, **kargs) def slot_code(self, scope): if not scope.needs_gc(): @@ -267,8 +277,8 @@ class GCDependentSlot(InternalMethodSlot): class ConstructorSlot(InternalMethodSlot): # Descriptor for tp_new and tp_dealloc. - def __init__(self, slot_name, method): - InternalMethodSlot.__init__(self, slot_name) + def __init__(self, slot_name, method, **kargs): + InternalMethodSlot.__init__(self, slot_name, **kargs) self.method = method def slot_code(self, scope): @@ -294,8 +304,8 @@ class SyntheticSlot(InternalMethodSlot): # alternative default value will be placed in the type # slot. - def __init__(self, slot_name, user_methods, default_value, py2 = True): - InternalMethodSlot.__init__(self, slot_name, py2 = py2) + def __init__(self, slot_name, user_methods, default_value, **kargs): + InternalMethodSlot.__init__(self, slot_name, **kargs) self.user_methods = user_methods self.default_value = default_value @@ -550,32 +560,32 @@ PyNumberMethods = ( MethodSlot(binaryfunc, "nb_add", "__add__"), MethodSlot(binaryfunc, "nb_subtract", "__sub__"), MethodSlot(binaryfunc, "nb_multiply", "__mul__"), - MethodSlot(binaryfunc, "nb_divide", "__div__", py3k = False), + MethodSlot(binaryfunc, "nb_divide", "__div__", py3 = False), MethodSlot(binaryfunc, "nb_remainder", "__mod__"), MethodSlot(binaryfunc, "nb_divmod", "__divmod__"), MethodSlot(ternaryfunc, "nb_power", "__pow__"), MethodSlot(unaryfunc, "nb_negative", "__neg__"), MethodSlot(unaryfunc, "nb_positive", "__pos__"), MethodSlot(unaryfunc, "nb_absolute", "__abs__"), - MethodSlot(inquiry, "nb_nonzero", "__nonzero__"), + MethodSlot(inquiry, "nb_nonzero", "__nonzero__", py3 = ("nb_bool", "__bool__")), MethodSlot(unaryfunc, "nb_invert", "__invert__"), MethodSlot(binaryfunc, "nb_lshift", "__lshift__"), MethodSlot(binaryfunc, "nb_rshift", "__rshift__"), MethodSlot(binaryfunc, "nb_and", "__and__"), MethodSlot(binaryfunc, "nb_xor", "__xor__"), MethodSlot(binaryfunc, "nb_or", "__or__"), - EmptySlot("nb_coerce", py3k = False), - MethodSlot(unaryfunc, "nb_int", "__int__", default="__long__"), - MethodSlot(unaryfunc, "nb_long", "__long__", default="__int__", py3k = ""), + EmptySlot("nb_coerce", py3 = False), + MethodSlot(unaryfunc, "nb_int", "__int__", fallback="__long__"), + MethodSlot(unaryfunc, "nb_long", "__long__", fallback="__int__", py3 = ""), MethodSlot(unaryfunc, "nb_float", "__float__"), - MethodSlot(unaryfunc, "nb_oct", "__oct__", py3k = False), - MethodSlot(unaryfunc, "nb_hex", "__hex__", py3k = False), + MethodSlot(unaryfunc, "nb_oct", "__oct__", py3 = False), + MethodSlot(unaryfunc, "nb_hex", "__hex__", py3 = False), # Added in release 2.0 MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__"), MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__"), MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"), - MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3k = False), + MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3 = False), MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"), MethodSlot(ternaryfunc, "nb_inplace_power", "__ipow__"), # NOT iternaryfunc!!! MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"), @@ -615,10 +625,10 @@ PyMappingMethods = ( ) PyBufferProcs = ( - MethodSlot(getreadbufferproc, "bf_getreadbuffer", "__getreadbuffer__", py3k = False), - MethodSlot(getwritebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3k = False), - MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False), - MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False), + MethodSlot(getreadbufferproc, "bf_getreadbuffer", "__getreadbuffer__", py3 = False), + MethodSlot(getwritebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3 = False), + MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3 = False), + MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3 = False), MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000"), MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000") @@ -637,7 +647,7 @@ slot_table = ( EmptySlot("tp_print"), #MethodSlot(printfunc, "tp_print", "__print__"), EmptySlot("tp_getattr"), EmptySlot("tp_setattr"), - MethodSlot(cmpfunc, "tp_compare", "__cmp__"), + MethodSlot(cmpfunc, "tp_compare", "__cmp__", py3 = ''), MethodSlot(reprfunc, "tp_repr", "__repr__"), SuiteSlot(PyNumberMethods, "PyNumberMethods", "tp_as_number"), diff --git a/tests/run/autotestdict.pyx b/tests/run/autotestdict.pyx index 2f8bc711..51e347ee 100644 --- a/tests/run/autotestdict.pyx +++ b/tests/run/autotestdict.pyx @@ -126,4 +126,20 @@ cdef class MyCdefClass: False """ +cdef class MyOtherCdefClass: + """ + Needs no hack + + >>> True + True + """ + + def __bool__(self): + """ + Should not be included, as it can't be looked up with getattr in Py 2 + + >>> True + False + """ + cdeffunc() diff --git a/tests/run/type_slots_nonzero_bool.pyx b/tests/run/type_slots_nonzero_bool.pyx new file mode 100644 index 00000000..a9dd7914 --- /dev/null +++ b/tests/run/type_slots_nonzero_bool.pyx @@ -0,0 +1,43 @@ +__doc__ = """ + +>>> not not BoolA(0) +False +>>> not not BoolA(1) +True + +>>> not not BoolB(0) +False +>>> not not BoolB(1) +True + +>>> not not BoolX(0) +False +>>> not not BoolX(1) +True + +>>> not not BoolY(0) +False +>>> not not BoolY(1) +True + +""" + +cdef class BoolA: + cdef bint value + def __cinit__(self, bint value): + self.value = value + def __nonzero__(self): + return self.value + +cdef class BoolB: + cdef bint value + def __cinit__(self, bint value): + self.value = value + def __bool__(self): + return self.value + +cdef class BoolX(BoolA): + pass + +cdef class BoolY(BoolB): + pass -- 2.26.2