Commit 521185b4 authored by Lisandro Dalcin's avatar Lisandro Dalcin

remove dependency on structmember.h

parent 87b5c78b
......@@ -426,6 +426,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.globalstate["end"].putln("#endif /* Py_PYTHON_H */")
code.put("""
#include <stddef.h> /* For offsetof */
#ifndef offsetof
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
#endif
#ifndef PY_LONG_LONG
#define PY_LONG_LONG LONG_LONG
#endif
......@@ -903,7 +908,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_descr_set_function(scope, code)
self.generate_property_accessors(scope, code)
self.generate_method_table(scope, code)
self.generate_member_table(scope, code)
self.generate_getset_table(scope, code)
self.generate_typeobj_definition(full_module_name, entry, code)
......@@ -1529,34 +1533,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"};")
def generate_member_table(self, env, code):
#print "ModuleNode.generate_member_table: scope =", env ###
if env.public_attr_entries:
code.putln("")
code.putln(
"static struct PyMemberDef %s[] = {" %
env.member_table_cname)
type = env.parent_type
if type.typedef_flag:
objstruct = type.objstruct_cname
else:
objstruct = "struct %s" % type.objstruct_cname
for entry in env.public_attr_entries:
type_code = entry.type.pymemberdef_typecode
if entry.visibility == 'readonly':
flags = "READONLY"
else:
flags = "0"
code.putln('{(char *)"%s", %s, %s, %s, 0},' % (
entry.name,
type_code,
"offsetof(%s, %s)" % (objstruct, entry.cname),
flags))
code.putln(
"{0, 0, 0, 0, 0}")
code.putln(
"};")
def generate_getset_table(self, env, code):
if env.property_entries:
code.putln("")
......
......@@ -891,13 +891,13 @@ class CVarDefNode(StatNode):
# declarators [CDeclaratorNode]
# in_pxd boolean
# api boolean
# need_properties [entry]
# properties [entry]
# decorators [cython.locals(...)] or None
# directive_locals { string : NameNode } locals defined by cython.locals(...)
child_attrs = ["base_type", "declarators"]
need_properties = ()
properties = ()
decorators = None
directive_locals = {}
......@@ -912,15 +912,12 @@ class CVarDefNode(StatNode):
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
if (dest_scope.is_c_class_scope
and self.visibility == 'public'
and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)):
self.need_properties = []
and self.visibility in ('public', 'readonly')):
self.properties = []
need_property = True
visibility = 'private'
else:
need_property = False
visibility = self.visibility
visibility = self.visibility
for declarator in self.declarators:
name_declarator, type = declarator.analyse(base_type, env)
......@@ -951,8 +948,7 @@ class CVarDefNode(StatNode):
entry = dest_scope.declare_var(name, type, declarator.pos,
cname = cname, visibility = visibility, is_cdef = 1)
if need_property:
self.need_properties.append(entry)
entry.needs_property = 1
self.properties.append(entry)
class CStructOrUnionDefNode(StatNode):
......
......@@ -952,6 +952,11 @@ property NAME:
def __set__(self, value):
ATTR = value
""", level='c_class')
basic_property_ro = TreeFragment(u"""
property NAME:
def __get__(self):
return ATTR
""", level='c_class')
def __call__(self, root):
self.env_stack = [root.scope]
......@@ -1037,12 +1042,9 @@ property NAME:
# to ensure all CNameDeclaratorNodes are visited.
self.visitchildren(node)
if node.need_properties:
# cdef public attributes may need type testing on
# assignment, so we create a property accesss
# mechanism for them.
if node.properties:
stats = []
for entry in node.need_properties:
for entry in node.properties:
property = self.create_Property(entry)
property.analyse_declarations(node.dest_scope)
self.visit(property)
......@@ -1052,13 +1054,34 @@ property NAME:
return None
def create_Property(self, entry):
template = self.basic_property
if entry.visibility == 'public':
template = self.basic_property
elif entry.visibility == 'readonly':
template = self.basic_property_ro
property = template.substitute({
u"ATTR": AttributeNode(pos=entry.pos,
obj=NameNode(pos=entry.pos, name="self"),
attribute=entry.name),
}, pos=entry.pos).stats[0]
property.name = entry.name
# ---------------------------------------
# XXX This should go to AutoDocTransforms
# ---------------------------------------
if self.current_directives['embedsignature']:
attr_name = entry.name
type_name = entry.type.declaration_code("", for_display=1)
default_value = ''
if not entry.type.is_pyobject:
type_name = "'%s'" % type_name
elif entry.type.is_extension_type:
type_name = entry.type.module_name + '.' + type_name
if entry.init is not None:
default_value = ' = ' + entry.init
elif entry.init_to_none:
default_value = ' = ' + repr(None)
docstring = attr_name + ': ' + type_name + default_value
property.doc = EncodedString(docstring)
# ---------------------------------------
return property
class AnalyseExpressionsTransform(CythonTransform):
......
......@@ -56,7 +56,6 @@ class PyrexType(BaseType):
# is_buffer boolean Is buffer access type
# has_attributes boolean Has C dot-selectable attributes
# default_value string Initial value
# pymemberdef_typecode string Type code for PyMemberDef struct
#
# declaration_code(entity_code,
# for_display = 0, dll_linkage = None, pyrex = 0)
......@@ -109,7 +108,6 @@ class PyrexType(BaseType):
is_buffer = 0
has_attributes = 0
default_value = ""
pymemberdef_typecode = None
def resolve(self):
# If a typedef, returns the base type.
......@@ -198,18 +196,6 @@ class CTypedefType(BaseType):
self.typedef_cname = cname
self.typedef_base_type = base_type
self.typedef_is_external = is_external
# Make typecodes in external typedefs use typesize-neutral macros
if is_external:
typecode = None
if base_type.is_int:
if base_type.signed == 0:
typecode = "__Pyx_T_UNSIGNED_INT"
else:
typecode = "__Pyx_T_SIGNED_INT"
elif base_type.is_float and not rank_to_type_name[base_type.rank] == "long double":
typecode = "__Pyx_T_FLOATING"
if typecode:
self.pymemberdef_typecode = "%s(%s)" % (typecode, cname)
def resolve(self):
return self.typedef_base_type.resolve()
......@@ -349,7 +335,6 @@ class PyObjectType(PyrexType):
name = "object"
is_pyobject = 1
default_value = "0"
pymemberdef_typecode = "T_OBJECT"
buffer_defaults = None
is_extern = False
is_subclassed = False
......@@ -618,10 +603,9 @@ class CNumericType(CType):
sign_words = ("unsigned ", "", "signed ")
def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
def __init__(self, rank, signed = 1):
self.rank = rank
self.signed = signed
self.pymemberdef_typecode = pymemberdef_typecode
def sign_and_name(self):
s = self.sign_words[self.signed]
......@@ -787,8 +771,8 @@ class CIntType(CNumericType):
from_py_function = "__Pyx_PyInt_AsInt"
exception_value = -1
def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
def __init__(self, rank, signed, is_returncode = 0):
CNumericType.__init__(self, rank, signed)
self.is_returncode = is_returncode
if self.from_py_function == "__Pyx_PyInt_AsInt":
self.from_py_function = self.get_type_conversion()
......@@ -887,8 +871,8 @@ class CFloatType(CNumericType):
exception_value = -1
def __init__(self, rank, pymemberdef_typecode = None, math_h_modifier = ''):
CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
def __init__(self, rank, math_h_modifier = ''):
CNumericType.__init__(self, rank, 1)
self.math_h_modifier = math_h_modifier
def assignable_from_resolved_type(self, src_type):
......@@ -1988,7 +1972,6 @@ class CStringType(object):
class CUTF8CharArrayType(CStringType, CArrayType):
# C 'char []' type.
pymemberdef_typecode = "T_STRING_INPLACE"
is_unicode = 1
to_py_function = "PyUnicode_DecodeUTF8"
......@@ -2000,8 +1983,6 @@ class CUTF8CharArrayType(CStringType, CArrayType):
class CCharArrayType(CStringType, CArrayType):
# C 'char []' type.
pymemberdef_typecode = "T_STRING_INPLACE"
def __init__(self, size):
CArrayType.__init__(self, c_char_type, size)
......@@ -2009,8 +1990,6 @@ class CCharArrayType(CStringType, CArrayType):
class CCharPtrType(CStringType, CPtrType):
# C 'char *' type.
pymemberdef_typecode = "T_STRING"
def __init__(self):
CPtrType.__init__(self, c_char_type)
......@@ -2018,8 +1997,6 @@ class CCharPtrType(CStringType, CPtrType):
class CUCharPtrType(CStringType, CPtrType):
# C 'unsigned char *' type.
pymemberdef_typecode = "T_STRING"
to_py_function = "__Pyx_PyBytes_FromUString"
from_py_function = "__Pyx_PyBytes_AsUString"
......@@ -2085,30 +2062,30 @@ c_void_type = CVoidType()
c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_uchar_type = CIntType(0, 0, "T_UBYTE")
c_ushort_type = CIntType(1, 0, "T_USHORT")
c_uint_type = CUIntType(2, 0, "T_UINT")
c_ulong_type = CULongType(3, 0, "T_ULONG")
c_ulonglong_type = CULongLongType(6, 0, "T_ULONGLONG")
c_char_type = CIntType(0, 1, "T_CHAR")
c_short_type = CIntType(1, 1, "T_SHORT")
c_int_type = CIntType(2, 1, "T_INT")
c_long_type = CLongType(3, 1, "T_LONG")
c_longlong_type = CLongLongType(6, 1, "T_LONGLONG")
c_bint_type = CBIntType(2, 1, "T_INT")
c_schar_type = CIntType(0, 2, "T_CHAR")
c_sshort_type = CIntType(1, 2, "T_SHORT")
c_sint_type = CIntType(2, 2, "T_INT")
c_slong_type = CLongType(3, 2, "T_LONG")
c_slonglong_type = CLongLongType(6, 2, "T_LONGLONG")
c_py_ssize_t_type = CPySSizeTType(4, 2, "T_PYSSIZET")
c_size_t_type = CSizeTType(5, 0, "T_SIZET")
c_float_type = CFloatType(7, "T_FLOAT", math_h_modifier='f')
c_double_type = CFloatType(8, "T_DOUBLE")
c_uchar_type = CIntType(0, 0)
c_ushort_type = CIntType(1, 0)
c_uint_type = CUIntType(2, 0)
c_ulong_type = CULongType(3, 0)
c_ulonglong_type = CULongLongType(6, 0)
c_char_type = CIntType(0, 1)
c_short_type = CIntType(1, 1)
c_int_type = CIntType(2, 1)
c_long_type = CLongType(3, 1)
c_longlong_type = CLongLongType(6, 1)
c_bint_type = CBIntType(2, 1)
c_schar_type = CIntType(0, 2)
c_sshort_type = CIntType(1, 2)
c_sint_type = CIntType(2, 2)
c_slong_type = CLongType(3, 2)
c_slonglong_type = CLongLongType(6, 2)
c_py_ssize_t_type = CPySSizeTType(4, 2)
c_size_t_type = CSizeTType(5, 0)
c_float_type = CFloatType(7, math_h_modifier='f')
c_double_type = CFloatType(8)
c_longdouble_type = CFloatType(9, math_h_modifier='l')
c_double_complex_type = CComplexType(c_double_type)
......@@ -2123,7 +2100,7 @@ c_int_ptr_type = CPtrType(c_int_type)
c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
c_size_t_ptr_type = CPtrType(c_size_t_type)
c_returncode_type = CIntType(2, 1, "T_INT", is_returncode = 1)
c_returncode_type = CIntType(2, 1, is_returncode = 1)
c_anon_enum_type = CAnonEnumType(-1, 1)
......@@ -2492,68 +2469,6 @@ type_conversion_predeclarations = """
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
#if !defined(T_PYSSIZET)
#if PY_VERSION_HEX < 0x02050000
#define T_PYSSIZET T_INT
#elif !defined(T_LONGLONG)
#define T_PYSSIZET \\
((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \\
((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1))
#else
#define T_PYSSIZET \\
((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \\
((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : \\
((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))
#endif
#endif
#if !defined(T_ULONGLONG)
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1))))
#else
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \\
((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))))
#endif
#if !defined(T_LONGLONG)
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : -1))))
#else
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : \\
((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))))
#endif
#define __Pyx_T_FLOATING(x) \\
((sizeof(x) == sizeof(float)) ? T_FLOAT : \\
((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1))
#if !defined(T_SIZET)
#if !defined(T_ULONGLONG)
#define T_SIZET \\
((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1))
#else
#define T_SIZET \\
((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : \\
((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))
#endif
#endif
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
......
......@@ -791,7 +791,7 @@ class ModuleScope(Scope):
self.doc_cname = Naming.moddoc_cname
self.utility_code_list = []
self.module_entries = {}
self.python_include_files = ["Python.h", "structmember.h"]
self.python_include_files = ["Python.h"]
self.include_files = []
self.type_names = dict(outer_scope.type_names)
self.pxd_file_loaded = 0
......@@ -1321,10 +1321,8 @@ class CClassScope(ClassScope):
# #typeobj_cname string or None
# #objstruct_cname string
# method_table_cname string
# member_table_cname string
# getset_table_cname string
# has_pyobject_attrs boolean Any PyObject attributes?
# public_attr_entries boolean public/readonly attrs
# property_entries [Entry]
# defined boolean Defined in .pxd file
# implemented boolean Defined in .pyx file
......@@ -1336,10 +1334,8 @@ class CClassScope(ClassScope):
ClassScope.__init__(self, name, outer_scope)
if visibility != 'extern':
self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
self.member_table_cname = outer_scope.mangle(Naming.memtab_prefix, name)
self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
self.has_pyobject_attrs = 0
self.public_attr_entries = []
self.property_entries = []
self.inherited_var_entries = []
self.defined = 0
......@@ -1380,16 +1376,14 @@ class CClassScope(ClassScope):
error(pos,
"Attribute of extension type cannot be declared %s" % visibility)
if visibility in ('public', 'readonly'):
if type.pymemberdef_typecode:
self.public_attr_entries.append(entry)
if name == "__weakref__":
error(pos, "Special attribute __weakref__ cannot be exposed to Python")
else:
error(pos,
"C attribute of type '%s' cannot be accessed from Python" % type)
if visibility == 'public' and type.is_extension_type:
error(pos,
"Non-generic Python attribute cannot be exposed for writing from Python")
if name == "__weakref__":
error(pos, "Special attribute __weakref__ cannot be exposed to Python")
if not type.is_pyobject:
if (not type.create_to_py_utility_code(self) or
(visibility=='public' and not
type.create_from_py_utility_code(self))):
error(pos,
"C attribute of type '%s' cannot be accessed from Python" % type)
return entry
else:
if type is unspecified_type:
......
......@@ -370,10 +370,7 @@ class MemberTableSlot(SlotDescriptor):
# Slot descriptor for the table of Python-accessible attributes.
def slot_code(self, scope):
if scope.public_attr_entries:
return scope.member_table_cname
else:
return "0"
return "0"
class GetSetSlot(SlotDescriptor):
......
......@@ -8,7 +8,7 @@ cdef class Spam:
cdef public float f
cdef public double d
cdef public char *s
cdef public char a[42]
cdef readonly char a[42]
cdef public object o
cdef readonly int r
cdef readonly Spam e
ctypedef void* VoidP
cdef class Spam:
cdef VoidP vp0
cdef readonly VoidP vp2
cdef public VoidP vp1
ctypedef struct Foo:
int i
cdef class Bar:
cdef Foo foo0
cdef readonly Foo foo2
cdef public Foo foo1
pass
_ERRORS = u"""
5:24: C attribute of type 'VoidP' cannot be accessed from Python
5:24: Cannot convert 'VoidP' to Python object
6:24: C attribute of type 'VoidP' cannot be accessed from Python
6:24: Cannot convert 'VoidP' to Python object
6:24: Cannot convert Python object to 'VoidP'
14:22: C attribute of type 'Foo' cannot be accessed from Python
14:22: Cannot convert Python object to 'Foo'
"""
......@@ -13,7 +13,10 @@ cdef void f():
x = c.__weakref__
c.__weakref__ = x
_ERRORS = u"""
5:20: Illegal use of special attribute __weakref__
5:20: Illegal use of special attribute __weakref__
5:20: Special attribute __weakref__ cannot be exposed to Python
8:22: Illegal use of special attribute __weakref__
8:22: Special attribute __weakref__ cannot be exposed to Python
13:6: Illegal use of special attribute __weakref__
14:2: Illegal use of special attribute __weakref__
......
#cython: embedsignature=True
__doc__ = u"""
>>> a = A()
>>> a.h = 7
>>> a.i = 127
>>> a.l = 255
>>> a.q = 255
>>> a.f = 1.0/2.0
>>> a.d = 1/2.0 + 1/4.0
>>> a.g = 1/2.0 + 1/4.0 + 1/8.0
>>> a.Zf = 1+2j
>>> a.Zd = 3+4j
>>> a.Zg = 5+6j
>>> a.h, a.i, a.l
(7, 127, 255)
>>> a.ro_h, a.ro_i, a.ro_l
(7, 127, 255)
>>> a.f, a.d, a.g
(0.5, 0.75, 0.875)
>>> a.ro_f, a.ro_d, a.ro_g
(0.5, 0.75, 0.875)
>>> a.Zf, a.Zd, a.Zg
((1+2j), (3+4j), (5+6j))
>>> a.ro_Zf, a.ro_Zd, a.ro_Zg
((1+2j), (3+4j), (5+6j))
>>> b = B()
>>> b.a0 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
>>> b.b0 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
>>> b.c0 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
>>> isinstance(b.a1, type(None))
True
>>> isinstance(b.a2, type(None))
True
>>> isinstance(b.b1, list)
True
>>> isinstance(b.b2, list)
True
>>> isinstance(b.c1, A)
True
>>> isinstance(b.c2, A)
True
>>> b.a1 = a
>>> b.a1 is not b.a2
True
>>> b.b1 = 1 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ...
>>> b.c1 = 1 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ...
>>> b.a2 = None #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
>>> b.b2 = [] #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
>>> b.c2 = A() #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: ...
"""
cdef class A:
cdef public short h
cdef public int i
cdef public long l
cdef public long long q
cdef public float f
cdef public double d
cdef public long double g
cdef public float complex Zf
cdef public double complex Zd
cdef public long double complex Zg
cdef readonly short ro_h
cdef readonly int ro_i
cdef readonly long ro_l
cdef readonly long long ro_q
cdef readonly float ro_f
cdef readonly double ro_d
cdef readonly long double ro_g
cdef readonly float complex ro_Zf
cdef readonly double complex ro_Zd
cdef readonly long double complex ro_Zg
def __cinit__(self):
self.ro_h = 7
self.ro_i = 127
self.ro_l = 255
self.ro_q = 255
self.ro_f = 1.0/2.0
self.ro_d = 1/2.0 + 1/4.0
self.ro_g = 1/2.0 + 1/4.0 + 1/8.0
self.ro_Zf = 1+2j
self.ro_Zd = 3+4j
self.ro_Zg = 5+6j
cdef class B:
cdef object a0
cdef public object a1
cdef readonly object a2
cdef list b0
cdef public list b1
cdef readonly list b2
cdef A c0
cdef public A c1
cdef readonly A c2
def __cinit__(self):
self.b0 = self.b1 = self.b2 = []
self.c0 = self.c1 = self.c2 = A()
......@@ -5,6 +5,15 @@ __doc__ = ur"""
>>> print (Ext.__doc__)
Ext(a, b, c=None)
>>> print (Ext.attr0.__doc__)
attr0: 'int'
>>> print (Ext.attr1.__doc__)
attr1: object
>>> print (Ext.attr2.__doc__)
attr2: list
>>> print (Ext.attr3.__doc__)
attr3: embedsignatures.Ext
>>> print (Ext.a.__doc__)
Ext.a(self)
......@@ -145,6 +154,11 @@ __doc__ = ur"""
cdef class Ext:
cdef public int attr0
cdef public attr1
cdef public list attr2
cdef public Ext attr3
def __init__(self, a, b, c=None):
pass
......
__doc__ = """
>>> readonly()
>>> readonly() #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: readonly attribute
...
TypeError: ...
"""
import sys
if sys.version_info[0] >= 3:
if sys.version_info[0:2] >= (2,4):
__doc__ = __doc__.replace(u'TypeError:', u'AttributeError:')
......@@ -51,9 +51,7 @@ def f():
def longdouble_access():
"""
>>> longdouble_access()
Traceback (most recent call last):
...
SystemError: bad memberdescr type
42.0
"""
cdef object c = MyClass()
print c.float_isreally_longdouble
......
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