<div dir="ltr"><div><div><div>My thought about decorators is that they allow obvious scoping of changes for the reader. Anything that becomes module scope or is implied based on system state that is set in another module will make debugging and reading much harder. Both lazy_python and codetransformer use bytecode manipulation; however, it is a purely opt-in system where the transformed function is decorated. This keeps the transformations in view while you are reading the code that is affected by them. I would find debugging a project much more difficult if I needed to remember that the order my modules were imported matters a lot because they setup a bunch of state. I am not sure why people want the module to be the smallest unit that is transformed when really it is the code object that should be the smallest unit. This means class bodies and functions. If we treat the module as the most atomic unit then you wouldn't be able to use something like `asconstants`<br><br></div>This is a really great local optimzation when calling a function in a loop, especially builtins that you know will most likely never change and you don't want to change if they do. For example:<br><br>In [1]: from codetransformer.transformers.constants import asconstants<br><br>In [2]: @asconstants(a=1)<br>   ...: def f():<br>   ...:     return a<br>   ...: <br><br>In [3]: a = 5<br><br>In [4]: f()<br>Out[4]: 1<br><br>In [5]: @asconstants('pow')  # string means use the built in for this name<br>   ...: def g(ns):<br>   ...:     for n in ns:<br>   ...:         yield pow(n, 2)<br>   ...:         <br><br>In [6]: list(g([1, 2, 3]))<br>Out[6]: [1, 4, 9]<br><br>In [7]: dis(g)<br>  3           0 SETUP_LOOP              28 (to 31)<br>              3 LOAD_FAST                0 (ns)<br>              6 GET_ITER<br>        >>    7 FOR_ITER                20 (to 30)<br>             10 STORE_FAST               1 (n)<br>             13 LOAD_CONST               0 (<built-in function pow>)<br>             16 LOAD_FAST                1 (n)<br>             19 LOAD_CONST               1 (2)<br>             22 CALL_FUNCTION            2 (2 positional, 0 keyword pair)<br>             25 YIELD_VALUE<br>             26 POP_TOP<br>             27 JUMP_ABSOLUTE            7<br>        >>   30 POP_BLOCK<br>        >>   31 LOAD_CONST               2 (None)<br>             34 RETURN_VALUE<br><br><br></div>This is a simple optimization that people emulate all the time with things like `sum_ = sum` before the loop or `def g(ns, *, _sum=sum)`.  This cannot be used at module scope because often you only think it is safe or worth it to lock in the value for a small segment of code.<br></div><div>Hopefully this use case is being considered as I think this is a very simple, non-semantics preserving case that is not very and also practical.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 27, 2016 at 3:20 PM, Brett Cannon <span dir="ltr"><<a href="mailto:brett@python.org" target="_blank">brett@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><br><div class="gmail_quote"><span class=""><div dir="ltr">On Wed, 27 Jan 2016 at 08:49 Andrew Barnert via Python-ideas <<a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Jan 27, 2016, at 07:39, Victor Stinner <<a href="mailto:victor.stinner@gmail.com" target="_blank">victor.stinner@gmail.com</a>> wrote:<br>
><br>
> Hi,<br>
><br>
> Thank you for all feedback on my PEP 511. It looks like the current<br>
> blocker point is the unclear status of "language extensions": code<br>
> tranformers which deliberately changes the Python semantics. I would<br>
> like to discuss how we should register them. I think that the PEP 511<br>
> must discuss "language extensions" even if it doesn't have to propose<br>
> a solution to make their usage easier. It's an obvious usage of code<br>
> transformers. If possible, I would like to find a compromise to<br>
> support them, but make it explicit that they change the Python<br>
> semantics.<br>
<br>
Is this really necessary?<br>
<br>
If someone is testing a language change locally, and just wants to use your (original) API for his tests instead of the more complicated alternative of building an import hook, it works fine. If he can't deploy that way, that's fine.<br>
<br>
If someone builds a transformer that adds a feature in a way that makes it a pure superset of Python, he should be fine with running it on all files, so your API works fine. And if some files that didn't use any of the new features get .pyc files that imply they did, so what?<br>
<br>
If someone builds a transformer that only runs on files with a different extension, he already needs an import hook, so he might as well just call his transformer from the input hook, same as he does today.<br></blockquote><div><br></div></span><div>And the import hook is not that difficult. You can reuse everything from importlib without modification except for needing to override a single method in some loader to do your transformation (<a href="https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader.source_to_code" target="_blank">https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader.source_to_code</a>). Otherwise the only complication is instantiating the right classes and setting the path hook in `sys.path_hooks`.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
So... What case is served by this new, more complicated API that wasn't already served by your original, simple one (remembering that import hooks are already there as a fallback)?<br></blockquote><div><br></div></span><div>As Victor pointed out, the discussion could end in "nothing changed, but we at least discussed it". I think both you and I currently agree that's the answer to his question. :)</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>-Brett</div></font></span></div></div>
<br>_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br></blockquote></div><br></div>