Commit 509b419f authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Buffers: Better Py2.6 support (ticket 62)

parent 3ac9414c
...@@ -566,6 +566,9 @@ def buffer_type_checker(dtype, code): ...@@ -566,6 +566,9 @@ def buffer_type_checker(dtype, code):
return funcname return funcname
def use_py2_buffer_functions(env): def use_py2_buffer_functions(env):
# Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
# For >= 2.6 we do double mode -- use the new buffer interface on objects
# which has the right tp_flags set, but emulation otherwise.
codename = "PyObject_GetBuffer" # just a representative unique key codename = "PyObject_GetBuffer" # just a representative unique key
# Search all types for __getbuffer__ overloads # Search all types for __getbuffer__ overloads
...@@ -586,8 +589,12 @@ def use_py2_buffer_functions(env): ...@@ -586,8 +589,12 @@ def use_py2_buffer_functions(env):
find_buffer_types(env) find_buffer_types(env)
code = dedent(""" code = dedent("""
#if (PY_MAJOR_VERSION < 3) && !(Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER) #if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
#if PY_VERSION_HEX >= 0x02060000
if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)
return PyObject_GetBuffer(obj, view, flags);
#endif
""") """)
if len(types) > 0: if len(types) > 0:
clause = "if" clause = "if"
...@@ -623,7 +630,7 @@ def use_py2_buffer_functions(env): ...@@ -623,7 +630,7 @@ def use_py2_buffer_functions(env):
""") """)
env.use_utility_code([dedent("""\ env.use_utility_code([dedent("""\
#if (PY_MAJOR_VERSION < 3) && !(Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER) #if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
static void __Pyx_ReleaseBuffer(Py_buffer *view); static void __Pyx_ReleaseBuffer(Py_buffer *view);
#else #else
......
...@@ -461,6 +461,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -461,6 +461,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define Py_TPFLAGS_HAVE_INDEX 0") code.putln(" #define Py_TPFLAGS_HAVE_INDEX 0")
code.putln("#endif") code.putln("#endif")
code.putln("#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3)")
code.putln(" #define Py_TPFLAGS_HAVE_NEWBUFFER 0")
code.putln("#endif")
code.putln("#if PY_MAJOR_VERSION >= 3") code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln(" #define PyBaseString_Type PyUnicode_Type") code.putln(" #define PyBaseString_Type PyUnicode_Type")
code.putln(" #define PyString_Type PyBytes_Type") code.putln(" #define PyString_Type PyBytes_Type")
......
...@@ -127,13 +127,15 @@ class SlotDescriptor: ...@@ -127,13 +127,15 @@ class SlotDescriptor:
# flag Py_TPFLAGS_XXX value indicating presence of slot # flag Py_TPFLAGS_XXX value indicating presence of slot
# py3k Indicates presence of slot in Python 3 # py3k Indicates presence of slot in Python 3
# py2 Indicates presence of slot in Python 2 # 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.)
def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True, py2 = True): def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True, py2 = True, ifdef = None):
self.slot_name = slot_name self.slot_name = slot_name
self.is_initialised_dynamically = dynamic self.is_initialised_dynamically = dynamic
self.flag = flag self.flag = flag
self.py3k = py3k self.py3k = py3k
self.py2 = py2 self.py2 = py2
self.ifdef = ifdef
def generate(self, scope, code): def generate(self, scope, code):
if self.is_initialised_dynamically: if self.is_initialised_dynamically:
...@@ -143,16 +145,17 @@ class SlotDescriptor: ...@@ -143,16 +145,17 @@ class SlotDescriptor:
flag = self.flag flag = self.flag
py3k = self.py3k py3k = self.py3k
py2 = self.py2 py2 = self.py2
if not py3k: if self.ifdef:
code.putln("#if PY_MAJOR_VERSION < 3") code.putln("#if %s" % self.ifdef)
elif not py2: else:
code.putln("#if PY_MAJOR_VERSION >= 3") if not py3k:
if flag: code.putln("#if PY_MAJOR_VERSION < 3")
code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag) elif not py2:
code.putln("#if PY_MAJOR_VERSION >= 3")
if flag:
code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag)
code.putln("%s, /*%s*/" % (value, self.slot_name)) code.putln("%s, /*%s*/" % (value, self.slot_name))
if flag: if flag or (not py3k or not py2) or self.ifdef:
code.putln("#endif")
if not py3k or not py2:
code.putln("#endif") code.putln("#endif")
# Some C implementations have trouble statically # Some C implementations have trouble statically
...@@ -199,8 +202,8 @@ class MethodSlot(SlotDescriptor): ...@@ -199,8 +202,8 @@ class MethodSlot(SlotDescriptor):
# method_name string The __xxx__ name of the method # method_name string The __xxx__ name of the method
# default string or None Default value of the slot # default string or None Default value of the slot
def __init__(self, signature, slot_name, method_name, default = None, flag = None, py3k=True, py2=True): 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) SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k, py2=py2, ifdef=ifdef)
self.signature = signature self.signature = signature
self.slot_name = slot_name self.slot_name = slot_name
self.method_name = method_name self.method_name = method_name
...@@ -296,7 +299,7 @@ class TypeFlagsSlot(SlotDescriptor): ...@@ -296,7 +299,7 @@ class TypeFlagsSlot(SlotDescriptor):
# Descriptor for the type flags slot. # Descriptor for the type flags slot.
def slot_code(self, scope): def slot_code(self, scope):
value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE" value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_NEWBUFFER"
if scope.needs_gc(): if scope.needs_gc():
value += "|Py_TPFLAGS_HAVE_GC" value += "|Py_TPFLAGS_HAVE_GC"
return value return value
...@@ -609,8 +612,8 @@ PyBufferProcs = ( ...@@ -609,8 +612,8 @@ PyBufferProcs = (
MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False), MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False),
MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False), MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False),
MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"), MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000"),
MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"), MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000")
) )
#------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment