This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author mikekap
Recipients brett.cannon, eric.snow, mikekap, ncoghlan
Date 2016-10-30.05:52:33
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1477806755.02.0.781206156162.issue26388@psf.upfronthosting.co.za>
In-reply-to
Content
Hey Nick,

Definitely agree that this refactor is big enough to try adding target modules. There's a somewhat hidden feature in the second patch that does this: `use_globals_from_sys_modules` takes `sys.globals` from the `sys.modules` entry for the module. It's a constructor arg though. It's only used by `_run_module_as_main`, but making it more official sounds good.

Given that goal, I'm a bit worried about how to accurately describe the behavior of `runnable.globals`. Particularly, what's a good API? Here are a couple of options I'm thinking of:

 - `x = load_module(...); x.module = sys.modules['foo']; x.run()`.
   Pros: allows setting the module that's to be used for maximal customizability.
   Cons: `x.globals` is poorly defined in that scenario. What should it reflect AFTER calling `x.run()`? What should it be before/after setting `x.module`? Should it overwrite __file__, __loader__, etc in the target module? Should it restore the values? When should it do this?
 - `x = load_module(...); x.overwrite_sys_modules = True; x.run()`
   This is a version of the above that perhaps makes it a bit easier to document what happens to which globals when.
 - `x = load_module(..., target_module=sys.modules['foo']); x.run()`
   Pros: less ambiguity about globals. They're always either local or the module's.
   Cons: all other "customizations" can be set after load_module is called. This is very asymmetric from an API perspective. There's also some ambiguity about what happens to the __file__, __line__, etc.
 - `x = load_module(...); x.run(target_module=...);`
   This is pretty much the sum of the cons of the above and more. Mostly here for completeness.

I'm leaning towards the second option for API symmetry. The largest hurdle is defining a behavior w.r.t. globals that is least surprising. Maybe something like - if set to True, the globals in the target will be overwritten (i.e. .update) with the globals in the runner when `run()` is called. If folks want to save/restore anything around globals in the target module, they are free to do so themselves before calling .run().

Separately, what needs this type of behavior, other than for backwards compatibility? Do you know of any specific use-case? It feels like almost everything should be covered by a combination of add_to_sys_modules (i.e. temporary modules in sys.modules) and inspecting runner.globals after execution.

What do you think?

Mike.
History
Date User Action Args
2016-10-30 05:52:35mikekapsetrecipients: + mikekap, brett.cannon, ncoghlan, eric.snow
2016-10-30 05:52:35mikekapsetmessageid: <1477806755.02.0.781206156162.issue26388@psf.upfronthosting.co.za>
2016-10-30 05:52:35mikekaplinkissue26388 messages
2016-10-30 05:52:33mikekapcreate