[Import-SIG] PEP 420 issue: extend_path

Nick Coghlan ncoghlan at gmail.com
Thu May 10 02:52:39 CEST 2012


On Thu, May 10, 2012 at 9:46 AM, Eric V. Smith <eric at trueblade.com> wrote:
> On 5/9/2012 12:14 PM, Barry Warsaw wrote:
>> On May 09, 2012, at 06:19 PM, Nick Coghlan wrote:
>>
>>> Eric's counter-proposal is to handle the 3 scenarios as:
>>>
>>> 1. (<loader>, <don't care>)
>>> 2. (None, [<path entries>])
>>> 3. (None, [])
>>
>
> ...
>
>> I'd like to relax the formal specification just a bit though, so that the
>> second element is a sequence, not necessarily a concrete list.
>
> I was going to say just use whatever list.extend() is documented to
> accept, but I notice that's "list" [1]. I would assume it can really be
> any iterable. But since len() is called on it (in case 3, above), I
> guess "sequence of strings" is the best description.

Why do we call len() specifically on the return value? Can't we just
extend the namespace path unconditionally, and then call len() on
*that* at the end to check if we found any namespace portions while
iterating over the path?

> But if case 3 were changed to (None, None), then I wouldn't need to call
> len(), and it could be any iterable returning strings in case 2. What
> are your thoughts on making case 3 (None, None)? I sort of like it.

I'd personally prefer to make the requirement an "iterable of path
entries", and adjust the outer algorithm so it doesn't call len()
directly on the return value.

PathFinder.find_module would become simply:

    @classmethod
    def find_module(cls, fullname, path=None):
        """Find the module on sys.path or 'path' based on sys.path_hooks and
        sys.path_importer_cache."""
        if path is None:
            path = sys.path

        # If this ends up being a namespace package, this is the
        #  list of paths that will become its __path__
        namespace_path = []

        for entry in path:
            finder = cls._path_importer_cache(entry)
            if finder is not None:
                if hasattr(finder, 'find_loader'):
                    loader, portions = finder.find_loader(fullname)
                else:
                    loader = finder.find_module(fullname)
                    portions = []
                # As soon as we find a loader, we're done
                if loader is not None:
                    return loader
                # Otherwise, record the package portions (if any) and
                # continue scanning the path
                namespace_path.extend(portions)
        # Made it through the entire path without finding a loader
        if namespace_path:
            # We found at least one namespace directory. Return a loader
            #  which can create the namespace package.
            return NamespaceLoader(namespace_path)
        # We got nuthin'
        return None

> For case 1, I'm currently returning "<don't care>" part as an empty
> string. Should I document it as that, or as really "<don't care>"? I
> don't have an opinion on this.

If the first field is not None, we shouldn't even look at the second
field. However, the return value should still follow whatever
conventions are established for the second field (i.e. it should be
either an empty iterable, or an iterable of path entries).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Import-SIG mailing list