On 1 Nov 2013 01:37, "PJ Eby" <pje@telecommunity.com> wrote:
.  ;-)
>
> I also suspect, that if properly spelled out, those use cases are
> going to boil down to:
>
> 1. Throwing errors if you have an existing module object you can't
> load into, and
> 2. Passing in a previous spec object, if available
>
> In other words, loaders should not really have any responsibility for
> or concept of "reloading" -- they always load into a module object
> (that they may or may not have created), and they may get given a spec
> from a previous load.  They should deal only in "module reuse" and
> "spec reuse".  While a typical reload() might involve both reuses,
> there are cases where one sort of reuse could occur independently, and
> not all loaders care about both (or even either) condition.
>
> At any rate, it means a loader author doesn't have to figure out how
> to handle "reloading", all they have to figure out is whether they can
> load into a particular module object, and whether they can do
> something useful with a spec that was previously used to load a module
> with the same name -- a spec that may or may not refer to a similar
> previous loader.  These are rather more well-defined endeavors than
> trying to determine in the abstract whether one "supports reload".
> ;-)

It may not have been clear from the email exchange, but that's basically where we ended up :)

The change Eric is currently going to make to the PEP is to add an optional "previous" parameter to the various find_spec APIs.

At the time when find_spec runs, sys.modules hasn't been touched yet, so the old module state is still available when reloading. Passing the spec in lets the loader decide whether or not it can actually load that module given the information about the previous load operation.

However, perhaps it makes more sense to pass the entire existing module, rather than just the spec? I'd like to minimise the need for new-style loader authors to retrieve things directly from the sys module, and you're right that "can I reload into this particular module?" is a slightly different question from "can I reload a module previously loaded using this particular spec?".

A spec-based API could still be used to answer the first question by looking up sys.modules, but so could the name based API. Passing in the module reference, on the other hand, should let loaders answer both questions without needing to touch the sys module.

I also now think this pass-the-module approach when finding the spec approach could also clean up some of the messiness that is __main__ initialisation, where we repeatedly load things into the same module object.

Let's say we be completely explicit and call the new parameter something like "load_target". If we do that then I would make the *same* change to runpy.run_path and runpy.run_module: let you pass in an existing module object under that name to say "hey, run in this namespace, rather than a fresh one". (Those APIs currently only support pre-populating a *fresh* namespace, rather than allowing you to directly specify an existing one)

Most loaders won't care, but those that do will have all the info they need to throw an exception saying "I could provide a spec for this, but it's not compatible with that load target".

Cheers,
Nick.