[Python-ideas] PEP 511: Add a check function to decide if a "language extension" code transformer should be used or not

Sven R. Kunze srkunze at mail.de
Wed Jan 27 14:06:26 EST 2016


Hi,

On 27.01.2016 16:39, Victor Stinner wrote:
> "One concern that I have though is that transformers are registered
> globally. I think that the decorators in codetransformer do a good job
> of signalling to reader the scope of some new code generation."

I share this concern but haven't a good solution right now. Admittedly, 
I already have a use-case where I would like to apply a transformation 
which is NOT an optimization but a global extension.

So, the discussion about allowing global extension really made me think 
about whether that is really a good idea. *BUT* it would allow me to 
experiment and find out if the risk is worth it.

(use-case: adding some hooks before entering and leaving all try blocks)

> Currently, the PEP 511 doesn't provide a way to register a code
> transformer but only use it under some conditions. For example, if
> fatoptimizer is registered, all .pyc files will be called
> file.cpython-36.fat-0.pyc even if fatoptimizer was disabled.
>
> I propose to change the design of sys.set_code_transformers() to use
> it more like a registry similar to the codecs registry
> (codecs.register), but different (details below). A difference is that
> the codecs registry uses a mapping (codec name => codec functions),
> whereas sys.set_code_transformers() uses an ordered sequence (list) of
> code transformers. A sequence is used because multiple code
> transformers can be applied sequentially on a single .py file.

How does it change the interface for the users? (I mean besides the 
renaming).



I still like your idea of having the following three options:

1) global optimizers
2) local extensions --> via codec or import hook
3) global extension --> use with care


So, I assume we talk about specifying 2).

> Petr Viktorin wrote that language extensions "target specific modules,
> with which they're closely coupled: The modules won't run without the
> transformer. And with other modules, the transformer either does
> nothing (as with MacroPy, hopefully), or would fail altogether (as
> with Hy). So, they would benefit from specific packages opting in. The
> effects of enabling them globally range from inefficiency (MacroPy) to
> failures or needing workarounds (Hy)."
>
>
> Problem (A): solutions proposed below don't make code tranformers
> mandatory. If a code *requires* a code transformer and the code
> transformer is not registered, Python doesn't complain. Do you think
> that it is a real issue in practice? For MacroPy, it's not a problem
> in practice since functions must be decorated using a decorator from
> the macropy package. If importing macropy fails, the module cannot be
> imported.

Sounds good.

> Problem (B): proposed solutions below adds markers to ask to enable a
> specific code transformer, but a code transformer can decide to always
> modify the Python semantics without using such marker. According to
> Nick Coghlan, code transformers changing the Python semantics *must*
> require a marker in the code using them. IMHO it's the responsability
> of the author of the code transformer to use markers, not the
> responsability of Python.

I agree with Nick. Be explicit.

> Code transformers should maybe return a flag telling if they changed
> the code or not. I prefer a flag rather than comparing the output to
> the input, since the comparison can be expensive, especially for a
> deep AST tree. Example:
>
> class Optimizer:
>      def ast_optimizer(self, tree, context):
>          # ...
>          return modified, tree
>
> *modified* must be True if tree was modified.

Not sure if that is needed. If we don't have an immediate use-case, 
simpler is better.

> There are several options to decide if a code transformer must be used
> on a specific source file.

The user should decide, otherwise there is too much magic involved: a 
marker (source file) or an option (cmdline).

I am indifferent whether the marker should be a codec-decl or an import 
hook. But it should be file-local (at least I would prefer that).


All of the options below seem to involve too much magic for my taste (or 
I didn't understand them correctly).

> (1) Add a check_code() and check_ast() functions to code transformers.
> The code transformer is responsible to decide if it wants to transform
> the code or not. Python doesn't use the code transformer if the check
> method returns False.
>
> Examples:
>
> * MacroPy can search for the "import macropy" statement (of "from
> macropy import ...") in the AST tree
> * fatoptimizer can search for "__fatoptimizer__ = {'enabled': False}"
> in the code: if this variable is found, the optimizer is completly
> skipped
>
>
> (2) Petr proposed to extend importlib to pass a code transformer when
> importing a module.
>
>      importlib.util.import_with_transformer(
>          'mypackage.specialmodule', MyTransformer())
>
> IMHO this option is too specific: it's restricted to importlib
> (py_compile, compileall and interactive interpreter don't have the
> feature). I also dislike the API.
>
>
> (3) Petr also proposed "a special flag in packages":
>
>      __transformers_for_submodules__ = [MyTransformer()]
>
> I don't like having to get access to MyTransformer. The PEP 511
> mentions an use case where the transformed code is run *without*
> registering the transformer. But this issue can easily be fixed by
> using the string to identify the transformer in the registery (ex:
> "fat") rather than its class.
>
> I'm not sure that putting a flag on the package (package/__init__.py?)
> is a good idea. I would prefer to enable language extensions on
> individual files to restrict their scope.
>
>
> (4) Sjoerd Job Postmus proposed something similar but using a comment
> and not for packages, but any source file:
>
>      #:Transformers modname.TransformerClassName,
> modname.OtherTransformerClassName
>
> The problem is that comments are not stored in the AST tree. I would
> prefer to use AST to decide if an AST transformer should be used or
> not.
>
> Note: I'm not really motived to extend the AST to start to include
> comments, or even code formatting (spaces, newlines, etc.).
> https://pypi.python.org/pypi/redbaron/ can be used if you want to
> transform a .py file without touching the format. But I don't think
> that AST must go to this direction. I prefer to keep AST simple.
>
>
> (5) Nick proposed (indirectly) to use a different filename (don't use
> ".py") for language extensions.
>
> This option works with my option (2): the context contains the
> filename which can be used to decide to enable or not the code
> transformer.
>
> I understand that the code transformer must also install an importlib
> hook to search for other filenames than only .py files. Am I right?
>
>
> (6) Nick proposed (indirectly) to use an encoding cookie "which are
> visible as a comment in the module header".
>
> Again, I dislike this option because comments are not stored in AST.

Best,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160127/3b651862/attachment-0001.html>


More information about the Python-ideas mailing list