Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade setuptools.depends to importlib from depracated imp #1855

Merged
merged 16 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/479.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace usage of deprecated ``imp`` module with local re-implementation in ``setuptools._imp``.
1 change: 1 addition & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def pytest_addoption(parser):

if sys.version_info < (3,):
collect_ignore.append('setuptools/lib2to3_ex.py')
collect_ignore.append('setuptools/_imp.py')


if sys.version_info < (3, 6):
Expand Down
73 changes: 73 additions & 0 deletions setuptools/_imp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Re-implementation of find_module and get_frozen_object
from the deprecated imp module.
"""

import os
import importlib.util
import importlib.machinery

from .py34compat import module_from_spec


PY_SOURCE = 1
PY_COMPILED = 2
C_EXTENSION = 3
C_BUILTIN = 6
PY_FROZEN = 7


def find_module(module, paths=None):
"""Just like 'imp.find_module()', but with package support"""
spec = importlib.util.find_spec(module, paths)
if spec is None:
raise ImportError("Can't find %s" % module)
if not spec.has_location and hasattr(spec, 'submodule_search_locations'):
spec = importlib.util.spec_from_loader('__init__.py', spec.loader)

kind = -1
file = None
static = isinstance(spec.loader, type)
if spec.origin == 'frozen' or static and issubclass(
spec.loader, importlib.machinery.FrozenImporter):
kind = PY_FROZEN
path = None # imp compabilty
suffix = mode = '' # imp compability
elif spec.origin == 'built-in' or static and issubclass(
spec.loader, importlib.machinery.BuiltinImporter):
kind = C_BUILTIN
path = None # imp compabilty
suffix = mode = '' # imp compability
elif spec.has_location:
path = spec.origin
suffix = os.path.splitext(path)[1]
mode = 'r' if suffix in importlib.machinery.SOURCE_SUFFIXES else 'rb'

if suffix in importlib.machinery.SOURCE_SUFFIXES:
kind = PY_SOURCE
elif suffix in importlib.machinery.BYTECODE_SUFFIXES:
kind = PY_COMPILED
elif suffix in importlib.machinery.EXTENSION_SUFFIXES:
kind = C_EXTENSION

if kind in {PY_SOURCE, PY_COMPILED}:
file = open(path, mode)
else:
path = None
suffix = mode = ''

return file, path, (suffix, mode, kind)


def get_frozen_object(module, paths=None):
spec = importlib.util.find_spec(module, paths)
if not spec:
raise ImportError("Can't find %s" % module)
return spec.loader.get_code(module)


def get_module(module, paths, info):
spec = importlib.util.find_spec(module, paths)
if not spec:
raise ImportError("Can't find %s" % module)
return module_from_spec(spec)
48 changes: 19 additions & 29 deletions setuptools/depends.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import sys
import imp
import marshal
import contextlib
from distutils.version import StrictVersion
from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN

from .py33compat import Bytecode

from .py27compat import find_module, PY_COMPILED, PY_FROZEN, PY_SOURCE
from . import py27compat


__all__ = [
'Require', 'find_module', 'get_module_constant', 'extract_constant'
Expand All @@ -15,7 +17,8 @@
class Require:
"""A prerequisite to building or installing a distribution"""

def __init__(self, name, requested_version, module, homepage='',
def __init__(
self, name, requested_version, module, homepage='',
attribute=None, format=None):

if format is None and requested_version is not None:
Expand Down Expand Up @@ -79,23 +82,15 @@ def is_current(self, paths=None):
return self.version_ok(version)


def find_module(module, paths=None):
"""Just like 'imp.find_module()', but with package support"""

parts = module.split('.')

while parts:
part = parts.pop(0)
f, path, (suffix, mode, kind) = info = imp.find_module(part, paths)

if kind == PKG_DIRECTORY:
parts = parts or ['__init__']
paths = [path]

elif parts:
raise ImportError("Can't find %r in %s" % (parts, module))
def maybe_close(f):
@contextlib.contextmanager
def empty():
yield
return
if not f:
return empty()

return info
return contextlib.closing(f)


def get_module_constant(module, symbol, default=-1, paths=None):
Expand All @@ -106,28 +101,23 @@ def get_module_constant(module, symbol, default=-1, paths=None):
constant. Otherwise, return 'default'."""

try:
f, path, (suffix, mode, kind) = find_module(module, paths)
f, path, (suffix, mode, kind) = info = find_module(module, paths)
except ImportError:
# Module doesn't exist
return None

try:
with maybe_close(f):
if kind == PY_COMPILED:
f.read(8) # skip magic & date
code = marshal.load(f)
elif kind == PY_FROZEN:
code = imp.get_frozen_object(module)
code = py27compat.get_frozen_object(module, paths)
elif kind == PY_SOURCE:
code = compile(f.read(), path, 'exec')
else:
# Not something we can parse; we'll have to import it. :(
if module not in sys.modules:
imp.load_module(module, f, path, (suffix, mode, kind))
return getattr(sys.modules[module], symbol, None)

finally:
if f:
f.close()
imported = py27compat.get_module(module, paths, info)
return getattr(imported, symbol, None)

return extract_constant(code, symbol, default)

Expand Down
32 changes: 32 additions & 0 deletions setuptools/py27compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Compatibility Support for Python 2.7 and earlier
"""

import sys
import platform

from setuptools.extern import six
Expand All @@ -26,3 +27,34 @@ def get_all_headers(message, key):

rmtree_safe = str if linux_py2_ascii else lambda x: x
"""Workaround for http://bugs.python.org/issue24672"""


try:
from ._imp import find_module, PY_COMPILED, PY_FROZEN, PY_SOURCE
from ._imp import get_frozen_object, get_module
except ImportError:
import imp
from imp import PY_COMPILED, PY_FROZEN, PY_SOURCE # noqa

def find_module(module, paths=None):
"""Just like 'imp.find_module()', but with package support"""
parts = module.split('.')
while parts:
part = parts.pop(0)
f, path, (suffix, mode, kind) = info = imp.find_module(part, paths)

if kind == imp.PKG_DIRECTORY:
parts = parts or ['__init__']
paths = [path]

elif parts:
raise ImportError("Can't find %r in %s" % (parts, module))

return info

def get_frozen_object(module, paths):
return imp.get_frozen_object(module)

def get_module(module, paths, info):
imp.load_module(module, *info)
return sys.modules[module]
13 changes: 13 additions & 0 deletions setuptools/py34compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import importlib

try:
import importlib.util
except ImportError:
pass


try:
module_from_spec = importlib.util.module_from_spec
except AttributeError:
def module_from_spec(spec):
return spec.loader.load_module(spec.name)