[pypy-commit] pypy default: Implement cpyext.is_cpyext_function()
rlamy
pypy.commits at gmail.com
Mon Nov 13 15:31:00 EST 2017
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch:
Changeset: r93005:a305590465d6
Date: 2017-11-13 20:30 +0000
http://bitbucket.org/pypy/pypy/changeset/a305590465d6/
Log: Implement cpyext.is_cpyext_function()
inspect.isbuiltin() now returns True for functions implemented in C,
like on CPython.
diff --git a/lib-python/2.7/inspect.py b/lib-python/2.7/inspect.py
--- a/lib-python/2.7/inspect.py
+++ b/lib-python/2.7/inspect.py
@@ -40,6 +40,10 @@
import linecache
from operator import attrgetter
from collections import namedtuple
+try:
+ from cpyext import is_cpyext_function as _is_cpyext_function
+except ImportError:
+ _is_cpyext_function = lambda obj: False
# These constants are from Include/code.h.
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8
@@ -230,7 +234,7 @@
__doc__ documentation string
__name__ original name of this function or method
__self__ instance to which a method is bound, or None"""
- return isinstance(object, types.BuiltinFunctionType)
+ return isinstance(object, types.BuiltinFunctionType) or _is_cpyext_function(object)
def isroutine(object):
"""Return true if the object is any kind of function or method."""
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -5,6 +5,7 @@
class Module(MixedModule):
interpleveldefs = {
'load_module': 'api.load_extension_module',
+ 'is_cpyext_function': 'interp_cpyext.is_cpyext_function',
}
appleveldefs = {
diff --git a/pypy/module/cpyext/interp_cpyext.py b/pypy/module/cpyext/interp_cpyext.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/interp_cpyext.py
@@ -0,0 +1,4 @@
+from .methodobject import W_PyCFunctionObject
+
+def is_cpyext_function(space, w_arg):
+ return space.newbool(isinstance(w_arg, W_PyCFunctionObject))
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -381,6 +381,11 @@
def test_export_function(self):
import sys
+ if '__pypy__' in sys.modules:
+ from cpyext import is_cpyext_function
+ else:
+ import inspect
+ is_cpyext_function = inspect.isbuiltin
init = """
if (Py_IsInitialized())
Py_InitModule("foo", methods);
@@ -399,6 +404,7 @@
assert 'foo' in sys.modules
assert 'return_pi' in dir(module)
assert module.return_pi is not None
+ assert is_cpyext_function(module.return_pi)
assert module.return_pi() == 3.14
assert module.return_pi.__module__ == 'foo'
@@ -777,14 +783,14 @@
# Set an exception and return NULL
raises(TypeError, module.set, None)
- # clear any exception and return a value
+ # clear any exception and return a value
assert module.clear(1) == 1
# Set an exception, but return non-NULL
expected = 'An exception was set, but function returned a value'
exc = raises(SystemError, module.set, 1)
assert exc.value[0] == expected
-
+
# Clear the exception and return a value, all is OK
assert module.clear(1) == 1
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -104,8 +104,10 @@
class A(object): pass
A.f = mod.f
A.g = lambda: 42
+ # Unbound method
assert A.f() == 42
raises(TypeError, A.g)
+ # Bound method
assert A().f() == 42
raises(TypeError, A().g)
More information about the pypy-commit
mailing list