Author: Ronan Lamy <[email protected]>
Branch:
Changeset: r78631:89862db1c9f1
Date: 2015-07-21 19:38 +0100
http://bitbucket.org/pypy/pypy/changeset/89862db1c9f1/
Log: merge branch 'numpy-docstrings'
diff --git a/pypy/module/micronumpy/__init__.py
b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -2,7 +2,9 @@
class MultiArrayModule(MixedModule):
- appleveldefs = {'arange': 'app_numpy.arange'}
+ appleveldefs = {
+ 'arange': 'app_numpy.arange',
+ 'add_docstring': 'app_numpy.add_docstring'}
interpleveldefs = {
'ndarray': 'ndarray.W_NDimArray',
'dtype': 'descriptor.W_Dtype',
@@ -29,6 +31,8 @@
'set_string_function': 'appbridge.set_string_function',
'typeinfo': 'descriptor.get_dtype_cache(space).w_typeinfo',
'nditer': 'nditer.W_NDIter',
+
+ 'set_docstring': 'support.descr_set_docstring',
}
for c in ['MAXDIMS', 'CLIP', 'WRAP', 'RAISE']:
interpleveldefs[c] = 'space.wrap(constants.%s)' % c
diff --git a/pypy/module/micronumpy/app_numpy.py
b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -3,6 +3,7 @@
import math
import _numpypy
+from _numpypy.multiarray import set_docstring
def arange(start, stop=None, step=1, dtype=None):
'''arange([start], stop[, step], dtype=None)
@@ -22,3 +23,13 @@
arr[j] = i
i += step
return arr
+
+
+def add_docstring(obj, docstring):
+ old_doc = getattr(obj, '__doc__', None)
+ if old_doc is not None:
+ raise RuntimeError("%s already has a docstring" % obj)
+ try:
+ set_docstring(obj, docstring)
+ except:
+ raise TypeError("Cannot set a docstring for %s" % obj)
diff --git a/pypy/module/micronumpy/support.py
b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -1,8 +1,12 @@
-from pypy.interpreter.error import OperationError, oefmt
from rpython.rlib import jit
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import unwrap_spec, appdef
+from pypy.interpreter.typedef import GetSetProperty
+from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.objspace.std.objspace import StdObjSpace
def issequence_w(space, w_obj):
from pypy.module.micronumpy.base import W_NDimArray
@@ -172,3 +176,27 @@
elif req_order == 'A':
return proto_order
+
+def descr_set_docstring(space, w_obj, w_docstring):
+ if not isinstance(space, StdObjSpace):
+ raise oefmt(space.w_NotImplementedError,
+ "This only works with the real object space")
+ if isinstance(w_obj, W_TypeObject):
+ w_obj.w_doc = w_docstring
+ return
+ elif isinstance(w_obj, GetSetProperty):
+ if space.is_none(w_docstring):
+ doc = None
+ else:
+ doc = space.str_w(w_docstring)
+ w_obj.doc = doc
+ return
+ app_set_docstring(space, w_obj, w_docstring)
+
+app_set_docstring = appdef("""app_set_docstring_(obj, docstring):
+ import types
+ if isinstance(obj, types.MethodType):
+ obj.im_func.__doc__ = docstring
+ else:
+ obj.__doc__ = docstring
+""")
diff --git a/pypy/module/micronumpy/test/test_support_app.py
b/pypy/module/micronumpy/test/test_support_app.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_support_app.py
@@ -0,0 +1,49 @@
+"""App-level tests for support.py"""
+import sys
+import py
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+from pypy.conftest import option
+
+class AppTestSupport(BaseNumpyAppTest):
+ def setup_class(cls):
+ if option.runappdirect and '__pypy__' not in sys.builtin_module_names:
+ py.test.skip("pypy only test")
+ BaseNumpyAppTest.setup_class.im_func(cls)
+
+ def test_add_docstring(self):
+ import numpy as np
+ foo = lambda: None
+ np.add_docstring(foo, "Does a thing")
+ assert foo.__doc__ == "Does a thing"
+
+ def test_type_docstring(self):
+ import numpy as np
+ import types
+ obj = types.ModuleType
+ doc = obj.__doc__
+ try:
+ np.set_docstring(obj, 'foo')
+ assert obj.__doc__ == 'foo'
+ finally:
+ np.set_docstring(obj, doc)
+
+ raises(RuntimeError, np.add_docstring, obj, 'foo')
+
+ def test_method_docstring(self):
+ import numpy as np
+ doc = int.bit_length.__doc__
+ try:
+ np.set_docstring(int.bit_length, 'foo')
+ assert int.bit_length.__doc__ == 'foo'
+ finally:
+ np.set_docstring(int.bit_length, doc)
+
+ def test_property_docstring(self):
+ import numpy as np
+ doc = np.flatiter.base.__doc__
+ try:
+ np.set_docstring(np.flatiter.base, 'foo')
+ assert np.flatiter.base.__doc__ == 'foo'
+ finally:
+ np.set_docstring(np.flatiter.base, doc)
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py
b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -1361,3 +1361,26 @@
assert np.add(np.zeros(5, dtype=np.int8), 257).dtype == np.int16
assert np.subtract(np.zeros(5, dtype=np.int8), 257).dtype == np.int16
assert np.divide(np.zeros(5, dtype=np.int8), 257).dtype == np.int16
+
+ def test_add_doc(self):
+ import sys
+ if '__pypy__' not in sys.builtin_module_names:
+ skip('')
+ try:
+ from numpy import set_docstring
+ except ImportError:
+ from _numpypy.multiarray import set_docstring
+ import numpy as np
+ assert np.add.__doc__ is None
+ add_doc = np.add.__doc__
+ ufunc_doc = np.ufunc.__doc__
+ try:
+ np.add.__doc__ = 'np.add'
+ assert np.add.__doc__ == 'np.add'
+ # Test for interferences between ufunc objects and their class
+ set_docstring(np.ufunc, 'np.ufunc')
+ assert np.ufunc.__doc__ == 'np.ufunc'
+ assert np.add.__doc__ == 'np.add'
+ finally:
+ set_docstring(np.ufunc, ufunc_doc)
+ np.add.__doc__ = add_doc
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -86,6 +86,7 @@
"identity", "int_only", "allow_bool", "allow_complex",
"complex_to_float", "nargs", "nout", "signature"
]
+ w_doc = None
def __init__(self, name, promote_to_largest, promote_to_float,
promote_bools,
identity, int_only, allow_bool, allow_complex,
complex_to_float):
@@ -105,6 +106,15 @@
def descr_repr(self, space):
return space.wrap("<ufunc '%s'>" % self.name)
+ def get_doc(self, space):
+ # Note: allows any object to be set as docstring, because why not?
+ if self.w_doc is None:
+ return space.w_None
+ return self.w_doc
+
+ def set_doc(self, space, w_doc):
+ self.w_doc = w_doc
+
def descr_get_identity(self, space):
if self.identity is None:
return space.w_None
@@ -1144,6 +1154,7 @@
__call__ = interp2app(W_Ufunc.descr_call),
__repr__ = interp2app(W_Ufunc.descr_repr),
__name__ = GetSetProperty(W_Ufunc.descr_get_name),
+ __doc__ = GetSetProperty(W_Ufunc.get_doc, W_Ufunc.set_doc),
identity = GetSetProperty(W_Ufunc.descr_get_identity),
accumulate = interp2app(W_Ufunc.descr_accumulate),
@@ -1157,8 +1168,6 @@
)
-
-
def ufunc_dtype_caller(space, ufunc_name, op_name, nin, bool_result):
def get_op(dtype):
try:
@@ -1481,7 +1490,7 @@
if w_ret.external_loop:
_parse_signature(space, w_ret, w_ret.signature)
if doc:
- w_ret.w_doc = space.wrap(doc)
+ w_ret.set_doc(space, space.wrap(doc))
return w_ret
# Instantiated in cpyext/ndarrayobject. It is here since ufunc calls
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit