Author: Matti Picus <matti.pi...@gmail.com> Branch: cpyext-add_newdoc Changeset: r91681:4e8cc878567f Date: 2017-07-04 15:47 -0400 http://bitbucket.org/pypy/pypy/changeset/4e8cc878567f/
Log: test, add more doc assignment from cpyext diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -250,12 +250,13 @@ return res class GetSetProperty(W_Root): - _immutable_fields_ = ["fget", "fset", "fdel"] + _immutable_fields_ = ["fget", "fset", "fdel", "is_cpyext"] w_objclass = None @specialize.arg(7) def __init__(self, fget, fset=None, fdel=None, doc=None, - cls=None, use_closure=False, tag=None, name=None): + cls=None, use_closure=False, tag=None, name=None, + is_cpyext=False): objclass_getter, cls = make_objclass_getter(tag, fget, cls) fget = make_descr_typecheck_wrapper((tag, 0), fget, cls=cls, use_closure=use_closure) @@ -264,10 +265,10 @@ fdel = make_descr_typecheck_wrapper((tag, 2), fdel, cls=cls, use_closure=use_closure) self._init(fget, fset, fdel, doc, cls, objclass_getter, use_closure, - name) + name, is_cpyext) def _init(self, fget, fset, fdel, doc, cls, objclass_getter, use_closure, - name): + name, is_cpyext): self.fget = fget self.fset = fset self.fdel = fdel @@ -276,12 +277,13 @@ self.objclass_getter = objclass_getter self.use_closure = use_closure self.name = name if name is not None else '<generic property>' + self.is_cpyext = is_cpyext def copy_for_type(self, w_objclass): if self.objclass_getter is None: new = instantiate(GetSetProperty) new._init(self.fget, self.fset, self.fdel, self.doc, self.reqcls, - None, self.use_closure, self.name) + None, self.use_closure, self.name, self.is_cpyext) new.w_objclass = w_objclass return new else: @@ -348,6 +350,11 @@ space._see_getsetproperty(self) # only for fake/objspace.py return self + def descr__doc(space, w_self): + if w_self.doc is None and w_self.is_cpyext: + from pypy.module.cpyext.typeobject import maybe_set_getset_doc + maybe_set_getset_doc(space, w_self) + return space.newtext_or_none(w_self.doc) def interp_attrproperty(name, cls, doc=None, wrapfn=None): "NOT_RPYTHON: initialization-time only" @@ -374,7 +381,8 @@ __delete__ = interp2app(GetSetProperty.descr_property_del), __name__ = interp_attrproperty('name', cls=GetSetProperty, wrapfn="newtext_or_none"), __objclass__ = GetSetProperty(GetSetProperty.descr_get_objclass), - __doc__ = interp_attrproperty('doc', cls=GetSetProperty, wrapfn="newtext_or_none"), + __doc__ = GetSetProperty(GetSetProperty.descr__doc, + cls=GetSetProperty, name="__doc__"), ) assert not GetSetProperty.typedef.acceptable_as_base_class # no __new__ diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py --- a/pypy/module/cpyext/methodobject.py +++ b/pypy/module/cpyext/methodobject.py @@ -245,6 +245,7 @@ wrapfn="newtext_or_none"), __objclass__ = interp_attrproperty_w('w_objclass', cls=W_PyCMethodObject), __repr__ = interp2app(W_PyCMethodObject.descr_method_repr), + __doc__ = GetSetProperty(W_PyCFunctionObject.get_doc), ) W_PyCMethodObject.typedef.acceptable_as_base_class = False @@ -257,6 +258,7 @@ __objclass__ = interp_attrproperty_w('w_objclass', cls=W_PyCClassMethodObject), __repr__ = interp2app(W_PyCClassMethodObject.descr_method_repr), + __doc__ = GetSetProperty(W_PyCFunctionObject.get_doc), ) W_PyCClassMethodObject.typedef.acceptable_as_base_class = False diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -1356,25 +1356,72 @@ return (PyObject *)&FooType_Type; ''' ), - ("add_doc_string", "METH_O", + ("add_doc_string_type", "METH_O", ''' PyTypeObject* obj = (PyTypeObject *)args; obj->tp_doc = "A docstring"; Py_INCREF(Py_None); return Py_None; ''' + ), + ("add_doc_string_getset", "METH_O", + ''' + PyGetSetDescrObject * obj = (PyGetSetDescrObject*)args; + obj->d_getset->doc = "A docstring"; + Py_INCREF(Py_None); + return Py_None; + ''' + ), + ("add_doc_string_method", "METH_O", + ''' + PyMethodDescrObject * obj = (PyMethodDescrObject*)args; + obj->d_method->ml_doc = "A docstring"; + Py_INCREF(Py_None); + return Py_None; + ''' )], prologue=''' static PyTypeObject FooType_Type = { PyVarObject_HEAD_INIT(NULL, 0) "foo.Type", }; + + static PyObject * + foo_42(void *self) + { + return PyInt_FromLong(42L); + }; + + static PyObject * + foo_43(void *self) + { + return PyInt_FromLong(43L); + }; + + static PyGetSetDef foo_getsetlist[] = { + {"foo_42", + (getter)foo_42, + NULL, + NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}, + }; + + static PyMethodDef foo_methods[] = { + {"foo_43", (PyCFunction)foo_43, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL} /* sentinel */ + }; ''', more_init=''' FooType_Type.tp_flags = Py_TPFLAGS_DEFAULT; FooType_Type.tp_base = &PyType_Type; + FooType_Type.tp_getset = foo_getsetlist; + FooType_Type.tp_methods = foo_methods; if (PyType_Ready(&FooType_Type) < 0) INITERROR; ''') a = module.getType() - module.add_doc_string(a) + module.add_doc_string_type(a) assert a.__doc__ == "A docstring" assert a.__dict__['__doc__'] == None # compatibility + module.add_doc_string_getset(a.foo_42) + assert a.foo_42.__doc__ == "A docstring" + module.add_doc_string_method(a.foo_43) + assert a.foo_43.__doc__ == "A docstring" diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -59,12 +59,12 @@ set = GettersAndSetters.setter.im_func GetSetProperty.__init__(self, get, set, None, doc, cls=None, use_closure=True, - tag="cpyext_1") + tag="cpyext_1", is_cpyext=True) def PyDescr_NewGetSet(space, getset, w_type): return W_GetSetPropertyEx(getset, w_type) -def make_GetSet(space, getsetprop): +def make_PyGetSetDef(space, getsetprop): py_getsetdef = lltype.malloc(PyGetSetDef, flavor='raw') doc = getsetprop.doc if doc: @@ -95,7 +95,13 @@ set = GettersAndSetters.member_setter.im_func GetSetProperty.__init__(self, get, set, del_, doc, cls=None, use_closure=True, - tag="cpyext_2") + tag="cpyext_2", is_cpyext=True) + + def descr__doc(space, w_self): + if w_self.doc is None and w_self.member.c_doc: + w_self.doc = rffi.charp2str(w_self.member.c_doc) + return space.newtext_or_none(w_self.doc) + # change the typedef name W_MemberDescr.typedef = TypeDef( @@ -106,8 +112,8 @@ __name__ = interp_attrproperty('name', cls=GetSetProperty, wrapfn="newtext_or_none"), __objclass__ = GetSetProperty(GetSetProperty.descr_get_objclass), - __doc__ = interp_attrproperty('doc', cls=GetSetProperty, - wrapfn="newtext_or_none"), + __doc__ = GetSetProperty(W_MemberDescr.descr__doc, + cls=W_MemberDescr, name="__doc__"), ) assert not W_MemberDescr.typedef.acceptable_as_base_class # no __new__ @@ -183,16 +189,17 @@ w_obj = space.allocate_instance(W_MemberDescr, w_type) w_obj.__init__(member, w_type) track_reference(space, obj, w_obj) + print 'memberdescr_realise called' return w_obj def getsetdescr_attach(space, py_obj, w_obj, w_userdata=None): """ - Fills a newly allocated PyGetSetDescrObject with the given W_GetSetPropertyEx - object. The values must not be modified. + Fills a newly allocated PyGetSetDescrObject with the given + W_GetSetPropertyEx object. The values must not be modified. """ py_getsetdescr = rffi.cast(PyGetSetDescrObject, py_obj) - if isinstance(w_obj, GetSetProperty): - py_getsetdef = make_GetSet(space, w_obj) + if type(w_obj) is GetSetProperty: + py_getsetdef = make_PyGetSetDef(space, w_obj) assert space.isinstance_w(w_userdata, space.w_type) w_obj = W_GetSetPropertyEx(py_getsetdef, w_userdata) # XXX assign to d_dname, d_type? @@ -375,6 +382,12 @@ # does not automatically assign to __dic__['__doc__'] # w_type.dict_w.setdefault('__doc__', w_type.w_doc) +def maybe_set_getset_doc(space, w_getset): + assert isinstance(w_getset, W_GetSetPropertyEx) + if not w_getset.doc and w_getset.getset.c_doc: + w_getset.doc = rffi.charp2str( + cts.cast('char*', w_getset.getset.c_doc)) + @slot_function([PyObject, PyObject, PyObject], PyObject) def tp_new_wrapper(space, self, w_args, w_kwds): self_pytype = rffi.cast(PyTypeObjectPtr, self) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit