Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: 
Changeset: r84383:51732368583f
Date: 2016-05-11 19:21 +0100
http://bitbucket.org/pypy/pypy/changeset/51732368583f/

Log:    turn make_wrapper() into a method of ApiFunction

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -203,46 +203,46 @@
 # id.  Invariant: this variable always contain 0 when the PyPy GIL is
 # released.  It should also contain 0 when regular RPython code
 # executes.  In non-cpyext-related code, it will thus always be 0.
-# 
+#
 # **make_generic_cpy_call():** RPython to C, with the GIL held.  Before
 # the call, must assert that the global variable is 0 and set the
 # current thread identifier into the global variable.  After the call,
 # assert that the global variable still contains the current thread id,
 # and reset it to 0.
-# 
+#
 # **make_wrapper():** C to RPython; by default assume that the GIL is
 # held, but accepts gil="acquire", "release", "around",
 # "pygilstate_ensure", "pygilstate_release".
-# 
+#
 # When a wrapper() is called:
-# 
+#
 # * "acquire": assert that the GIL is not currently held, i.e. the
 #   global variable does not contain the current thread id (otherwise,
 #   deadlock!).  Acquire the PyPy GIL.  After we acquired it, assert
 #   that the global variable is 0 (it must be 0 according to the
 #   invariant that it was 0 immediately before we acquired the GIL,
 #   because the GIL was released at that point).
-# 
+#
 # * gil=None: we hold the GIL already.  Assert that the current thread
 #   identifier is in the global variable, and replace it with 0.
-# 
+#
 # * "pygilstate_ensure": if the global variable contains the current
 #   thread id, replace it with 0 and set the extra arg to 0.  Otherwise,
 #   do the "acquire" and set the extra arg to 1.  Then we'll call
 #   pystate.py:PyGILState_Ensure() with this extra arg, which will do
 #   the rest of the logic.
-# 
+#
 # When a wrapper() returns, first assert that the global variable is
 # still 0, and then:
-# 
+#
 # * "release": release the PyPy GIL.  The global variable was 0 up to
 #   and including at the point where we released the GIL, but afterwards
 #   it is possible that the GIL is acquired by a different thread very
 #   quickly.
-# 
+#
 # * gil=None: we keep holding the GIL.  Set the current thread
 #   identifier into the global variable.
-# 
+#
 # * "pygilstate_release": if the argument is PyGILState_UNLOCKED,
 #   release the PyPy GIL; otherwise, set the current thread identifier
 #   into the global variable.  The rest of the logic of
@@ -254,7 +254,7 @@
 
 cpyext_namespace = NameManager('cpyext_')
 
-class ApiFunction:
+class ApiFunction(object):
     def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED,
                  c_name=None, gil=None, result_borrowed=False, 
result_is_ll=False):
         self.argtypes = argtypes
@@ -292,13 +292,61 @@
     def get_wrapper(self, space):
         wrapper = getattr(self, '_wrapper', None)
         if wrapper is None:
-            wrapper = make_wrapper(space, self.callable, self.gil)
+            wrapper = self._make_wrapper(space)
             self._wrapper = wrapper
             wrapper.relax_sig_check = True
             if self.c_name is not None:
                 wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
         return wrapper
 
+    # Make the wrapper for the cases (1) and (2)
+    def _make_wrapper(self, space):
+        "NOT_RPYTHON"
+        # This logic is obscure, because we try to avoid creating one
+        # big wrapper() function for every callable.  Instead we create
+        # only one per "signature".
+
+        callable = self.callable
+        gil = self.gil
+        argnames = self.argnames
+        argtypesw = zip(self.argtypes,
+                        [_name.startswith("w_") for _name in argnames])
+        error_value = getattr(self, "error_value", CANNOT_FAIL)
+        if (isinstance(self.restype, lltype.Ptr)
+                and error_value is not CANNOT_FAIL):
+            assert lltype.typeOf(error_value) == self.restype
+            assert not error_value    # only support error=NULL
+            error_value = 0    # because NULL is not hashable
+
+        if self.result_is_ll:
+            result_kind = "L"
+        elif self.result_borrowed:
+            result_kind = "B"     # note: 'result_borrowed' is ignored if we 
also
+        else:                     #  say 'result_is_ll=True' (in this case it's
+            result_kind = "."     #  up to you to handle refcounting anyway)
+
+        signature = (tuple(argtypesw),
+                    self.restype,
+                    result_kind,
+                    error_value,
+                    gil)
+
+        cache = space.fromcache(WrapperCache)
+        cache.stats[1] += 1
+        try:
+            wrapper_gen = cache.wrapper_gens[signature]
+        except KeyError:
+            #print signature
+            wrapper_gen = cache.wrapper_gens[signature] = WrapperGen(space,
+                                                                    signature)
+            cache.stats[0] += 1
+        #print 'Wrapper cache [wrappers/total]:', cache.stats
+        wrapper = wrapper_gen.make_wrapper(callable)
+        wrapper.relax_sig_check = True
+        if self.c_name is not None:
+            wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
+        return wrapper
+
 DEFAULT_HEADER = 'pypy_decl.h'
 def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
                 gil=None, result_borrowed=False, result_is_ll=False):
@@ -709,48 +757,6 @@
         return wrapper
 
 
-# Make the wrapper for the cases (1) and (2)
-def make_wrapper(space, callable, gil=None):
-    "NOT_RPYTHON"
-    # This logic is obscure, because we try to avoid creating one
-    # big wrapper() function for every callable.  Instead we create
-    # only one per "signature".
-
-    argnames = callable.api_func.argnames
-    argtypesw = zip(callable.api_func.argtypes,
-                    [_name.startswith("w_") for _name in argnames])
-    error_value = getattr(callable.api_func, "error_value", CANNOT_FAIL)
-    if (isinstance(callable.api_func.restype, lltype.Ptr)
-            and error_value is not CANNOT_FAIL):
-        assert lltype.typeOf(error_value) == callable.api_func.restype
-        assert not error_value    # only support error=NULL
-        error_value = 0    # because NULL is not hashable
-
-    if callable.api_func.result_is_ll:
-        result_kind = "L"
-    elif callable.api_func.result_borrowed:
-        result_kind = "B"     # note: 'result_borrowed' is ignored if we also
-    else:                     #  say 'result_is_ll=True' (in this case it's
-        result_kind = "."     #  up to you to handle refcounting anyway)
-
-    signature = (tuple(argtypesw),
-                 callable.api_func.restype,
-                 result_kind,
-                 error_value,
-                 gil)
-
-    cache = space.fromcache(WrapperCache)
-    cache.stats[1] += 1
-    try:
-        wrapper_gen = cache.wrapper_gens[signature]
-    except KeyError:
-        #print signature
-        wrapper_gen = cache.wrapper_gens[signature] = WrapperGen(space,
-                                                                 signature)
-        cache.stats[0] += 1
-    #print 'Wrapper cache [wrappers/total]:', cache.stats
-    return wrapper_gen.make_wrapper(callable)
-
 
 @dont_inline
 def deadlock_error(funcname):
@@ -1019,7 +1025,7 @@
     structindex = {}
     for header, header_functions in FUNCTIONS_BY_HEADER.iteritems():
         for name, func in header_functions.iteritems():
-            if not func: 
+            if not func:
                 # added only for the macro, not the decl
                 continue
             restype, args = c_function_signature(db, func)
@@ -1033,7 +1039,7 @@
     RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI;
     """ % dict(members=structmembers)
 
-    functions = generate_decls_and_callbacks(db, export_symbols, 
+    functions = generate_decls_and_callbacks(db, export_symbols,
                                             prefix='cpyexttest')
 
     global_objects = []
@@ -1415,7 +1421,7 @@
 
     generate_macros(export_symbols, prefix=prefix)
 
-    functions = generate_decls_and_callbacks(db, [], api_struct=False, 
+    functions = generate_decls_and_callbacks(db, [], api_struct=False,
                                             prefix=prefix)
     code = "#include <Python.h>\n"
     if use_micronumpy:
@@ -1471,7 +1477,7 @@
             if not func:
                 continue
             newname = mangle_name('PyPy', name) or name
-            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, 
+            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname,
                                         relax=True)
             deco(func.get_wrapper(space))
 
diff --git a/pypy/module/cpyext/test/test_translate.py 
b/pypy/module/cpyext/test/test_translate.py
--- a/pypy/module/cpyext/test/test_translate.py
+++ b/pypy/module/cpyext/test/test_translate.py
@@ -11,11 +11,11 @@
     FT = lltype.FuncType([], lltype.Signed)
     FTPTR = lltype.Ptr(FT)
 
-    def make_wrapper(space, func, gil=None):
+    def make_wrapper(self, space):
         def wrapper():
-            return func(space)
+            return self.callable(space)
         return wrapper
-    monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper)
+    monkeypatch.setattr(pypy.module.cpyext.api.ApiFunction, '_make_wrapper', 
make_wrapper)
 
     @specialize.memo()
     def get_tp_function(space, typedef):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to