Commit 0c0f4b2a authored by Kirill Smelkov's avatar Kirill Smelkov

golang: Adjust @func to wrap functions with standalone wrapper with recognizable name

Since 5146eb0b (Add support for defer & recover) we have func, which for

    @func
    def f():
        ...

will turn f to be run with additional frame where defer can register calls.

This works ok, but so far the worker of the wrapper was defined inside
func itself - each time func was used, and also the worker had "no
speaking" name _. The latter was making tracebacks a bit harder to read.

-> Move the wrapper to be standalone function with _goframe name. This
removes a bit of import-time overhead when @func is called, and makes
tracebacks a bit more readable.

But my original motivation here is to be able to detect double
func(func(·)) calls and make it idempotent - see next patch for that.

/reviewed-by @levin.zimmermann
/reviewed-on nexedi/pygolang!31
parent 9434cf08
......@@ -117,14 +117,9 @@ def _func(f):
fclass = type(f)
f = f.__func__
def _(f, *argv, **kw):
# run f under separate frame, where defer will register calls.
__goframe__ = _GoFrame()
with __goframe__:
return f(*argv, **kw)
# keep all f attributes, like __name__, __doc__, etc on _
_ = decorator.decorate(f, _)
# prepare function that runs f under separate frame, where defer will register calls
# keep all f attributes, like __name__, __doc__, etc on the wrapper
_ = decorator.decorate(f, _goframe)
# repack _ into e.g. @staticmethod if that was used on f.
if fclass is not None:
......@@ -132,7 +127,13 @@ def _func(f):
return _
# _GoFrame serves __goframe__ that is setup by @func.
# _goframe is used by @func to run f under separate frame.
def _goframe(f, *argv, **kw):
__goframe__ = _GoFrame()
with __goframe__:
return f(*argv, **kw)
# _GoFrame serves __goframe__ that is setup by _goframe.
class _GoFrame:
def __init__(self):
self.deferv = [] # defer registers funcs here
......
......@@ -1568,7 +1568,7 @@ RuntimeError: gamma
assertDoc("""\
Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311
File "PYGOLANG/golang/golang_test.py", line ..., in caller
......@@ -1590,7 +1590,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller()
...
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310
with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......@@ -1609,7 +1609,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller()
...
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310
with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......@@ -1625,7 +1625,7 @@ RuntimeError: aaa
e.__cause__ = e.__context__
assertDoc("""\
Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311
File "PYGOLANG/golang/golang_test.py", line ..., in caller
......@@ -1647,7 +1647,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller()
...
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310
with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......
Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311
File "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 42, in main
......@@ -31,7 +31,7 @@ Traceback (most recent call last):
... "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 45, in <module>
main()
...
File "PYGOLANG/golang/__init__.py", line ..., in _
File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310
with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......
...
RuntimeError Traceback (most recent call last)
PYGOLANG/golang/__init__.py in _(f, *argv, **kw)
PYGOLANG/golang/__init__.py in _goframe(f, *argv, **kw)
...
--> ... return f(*argv, **kw)
...
......@@ -50,7 +50,7 @@ PYGOLANG/golang/testprog/golang_test_defer_excchain.py in ...
...
PYGOLANG/golang/__init__.py in _(f, *argv, **kw)
PYGOLANG/golang/__init__.py in _goframe(f, *argv, **kw)
...
--> ... return f(*argv, **kw)
...
......
...
...________________ main ________________...
../__init__.py:...: in _
../__init__.py:...: in _goframe
return f(*argv, **kw)
golang_test_defer_excchain.py:42: in main
raise RuntimeError("err")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment