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

@ -7,28 +7,28 @@ critical to the functioning of other programming languages that use the
Python AST and Python VM, languages such as Hy, Doge, and Mochi.
Problem Statement
-----------------
-----------------
The Python module loader system is hard-coded to prevent the discovery
of heterogenous source code packages. From Python 2.6 through the
current (as of this writing) Python 3.5, the import mechanism allowed
for the creation of file finders and importers that would transform
Python's import syntax into a *path,* assert whether or not that path
could be made to correspond to a *syntax object*, and then attempt to
*load* that syntax object as a Python module. Python *packages*,
however, are assumed to be uniformly made up of Python syntax objects,
be they **.py** source files, **.pyc/.pyo** bytecode, or **.so/.dll**
files with an exposed Python-to-C API. In Python 2 these suffixes are
hard-coded into the source in the **imp** builtin module; in Python 3
these suffixes are constants defined in a private section of
**importlib**; in either case, they are unavailable for modification.
This lack of access to the extensions list prevents the *discovery* of
heterogenous source code packages.
current (as of this writing) Python 3.5, the import mechanism allows for
the creation of file finders and importers that would transform Python's
import syntax into a *path,* assert whether or not that path could be
made to correspond to a *syntax object*, and then attempt to *load* that
syntax object as a Python module. Python *packages*, however, are
assumed to be uniformly made up of Python syntax objects, be they
**.py** source files, **.pyc/.pyo** bytecode, or **.so/.dll** files with
an exposed Python-to-C API. In Python 2 these suffixes are hard-coded
into the source in the **imp** builtin module; in Python 3 these
suffixes are constants defined in a private section of **importlib**; in
either case, they are unavailable for modification. This lack of access
to the extensions list prevents the *discovery* of heterogenous source
code packages.
The discovery mechanism is outlined in Python's pkgutil module; features
such as **pkgutil.iter_modules** do not work with heterogenous source
code, which in turn means that one cannot write, for one important
example, Django management commands in an alternative syntax.
The discovery mechanism is outlined in Python's **pkgutil** module;
features such as **pkgutil.iter_modules** do not work with heterogenous
source code, which in turn means that one cannot write, for one
important example, Django management commands in an alternative syntax.
**polyloader** is a python module that intercepts calls to the default
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'
__version__ = '0.1.0'
if sys.version[0:2] == (2, 7):
from ._python27 import install
if sys.version_info[0:2] >= (2, 6):
from ._python2 import install
if sys.version[0] >= 3:
if sys.version_info[0] >= 3:
from ._python3 import 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
# found before the native one.
We actually want to have multiple
# SourceFileFinders, each of which either recognizes the file to be
# Why the heck python 2.6 insists on calling finders "importers" is
# beyond me. At least in calls loaders "loaders".
class PolyFinder(object):
def __init__(self, path = None):
self.path = path
def find_on_path(self, fullname):
def _pl_find_on_path(self, fullname, path=None):
subname = fullname.split(".")[-1]
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)]
fls = ["%s/__init__.%s", "%s.%s"]
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
for fp in fls:
for (compiler, suffix) in PolyLoader._loader_handlers:
composed_path = fp % ("%s/%s" % (pth, dirpath), suffix)
if os.path.exists(composed_path):
return composed_path
for fp in fls:
for (compiler, suffix) in PolyLoader._loader_handlers:
composed_path = fp % ("%s/%s" % (pth, dirpath), suffix)
if os.path.exists(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):
path = self.find_on_path(fullname)
path = self._pl_find_on_path(fullname)
if path:
return PolyLoader(path)
return None
def _install(compiler, suffixes):
sys.meta_path.insert(0, MetaImporter())
iter_importer_modules.register(MetaImporter, meta_iterate_modules)