Revising for 2/3 split. This isn't working. Just checking in to move to a new machine.

This commit is contained in:
Elf M. Sternberg 2016-06-06 07:41:39 -07:00
parent 613db3c2f6
commit 1b614cb103
3 changed files with 169 additions and 27 deletions

View File

@ -1,5 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
__author__ = 'Kenneth M. "Elf" Sternberg' __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):
from ._python27 import install
if sys.version[0] >= 3:
from ._python3 import install
__all__ = ['install']

74
polyloader/_python27.py Normal file
View File

@ -0,0 +1,74 @@
import os
import os.path
import sys
import pkgutil
class PolyLoader(pkgutil.ImpLoader):
_loader_handlers = []
_installed = False
def is_package(self, fullname):
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
for (compiler, suffix) in self._loader_handlers:
composed_path = "%s/%s/__init__.%s" % (pth, dirpath, suffix)
if os.path.exists(composed_path):
return True
return False
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
matches = [(compiler, suffix) for (compiler, suffix) in self._loader_handlers
if path.endswith(suffix)]
if matches.length == 0:
raise ImportError("%s is not a recognized module?" % name)
if matches.length > 1:
raise ImportError("Multiple possible resolutions for %s: %s" % (
name, ', '.join([suffix for (compiler, suffix) in matches])))
compiler = matches[0]
module = compiler(name, path)
module.__file__ = self.filename
module.__name__ = self.fullname
if self.is_package(fullname):
module.__path__ = self.path_entry
module.__package__ = fullname
else:
module.__package__ = '.'.join(fullname.split('.')[:-1])
sys.modules[fullname] = module
return module
class PolyFinder(pkgutil.ImpImporter):
def find_on_path(self, fullname):
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
def find_module(self, fullname, path=None):
path = self.find_on_path(fullname)
if path:
return PolyLoader(path)
def _install(compiler, suffixes):
sys.meta_path.insert(0, MetaImporter())
iter_importer_modules.register(MetaImporter, meta_iterate_modules)

View File

@ -30,16 +30,23 @@ import sys
from importlib import machinery from importlib import machinery
from importlib.machinery import SOURCE_SUFFIXES as PY_SOURCE_SUFFIXES from importlib.machinery import SOURCE_SUFFIXES as PY_SOURCE_SUFFIXES
from pkgutil import iter_importer_modules from pkgutil import iter_importer_modules
import sys
try:
from importlib._bootstrap import _get_supported_file_loaders
except:
from importlib._bootstrap_external import _get_supported_file_loaders
__author__ = 'Elf M. Sternberg' __author__ = 'Elf M. Sternberg'
__version__ = '2016.05.29' __version__ = '2016.05.29'
__contact__ = 'elf.sternberg@gmail.com' __contact__ = 'elf.sternberg@gmail.com'
if sys.version_info[0:2] in [(3,3), (3,4)]:
from importlib._bootstrap import _get_supported_file_loaders
sourcefile_recognizer = 'importlib.SourceFileLoader'
if sys.version_info[0:2] in [(3,5)]:
from importlib._bootstrap_external import _get_supported_file_loaders
sourcefile_recognizer = 'importlib_external.SourceFileLoader'
def _call_with_frames_removed(f, *args, **kwds): def _call_with_frames_removed(f, *args, **kwds):
# Hack. This function name and signature is hard-coded into # Hack. This function name and signature is hard-coded into
# Python's import.c. The name and signature trigger importlib to # Python's import.c. The name and signature trigger importlib to
@ -52,8 +59,7 @@ class ExtendedSourceFileLoader(machinery.SourceFileLoader):
if it's a Python file, which will generate pyc files as needed, if it's a Python file, which will generate pyc files as needed,
or works its way into the Extended version. This method does or works its way into the Extended version. This method does
not yet address the generation of .pyc/.pyo files from source not yet address the generation of .pyc/.pyo files from source
files. files for languages other than Python.
""" """
_source_handlers = [] _source_handlers = []
@ -70,7 +76,7 @@ class ExtendedSourceFileLoader(machinery.SourceFileLoader):
return PY_SOURCE_SUFFIXES + cls.get_extended_suffixes() return PY_SOURCE_SUFFIXES + cls.get_extended_suffixes()
# TODO: Address the generation of .pyc/.pyo files from source files. # TODO: Address the generation of .pyc/.pyo files from source files.
# See importlib/_bootstrap.py for details is SourceFileLoader of # See importlib/_bootstrap.py for details in SourceFileLoader of
# how that's done. # how that's done.
def get_code(self, fullname): def get_code(self, fullname):
source_path = self.get_filename(fullname) source_path = self.get_filename(fullname)
@ -79,10 +85,11 @@ class ExtendedSourceFileLoader(machinery.SourceFileLoader):
for compiler, suffixes in self._source_handlers: for compiler, suffixes in self._source_handlers:
if source_path.endswith(suffixes): if source_path.endswith(suffixes):
return compiler(source_path, fullname) return _call_with_frames_removed(compiler, source_path, fullname)
else: else:
raise ImportError("Could not find compiler for %s (%s)" % (fullname, source_path)) raise ImportError("Could not find compiler for %s (%s)" % (fullname, source_path))
# Provide a working namespace for our new FileFinder. # Provide a working namespace for our new FileFinder.
class ExtendedFileFinder(machinery.FileFinder): class ExtendedFileFinder(machinery.FileFinder):
@ -154,25 +161,77 @@ def install(compiler, suffixes):
python executable modules automatically. python executable modules automatically.
""" """
filefinder = [(f, i) for i, f in enumerate(sys.path_hooks) if sys.version[0] >= 3:
if repr(f).find('path_hook_for_FileFinder') != -1] filefinder = [(f, i) for i, f in enumerate(sys.path_hooks)
if not filefinder: if repr(f).find('path_hook_for_FileFinder') != -1]
return if not filefinder:
filefinder, fpos = filefinder[0] return
filefinder, fpos = filefinder[0]
ExtendedSourceFileLoader._source_handlers = (ExtendedSourceFileLoader._source_handlers +
[(compiler, tuple(suffixes))])
supported_loaders = _get_supported_file_loaders()
print([repr(i) for i in supported_loaders])
sourceloader = [(l, i) for i, l in enumerate(supported_loaders)
if repr(l[0]).find(sourcefile_recognizer) != -1]
if not sourceloader:
return
sourceloader, spos = sourceloader[0]
supported_loaders[spos] = (ExtendedSourceFileLoader,
ExtendedSourceFileLoader.get_extended_suffixes_inclusive())
sys.path_hooks[fpos] = ExtendedFileFinder.path_hook(*supported_loaders)
iter_importer_modules.register(ExtendedFileFinder, ExtendedFileFinder.iter_modules)
if sys.path[0] != "":
sys.path.insert(0, "")
ExtendedSourceFileLoader._source_handlers = (ExtendedSourceFileLoader._source_handlers + if sys.version[0:2] == (2, 7):
[(compiler, tuple(suffixes))]) def loader(path):
class Loader(object):
def __init__(self, path):
self.path = path
def is_package(self, fullname):
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
composed_path = "%s/%s/__init__.%s" % (pth, dirpath, suffix)
if os.path.exists(composed_path):
return True
return False
supported_loaders = _get_supported_file_loaders() def load_module(self, name):
sourceloader = [(l, i) for i, l in enumerate(supported_loaders) if name in sys.modules:
if repr(l[0]).find('importlib.SourceFileLoader') != -1] return sys.modules[name]
if not sourceloader:
return
sourceloader, spos = sourceloader[0] module = compiler(fullname, path)
supported_loaders[spos] = (ExtendedSourceFileLoader, module.__file__ = path
ExtendedSourceFileLoader.get_extended_suffixes_inclusive()) sys.modules[name] = module
sys.path_hooks[fpos] = ExtendedFileFinder.path_hook(*supported_loaders) if '.' in name:
iter_importer_modules.register(ExtendedFileFinder, ExtendedFileFinder.iter_modules) parent_name, child_name = name.rsplit('.', 1)
if sys.path[0] != "": setattr(sys.modules[parent_name], child_name, module)
sys.path.insert(0, "") sys.modules[name] = module
return module
return Loader()
class MetaImporter(object):
def find_module(self, fullname, path=None):
if fullname == 'numpy' or fullname.startswith('numpy.'):
_mapper.PerpetrateNumpyFixes()
if fullname in ('_hashlib', 'ctypes'):
raise ImportError('%s is not available in ironclad yet' % fullname)
lastname = fullname.rsplit('.', 1)[-1]
for d in (path or sys.path):
pyd = os.path.join(d, lastname + '.pyd')
if os.path.exists(pyd):
return loader(pyd)
return None
sys.meta_path.insert(0, MetaImporter())
iter_importer_modules.register(MetaImporter, meta_iterate_modules)