<p dir="ltr"><br>
On 3 Feb 2015 00:18, "Brett Cannon" <<a href="mailto:brett@python.org">brett@python.org</a>> wrote:<br>
><br>
><br>
><br>
> On Sun Feb 01 2015 at 12:28:46 AM Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
>><br>
>> * I don't think we should couple the concept of resource anchors<br>
>> directly to package names (as discussed, it doesn't work for namespace<br>
>> packages, for example). I think we *should* be able to *look up*<br>
>> resource anchors by package name, although this may fail in some cases<br>
>> (such as namespace packages), and that the top level API should do<br>
>> that lookup implicitly (allowing package names to be passed wherever<br>
>> an anchor is expected). A module object should also be usable as its<br>
>> own anchor. I believe we should disallow the use of filesystem paths<br>
>> as resource anchors, as that breaks the intended abstraction (looking<br>
>> resources up relative to the related modules), and the API behaviour<br>
>> is clearer if strings are always assumed to be referring to<br>
>> package/module names.<br>
><br>
><br>
> Not quite following here. So are you saying we should define the location as ('foo.bar', 'baz/file.txt') or as ('foo.bar.baz', 'file.txt')? You say you "don't think we should couple the concept of resource anchors directly" but then say "we should disallow the use of filesystem paths".</p>
<p dir="ltr">I like Donald's resource anchor/resource key terminology suggestion here.</p>
<p dir="ltr">The "no filesystem paths" comment refers only to specifying the anchor point in the module namespace, not to the key within that anchor.</p>
<p dir="ltr">>> * I *don't* think it's a good idea to incorporate this idea directly<br>
>> onto the existing module Loader API. Better to create a new<br>
>> "ResourceLoader" abstraction, such that we can easily provide a<br>
>> default LocationResourceLoader. Reusing module Loader instances across<br>
>> modules would still be permitted, reusing ResourceLoader instances<br>
>> *would not*. This allows the resource anchor to be specified when<br>
>> creating the resource loader, rather than on every call.<br>
><br>
> You do realize that importlib.abc.ResourceLoader already exists, right? Otherwise I'm rather confused by the terminology. =)</p>
<p dir="ltr">*blinks* Apparently I missed that. OK, guess I need a different name :)</p>
<p dir="ltr">> And are you saying that we should have special rules for LocationResourceLoader instances such that you can not have to specify the anchoring package and thus force loader creators to provide unique instances per package? Or are you talking about some new thing that is tied to specs?</p>
<p dir="ltr">Yes, I'm proposing each module will need its own resource reader, they won't be shareable the way module loaders are. I don't think the memory savings from sharing are worth the extra complexity.</p>
<p dir="ltr">>> * As a consequence of the previous point, the ResourceLoader instance<br>
>> would be linked *from the module spec* (and perhaps from the module<br>
>> globals), rather than from the module loader instance. (This is how we<br>
>> would support using a module as its own anchor). Having a resource<br>
>> loader defined in the spec would be optional, making it clear that<br>
>> namespace modules (for example), don't provide a resource access API -<br>
>> if you want to store resources inside a namespace package, you need to<br>
>> create a submodule or self-contained subpackage to serve as the<br>
>> resource anchor.<br>
><br>
><br>
> So are you suggesting we add a new attribute to specs which would store a certain ABC subclass which implements an API for loading resources?</p>
<p dir="ltr">Correct (although it would be "reading resources" with your suggested terminology tweak). </p>
<p dir="ltr">>> * As a consequence of making a suitably configured resource loader<br>
>> available through the module spec as part of the module finding<br>
>> process it would become possible to access module relative resources<br>
>> *without actually loading the module itself*.<br>
><br>
> OK, you are suggesting adding a new object type and attribute to specs. Can we call them "resource readers" so we don't conflate the "loader" term?</p>
<p dir="ltr">Yep, that sounds like a good improvement to me.</p>
<p dir="ltr">> And doing it through specs also means that the overhead of requiring the file name not have any directory parts is not extra overhead.</p>
<p dir="ltr">I don't follow this part. I'm OK with resource keys having path separators in them.</p>
<p dir="ltr">>> * If the import system gets a module spec where "spec.has_location" is<br>
>> set and Loader.get_data is available, but the new<br>
>> "spec.resource_loader" attribute is set to None, then it will set it<br>
>> to "LocationResourceLoader(spec.origin)", which will rely solely on<br>
>> Loader.get_data() for content access<br>
><br>
><br>
> This is a little finicky. Are we going to simply say that we assume spec.origin is some path that works with os.path functions? Will Windows be okay if someone decided to standardize on / as a path separator instead of \ ? I get this buys us support from older loader implementations but I just want to make sure that it will work 80% of the time before we add more implicit magic to importlib.</p>
<p dir="ltr">We'd only be assuming that loader.get_data(os.path.join(spec.origin, resource_key) works.</p>
<p dir="ltr">It will fail in the same cases where using __file__ currently fails, but with a potential way to fix it (i.e. providing a custom resource reader when populating the module spec)</p>
<p dir="ltr">>> * We'd also provide an optimised FilesystemResourceLoader for use with<br>
>> actual installed packages where the resources already exist on disk<br>
>> and don't need to be copied to memory or a temporary directory to<br>
>> provide a suitable API.<br>
>><br>
>> * For abstract data access at the ResourceLoader API level, I like<br>
>> "get_anchor()" (returning a suitably descriptive string such that<br>
>> "os.path.join(anchor, <relative path>)" will work with get_data() on<br>
>> the corresponding module Loader),<br>
><br>
><br>
> I would rather call it get_location() since get_anchor() using 'anchor' seems to conflate what an anchor is representing.</p>
<p dir="ltr">Yeah, I confused myself while writing that. I like anchor for the user facing API, location for the plugin level.</p>
<p dir="ltr">Cheers,<br>
Nick.</p>