golang: Fix `@func(cls) def name` not to override `name` in calling context
With @func being a decorator, the following @func(cls) def name(): ... is always processed by python as name = func(cls)(def name(): ...) Before this patch it was leading to name being overridden with None: def f(): print 'hello' class C: pass @func(C) def f(c): print 'C.f', c f() Traceback (most recent call last): File "<console>", line 1, in <module> TypeError: 'NoneType' object is not callable We can fix it by returning from `func(cls)(def name(): ...)` the original `name` object from the calling context. Unfortunately if `name` was not previously set I did not find a way(*) to avoid polluting the calling namespace where it is set to what @func(cls) returns (None) by the hardcoded way how python processes decorators: In [2]: c = """ ...: @fff ...: def ccc(): ...: return 1 ...: """ In [3]: cc = compile(c, "file", "exec") In [4]: dis(cc) 2 0 LOAD_NAME 0 (fff) 3 LOAD_CONST 0 (<code object ccc at 0x7fafe58d0130, file "file", line 2>) 6 MAKE_FUNCTION 0 9 CALL_FUNCTION 1 12 STORE_NAME 1 (ccc) <-- NOTE means: ccc = what fff() call returns 15 LOAD_CONST 1 (None) 18 RETURN_VALUE At least with no overriding taking place the situation is better now. NOTE: it is only @func(cls) which potentially pollutes calling namespace. Just @func (without class) is always clean because by definition it works as a regular decorator. (*) there is a very low-level and potentially fragile way to disable STORE_NAME after CALL_FUNCTION by dynamically patching caller's bytecode at runtime and replacing STORE_NAME with POP_TOP + NOP...
Showing
Please register or sign in to comment