[Python-Dev] PEP 420 - dynamic path computation is missing rationale

Nick Coghlan ncoghlan at gmail.com
Tue May 22 17:39:32 CEST 2012


On Wed, May 23, 2012 at 12:51 AM, Eric V. Smith <eric at trueblade.com> wrote:
> That seems like a pretty convincing example to me.
>
> Personally I'm +1 on putting dynamic computation into the PEP, at least
> for top-level namespace packages, and probably for all namespace packages.

Same here, but Guido's right that the rationale (and example) should
be clearer in the PEP itself if the feature is to be retained.

> P.S.: Here's the current code in the pep-420 branch. This code still has
> the restriction that sys.path (or parent_path in general) can't be
> replaced. I'll fix that if we decide to keep the feature.

I wonder if it would be worth exposing an importlib.LazyRef API to
make it generally easy to avoid this kind of early binding problem?

   class LazyRef:
      # similar API to weakref.weakref
      def __init__(self, modname, attr=None):
          self.modname = modname
          self.attr = attr
      def __call__(self):
          mod = sys.modules[self.modname]
          attr = self.attr
          if attr is None:
              return mod
          return getattr(mod, attr)

Then _NamespacePath could just be defined as taking a callable that
returns the parent path:


 class _NamespacePath:
    def __init__(self, name, path, parent_path, path_finder):
        self._name = name
        self._path = path
        self._parent_path = parent_path
        self._last_parent_path = tuple(parent_path)
        self._path_finder = path_finder

    def _recalculate(self):
        # If _parent_path has changed, recalculate _path
        parent_path = tuple(self._parent_path())     # Retrieve and make a copy
        if parent_path != self._last_parent_path:
            loader, new_path = self._path_finder(self._name, parent_path)
            # Note that no changes are made if a loader is returned, but we
            #  do remember the new parent path
            if loader is None:
                self._path = new_path
            self._last_parent_path = parent_path   # Save the copy
        return self._path

Even if the LazyRef idea isn't used, I still like the idea of passing
a callable in to _NamespacePath for the parent path rather than
hardcoding the "module name + attribute name" approach.

Cheers,
Nick.

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


More information about the Python-Dev mailing list