Commit 8133605f authored by Stefan Behnel's avatar Stefan Behnel

allow configuring the source language level in pyximport use default to the...

allow configuring the source language level in pyximport use default to the platform version for .py files
parent ee1719e5
...@@ -84,7 +84,7 @@ def _info(message, *args): ...@@ -84,7 +84,7 @@ def _info(message, *args):
def _load_pyrex(name, filename): def _load_pyrex(name, filename):
"Load a pyrex file given a name and filename." "Load a pyrex file given a name and filename."
def get_distutils_extension(modname, pyxfilename): def get_distutils_extension(modname, pyxfilename, language_level=None):
# try: # try:
# import hashlib # import hashlib
# except ImportError: # except ImportError:
...@@ -95,6 +95,8 @@ def get_distutils_extension(modname, pyxfilename): ...@@ -95,6 +95,8 @@ def get_distutils_extension(modname, pyxfilename):
if not extension_mod: if not extension_mod:
from distutils.extension import Extension from distutils.extension import Extension
extension_mod = Extension(name = modname, sources=[pyxfilename]) extension_mod = Extension(name = modname, sources=[pyxfilename])
if language_level is not None:
extension_mod.cython_directives = {'language_level': language_level}
return extension_mod,setup_args return extension_mod,setup_args
def handle_special_build(modname, pyxfilename): def handle_special_build(modname, pyxfilename):
...@@ -160,12 +162,12 @@ def handle_dependencies(pyxfilename): ...@@ -160,12 +162,12 @@ def handle_dependencies(pyxfilename):
if testing: if testing:
_test_files.append(file) _test_files.append(file)
def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False): def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False, language_level=None):
assert os.path.exists(pyxfilename), ( assert os.path.exists(pyxfilename), (
"Path does not exist: %s" % pyxfilename) "Path does not exist: %s" % pyxfilename)
handle_dependencies(pyxfilename) handle_dependencies(pyxfilename)
extension_mod,setup_args = get_distutils_extension(name, pyxfilename) extension_mod,setup_args = get_distutils_extension(name, pyxfilename, language_level)
build_in_temp=pyxargs.build_in_temp build_in_temp=pyxargs.build_in_temp
sargs=pyxargs.setup_args.copy() sargs=pyxargs.setup_args.copy()
sargs.update(setup_args) sargs.update(setup_args)
...@@ -191,13 +193,15 @@ def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False): ...@@ -191,13 +193,15 @@ def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False):
return so_path return so_path
def load_module(name, pyxfilename, pyxbuild_dir=None, is_package=False, build_inplace=False): def load_module(name, pyxfilename, pyxbuild_dir=None, is_package=False,
build_inplace=False, language_level=None):
try: try:
if is_package: if is_package:
module_name = name + '.__init__' module_name = name + '.__init__'
else: else:
module_name = name module_name = name
so_path = build_module(module_name, pyxfilename, pyxbuild_dir, inplace=build_inplace) so_path = build_module(module_name, pyxfilename, pyxbuild_dir,
inplace=build_inplace, language_level=language_level)
mod = imp.load_dynamic(name, so_path) mod = imp.load_dynamic(name, so_path)
assert mod.__file__ == so_path, (mod.__file__, so_path) assert mod.__file__ == so_path, (mod.__file__, so_path)
except Exception: except Exception:
...@@ -218,10 +222,12 @@ def load_module(name, pyxfilename, pyxbuild_dir=None, is_package=False, build_in ...@@ -218,10 +222,12 @@ def load_module(name, pyxfilename, pyxbuild_dir=None, is_package=False, build_in
class PyxImporter(object): class PyxImporter(object):
"""A meta-path importer for .pyx files. """A meta-path importer for .pyx files.
""" """
def __init__(self, extension=PYX_EXT, pyxbuild_dir=None, inplace=False): def __init__(self, extension=PYX_EXT, pyxbuild_dir=None, inplace=False,
language_level=None):
self.extension = extension self.extension = extension
self.pyxbuild_dir = pyxbuild_dir self.pyxbuild_dir = pyxbuild_dir
self.inplace = inplace self.inplace = inplace
self.language_level = language_level
def find_module(self, fullname, package_path=None): def find_module(self, fullname, package_path=None):
if fullname in sys.modules and not pyxargs.reload_support: if fullname in sys.modules and not pyxargs.reload_support:
...@@ -235,11 +241,13 @@ class PyxImporter(object): ...@@ -235,11 +241,13 @@ class PyxImporter(object):
return PyxLoader(fullname, pathname, return PyxLoader(fullname, pathname,
init_path=pkg_file, init_path=pkg_file,
pyxbuild_dir=self.pyxbuild_dir, pyxbuild_dir=self.pyxbuild_dir,
inplace=self.inplace) inplace=self.inplace,
language_level=self.language_level)
if pathname and pathname.endswith(self.extension): if pathname and pathname.endswith(self.extension):
return PyxLoader(fullname, pathname, return PyxLoader(fullname, pathname,
pyxbuild_dir=self.pyxbuild_dir, pyxbuild_dir=self.pyxbuild_dir,
inplace=self.inplace) inplace=self.inplace,
language_level=self.language_level)
if ty != imp.C_EXTENSION: # only when an extension, check if we have a .pyx next! if ty != imp.C_EXTENSION: # only when an extension, check if we have a .pyx next!
return None return None
...@@ -248,7 +256,8 @@ class PyxImporter(object): ...@@ -248,7 +256,8 @@ class PyxImporter(object):
if os.path.isfile(pyxpath): if os.path.isfile(pyxpath):
return PyxLoader(fullname, pyxpath, return PyxLoader(fullname, pyxpath,
pyxbuild_dir=self.pyxbuild_dir, pyxbuild_dir=self.pyxbuild_dir,
inplace=self.inplace) inplace=self.inplace,
language_level=self.language_level)
# .so/.pyd's on PATH should not be remote from .pyx's # .so/.pyd's on PATH should not be remote from .pyx's
# think no need to implement PyxArgs.importer_search_remote here? # think no need to implement PyxArgs.importer_search_remote here?
...@@ -283,7 +292,8 @@ class PyxImporter(object): ...@@ -283,7 +292,8 @@ class PyxImporter(object):
if is_file(path+sep+pyx_module_name): if is_file(path+sep+pyx_module_name):
return PyxLoader(fullname, join_path(path, pyx_module_name), return PyxLoader(fullname, join_path(path, pyx_module_name),
pyxbuild_dir=self.pyxbuild_dir, pyxbuild_dir=self.pyxbuild_dir,
inplace=self.inplace) inplace=self.inplace,
language_level=self.language_level)
# not found, normal package, not a .pyx file, none of our business # not found, normal package, not a .pyx file, none of our business
_debug("%s not found" % fullname) _debug("%s not found" % fullname)
...@@ -292,9 +302,12 @@ class PyxImporter(object): ...@@ -292,9 +302,12 @@ class PyxImporter(object):
class PyImporter(PyxImporter): class PyImporter(PyxImporter):
"""A meta-path importer for normal .py files. """A meta-path importer for normal .py files.
""" """
def __init__(self, pyxbuild_dir=None, inplace=False): def __init__(self, pyxbuild_dir=None, inplace=False, language_level=None):
if language_level is None:
language_level = sys.version_info[0]
self.super = super(PyImporter, self) self.super = super(PyImporter, self)
self.super.__init__(extension='.py', pyxbuild_dir=pyxbuild_dir, inplace=inplace) self.super.__init__(extension='.py', pyxbuild_dir=pyxbuild_dir, inplace=inplace,
language_level=language_level)
self.uncompilable_modules = {} self.uncompilable_modules = {}
self.blocked_modules = ['Cython', 'distutils.extension', self.blocked_modules = ['Cython', 'distutils.extension',
'distutils.sysconfig'] 'distutils.sysconfig']
...@@ -350,12 +363,15 @@ class PyImporter(PyxImporter): ...@@ -350,12 +363,15 @@ class PyImporter(PyxImporter):
return importer return importer
class PyxLoader(object): class PyxLoader(object):
def __init__(self, fullname, path, init_path=None, pyxbuild_dir=None, inplace=False): def __init__(self, fullname, path, init_path=None, pyxbuild_dir=None,
_debug("PyxLoader created for loading %s from %s (init path: %s)", fullname, path, init_path) inplace=False, language_level=None):
_debug("PyxLoader created for loading %s from %s (init path: %s)",
fullname, path, init_path)
self.fullname = fullname self.fullname = fullname
self.path, self.init_path = path, init_path self.path, self.init_path = path, init_path
self.pyxbuild_dir = pyxbuild_dir self.pyxbuild_dir = pyxbuild_dir
self.inplace=inplace self.inplace = inplace
self.language_level = language_level
def load_module(self, fullname): def load_module(self, fullname):
assert self.fullname == fullname, ( assert self.fullname == fullname, (
...@@ -366,13 +382,15 @@ class PyxLoader(object): ...@@ -366,13 +382,15 @@ class PyxLoader(object):
#print "PACKAGE", fullname #print "PACKAGE", fullname
module = load_module(fullname, self.init_path, module = load_module(fullname, self.init_path,
self.pyxbuild_dir, is_package=True, self.pyxbuild_dir, is_package=True,
build_inplace=self.inplace) build_inplace=self.inplace,
language_level=self.language_level)
module.__path__ = [self.path] module.__path__ = [self.path]
else: else:
#print "MODULE", fullname #print "MODULE", fullname
module = load_module(fullname, self.path, module = load_module(fullname, self.path,
self.pyxbuild_dir, self.pyxbuild_dir,
build_inplace=self.inplace) build_inplace=self.inplace,
language_level=self.language_level)
return module return module
...@@ -398,7 +416,8 @@ def _have_importers(): ...@@ -398,7 +416,8 @@ def _have_importers():
def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True,
setup_args={}, reload_support=False, setup_args={}, reload_support=False,
load_py_module_on_import_failure=False, inplace=False): load_py_module_on_import_failure=False, inplace=False,
language_level=None):
"""Main entry point. Call this to install the .pyx import hook in """Main entry point. Call this to install the .pyx import hook in
your meta-path for a single Python process. If you want it to be your meta-path for a single Python process. If you want it to be
installed whenever you use Python, add it to your sitecustomize installed whenever you use Python, add it to your sitecustomize
...@@ -438,6 +457,10 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, ...@@ -438,6 +457,10 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True,
failed. failed.
``inplace``: Install the compiled module next to the source file. ``inplace``: Install the compiled module next to the source file.
``language_level``: The source language level to use: 2 or 3.
The default is to use the language level of the current Python
runtime for .py files and Py2 for .pyx files.
""" """
if not build_dir: if not build_dir:
build_dir = os.path.expanduser('~/.pyxbld') build_dir = os.path.expanduser('~/.pyxbld')
...@@ -454,13 +477,15 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, ...@@ -454,13 +477,15 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True,
py_importer, pyx_importer = None, None py_importer, pyx_importer = None, None
if pyimport and not has_py_importer: if pyimport and not has_py_importer:
py_importer = PyImporter(pyxbuild_dir=build_dir, inplace=inplace) py_importer = PyImporter(pyxbuild_dir=build_dir, inplace=inplace,
language_level=language_level)
# make sure we import Cython before we install the import hook # make sure we import Cython before we install the import hook
import pyximport.pyxbuild, Cython.Compiler.Main, Cython.Compiler.Pipeline, Cython.Compiler.Optimize import pyximport.pyxbuild, Cython.Compiler.Main, Cython.Compiler.Pipeline, Cython.Compiler.Optimize
sys.meta_path.insert(0, py_importer) sys.meta_path.insert(0, py_importer)
if pyximport and not has_pyx_importer: if pyximport and not has_pyx_importer:
pyx_importer = PyxImporter(pyxbuild_dir=build_dir, inplace=inplace) pyx_importer = PyxImporter(pyxbuild_dir=build_dir, inplace=inplace,
language_level=language_level)
sys.meta_path.append(pyx_importer) sys.meta_path.append(pyx_importer)
return py_importer, pyx_importer return py_importer, pyx_importer
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment