Heading toward a final draft of the Py-2 instances.

This commit is contained in:
Elf M. Sternberg 2016-06-17 17:22:51 -07:00
parent df657c6b46
commit e8dfad4721
3 changed files with 46 additions and 39 deletions

View File

@ -11,24 +11,24 @@ Problem Statement
The Python module loader system is hard-coded to prevent the discovery The Python module loader system is hard-coded to prevent the discovery
of heterogenous source code packages. From Python 2.6 through the of heterogenous source code packages. From Python 2.6 through the
current (as of this writing) Python 3.5, the import mechanism allowed current (as of this writing) Python 3.5, the import mechanism allows for
for the creation of file finders and importers that would transform the creation of file finders and importers that would transform Python's
Python's import syntax into a *path,* assert whether or not that path import syntax into a *path,* assert whether or not that path could be
could be made to correspond to a *syntax object*, and then attempt to made to correspond to a *syntax object*, and then attempt to *load* that
*load* that syntax object as a Python module. Python *packages*, syntax object as a Python module. Python *packages*, however, are
however, are assumed to be uniformly made up of Python syntax objects, assumed to be uniformly made up of Python syntax objects, be they
be they **.py** source files, **.pyc/.pyo** bytecode, or **.so/.dll** **.py** source files, **.pyc/.pyo** bytecode, or **.so/.dll** files with
files with an exposed Python-to-C API. In Python 2 these suffixes are an exposed Python-to-C API. In Python 2 these suffixes are hard-coded
hard-coded into the source in the **imp** builtin module; in Python 3 into the source in the **imp** builtin module; in Python 3 these
these suffixes are constants defined in a private section of suffixes are constants defined in a private section of **importlib**; in
**importlib**; in either case, they are unavailable for modification. either case, they are unavailable for modification. This lack of access
This lack of access to the extensions list prevents the *discovery* of to the extensions list prevents the *discovery* of heterogenous source
heterogenous source code packages. code packages.
The discovery mechanism is outlined in Python's pkgutil module; features The discovery mechanism is outlined in Python's **pkgutil** module;
such as **pkgutil.iter_modules** do not work with heterogenous source features such as **pkgutil.iter_modules** do not work with heterogenous
code, which in turn means that one cannot write, for one important source code, which in turn means that one cannot write, for one
example, Django management commands in an alternative syntax. important example, Django management commands in an alternative syntax.
**polyloader** is a python module that intercepts calls to the default **polyloader** is a python module that intercepts calls to the default
finder, loader, and package module iterator, and if the path resolves to finder, loader, and package module iterator, and if the path resolves to

View File

@ -5,10 +5,10 @@ __author__ = 'Kenneth M. "Elf" Sternberg'
__email__ = 'elf.sternberg@gmail.com' __email__ = 'elf.sternberg@gmail.com'
__version__ = '0.1.0' __version__ = '0.1.0'
if sys.version[0:2] == (2, 7): if sys.version_info[0:2] >= (2, 6):
from ._python27 import install from ._python2 import install
if sys.version[0] >= 3: if sys.version_info[0] >= 3:
from ._python3 import install from ._python3 import install
__all__ = ['install'] __all__ = ['install']

View File

@ -64,34 +64,41 @@ class PolyLoader(pkgutil.ImpLoader):
# the iter_modules; or we provide our own finder and ensure it gets # the iter_modules; or we provide our own finder and ensure it gets
# found before the native one. # found before the native one.
We actually want to have multiple # Why the heck python 2.6 insists on calling finders "importers" is
# SourceFileFinders, each of which either recognizes the file to be # beyond me. At least in calls loaders "loaders".
class PolyFinder(object): class PolyFinder(object):
def __init__(self, path = None): def __init__(self, path = None):
self.path = path self.path = path
def find_on_path(self, fullname): def _pl_find_on_path(self, fullname, path=None):
fls = ["%s/__init__.%s", "%s.%s"] subname = fullname.split(".")[-1]
dirpath = "/".join(fullname.split(".")) if subname != fullname and self.path is None:
return None
# As in the original, we ignore the 'path' argument
path = None
if self.path is not None:
path = [os.path.realpath(self.path)]
for pth in sys.path: fls = ["%s/__init__.%s", "%s.%s"]
pth = os.path.abspath(pth)
for fp in fls: for fp in fls:
for (compiler, suffix) in PolyLoader._loader_handlers: for (compiler, suffix) in PolyLoader._loader_handlers:
composed_path = fp % ("%s/%s" % (pth, dirpath), suffix) composed_path = fp % ("%s/%s" % (pth, dirpath), suffix)
if os.path.exists(composed_path): if os.path.exists(composed_path):
return composed_path return PolyLoader(composed_path)
try:
file, filename, etc = imp.find_module(subname, path)
except ImportError:
return None
return ImpLoader(fullname, file, filename, etc)
def find_module(self, fullname, path=None): def find_module(self, fullname, path=None):
path = self.find_on_path(fullname) path = self._pl_find_on_path(fullname)
if path: if path:
return PolyLoader(path) return PolyLoader(path)
return None
def _install(compiler, suffixes): def _install(compiler, suffixes):
sys.meta_path.insert(0, MetaImporter()) sys.meta_path.insert(0, MetaImporter())
iter_importer_modules.register(MetaImporter, meta_iterate_modules) iter_importer_modules.register(MetaImporter, meta_iterate_modules)