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): ...@@ -117,14 +117,9 @@ def _func(f):
fclass = type(f) fclass = type(f)
f = f.__func__ f = f.__func__
def _(f, *argv, **kw): # prepare function that runs f under separate frame, where defer will register calls
# run f under separate frame, where defer will register calls. # keep all f attributes, like __name__, __doc__, etc on the wrapper
__goframe__ = _GoFrame() _ = decorator.decorate(f, _goframe)
with __goframe__:
return f(*argv, **kw)
# keep all f attributes, like __name__, __doc__, etc on _
_ = decorator.decorate(f, _)
# repack _ into e.g. @staticmethod if that was used on f. # repack _ into e.g. @staticmethod if that was used on f.
if fclass is not None: if fclass is not None:
...@@ -132,7 +127,13 @@ def _func(f): ...@@ -132,7 +127,13 @@ def _func(f):
return _ 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: class _GoFrame:
def __init__(self): def __init__(self):
self.deferv = [] # defer registers funcs here self.deferv = [] # defer registers funcs here
......
...@@ -1568,7 +1568,7 @@ RuntimeError: gamma ...@@ -1568,7 +1568,7 @@ RuntimeError: gamma
assertDoc("""\ assertDoc("""\
Traceback (most recent call last): Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311 ^^^^^^^^^^^^^^ +PY311
File "PYGOLANG/golang/golang_test.py", line ..., in caller File "PYGOLANG/golang/golang_test.py", line ..., in caller
...@@ -1590,7 +1590,7 @@ Traceback (most recent call last): ...@@ -1590,7 +1590,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller() caller()
... ...
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310 return f(*argv, **kw) -PY310
with __goframe__: +PY310 with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__ File "PYGOLANG/golang/__init__.py", line ..., in __exit__
...@@ -1609,7 +1609,7 @@ Traceback (most recent call last): ...@@ -1609,7 +1609,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller() caller()
... ...
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310 return f(*argv, **kw) -PY310
with __goframe__: +PY310 with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__ File "PYGOLANG/golang/__init__.py", line ..., in __exit__
...@@ -1625,7 +1625,7 @@ RuntimeError: aaa ...@@ -1625,7 +1625,7 @@ RuntimeError: aaa
e.__cause__ = e.__context__ e.__cause__ = e.__context__
assertDoc("""\ assertDoc("""\
Traceback (most recent call last): Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311 ^^^^^^^^^^^^^^ +PY311
File "PYGOLANG/golang/golang_test.py", line ..., in caller File "PYGOLANG/golang/golang_test.py", line ..., in caller
...@@ -1647,7 +1647,7 @@ Traceback (most recent call last): ...@@ -1647,7 +1647,7 @@ Traceback (most recent call last):
File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback File "PYGOLANG/golang/golang_test.py", line ..., in test_defer_excchain_traceback
caller() caller()
... ...
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310 return f(*argv, **kw) -PY310
with __goframe__: +PY310 with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__ File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......
Traceback (most recent call last): Traceback (most recent call last):
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) return f(*argv, **kw)
^^^^^^^^^^^^^^ +PY311 ^^^^^^^^^^^^^^ +PY311
File "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 42, in main File "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 42, in main
...@@ -31,7 +31,7 @@ Traceback (most recent call last): ...@@ -31,7 +31,7 @@ Traceback (most recent call last):
... "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 45, in <module> ... "PY39(PYGOLANG/golang/testprog/)golang_test_defer_excchain.py", line 45, in <module>
main() main()
... ...
File "PYGOLANG/golang/__init__.py", line ..., in _ File "PYGOLANG/golang/__init__.py", line ..., in _goframe
return f(*argv, **kw) -PY310 return f(*argv, **kw) -PY310
with __goframe__: +PY310 with __goframe__: +PY310
File "PYGOLANG/golang/__init__.py", line ..., in __exit__ File "PYGOLANG/golang/__init__.py", line ..., in __exit__
......
... ...
RuntimeError Traceback (most recent call last) 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) --> ... return f(*argv, **kw)
... ...
...@@ -50,7 +50,7 @@ PYGOLANG/golang/testprog/golang_test_defer_excchain.py in ... ...@@ -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) --> ... return f(*argv, **kw)
... ...
......
... ...
...________________ main ________________... ...________________ main ________________...
../__init__.py:...: in _ ../__init__.py:...: in _goframe
return f(*argv, **kw) return f(*argv, **kw)
golang_test_defer_excchain.py:42: in main golang_test_defer_excchain.py:42: in main
raise RuntimeError("err") 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