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):
return funcname
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
# Search all types for __getbuffer__ overloads
......@@ -586,8 +589,12 @@ def use_py2_buffer_functions(env):
find_buffer_types(env)
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) {
#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:
clause = "if"
......@@ -623,7 +630,7 @@ def use_py2_buffer_functions(env):
""")
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 void __Pyx_ReleaseBuffer(Py_buffer *view);
#else
......
......@@ -461,6 +461,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define Py_TPFLAGS_HAVE_INDEX 0")
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(" #define PyBaseString_Type PyUnicode_Type")
code.putln(" #define PyString_Type PyBytes_Type")
......
......@@ -127,13 +127,15 @@ class SlotDescriptor:
# flag Py_TPFLAGS_XXX value indicating presence of slot
# py3k 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.)
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.is_initialised_dynamically = dynamic
self.flag = flag
self.py3k = py3k
self.py2 = py2
self.ifdef = ifdef
def generate(self, scope, code):
if self.is_initialised_dynamically:
......@@ -143,6 +145,9 @@ class SlotDescriptor:
flag = self.flag
py3k = self.py3k
py2 = self.py2
if self.ifdef:
code.putln("#if %s" % self.ifdef)
else:
if not py3k:
code.putln("#if PY_MAJOR_VERSION < 3")
elif not py2:
......@@ -150,9 +155,7 @@ class SlotDescriptor:
if flag:
code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag)
code.putln("%s, /*%s*/" % (value, self.slot_name))
if flag:
code.putln("#endif")
if not py3k or not py2:
if flag or (not py3k or not py2) or self.ifdef:
code.putln("#endif")
# Some C implementations have trouble statically
......@@ -199,8 +202,8 @@ class MethodSlot(SlotDescriptor):
# method_name string The __xxx__ name of the method
# 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):
SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k, py2=py2)
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)
self.signature = signature
self.slot_name = slot_name
self.method_name = method_name
......@@ -296,7 +299,7 @@ class TypeFlagsSlot(SlotDescriptor):
# Descriptor for the type flags slot.
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():
value += "|Py_TPFLAGS_HAVE_GC"
return value
......@@ -609,8 +612,8 @@ PyBufferProcs = (
MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False),
MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False),
MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"),
MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"),
MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000"),
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