Author: Ronan Lamy <ronan.l...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit