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

Partially implement PEP 517 #4589

Closed
wants to merge 82 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
cef6c02
# This is a combination of 2 commits.
xoviat Sep 2, 2017
b44f765
ENH: wheel: attempt to build with pep517
xoviat Oct 16, 2017
73fde9e
backend: remove dead code
xoviat Sep 2, 2017
634a760
backend: assume isolated
xoviat Sep 2, 2017
d3f2b7a
backend: remove --no-user-cfg
xoviat Sep 2, 2017
456dff7
backend: remove circular dependency
xoviat Sep 3, 2017
d3fbcfa
req_install: fix build_environment cleanup
xoviat Sep 3, 2017
461c793
wheel: fix build_environment
xoviat Sep 3, 2017
b6569be
MAINT: backend: remove pyproject_toml
xoviat Sep 3, 2017
41b3fc6
backend: begin fix for prepare_metadata
xoviat Sep 3, 2017
0d8b46f
wheel: don't use backend to clean
xoviat Sep 3, 2017
5435681
FIX: backend: remove editable as a parameter
xoviat Sep 3, 2017
a762108
backend: use the setuptools build_meta
xoviat Oct 13, 2017
69dba1f
MAINT: req_install: fix setuptools requirements
xoviat Oct 13, 2017
f8609f2
BUG: fix the metadata directory to be correct
xoviat Oct 13, 2017
5483575
FIX: check for METADATA in all packages
xoviat Oct 14, 2017
c12e92d
TST: temporarily disable
xoviat Oct 14, 2017
7f152b4
TST: temporarily force a newer setuptools
xoviat Oct 14, 2017
84af08c
FIX: install build dependencies inside of the build environment
xoviat Oct 14, 2017
f04937e
FIX: backend: print system PATH
xoviat Oct 14, 2017
882de6e
ENH: log both parent and child debugging information
xoviat Oct 14, 2017
3b72d1a
FIX: backend: override default environment
xoviat Oct 14, 2017
84535ac
TST: set maxfail
xoviat Oct 14, 2017
c847b85
TST: set timeout
xoviat Oct 14, 2017
dd21534
FIX: set time limit for command to run
xoviat Oct 14, 2017
1c400cd
FIX: repair the pickling error
xoviat Oct 15, 2017
99f04b8
TST: tox: increase maxfail
xoviat Oct 15, 2017
2905b18
change to print to actually see output
xoviat Oct 15, 2017
091dfdd
FIX: backend: set the correct paths
xoviat Oct 15, 2017
d8d94ab
FIX: backend: show entry points
xoviat Oct 15, 2017
d68cdf2
[tmp] travis: only keep py27/py36 jobs
benoit-pierre Oct 15, 2017
5858f5c
monkey-patch backend
benoit-pierre Oct 15, 2017
535647e
drop timeout hack
benoit-pierre Oct 15, 2017
d8ff52c
tests: mark `test_install_environment_markers` as xfailed
benoit-pierre Oct 15, 2017
c2eccdf
tests: mark `test_install_pep508_with_url_in_install_requires` as xfa…
benoit-pierre Oct 15, 2017
a7efc40
tests: tweak some tests for easier debugging
benoit-pierre Oct 15, 2017
bab4f6d
fix `InstallRequirement.get_dist`
benoit-pierre Oct 15, 2017
4b9ab5f
tests: fix `test_install_special_extra`
benoit-pierre Oct 15, 2017
9a42d0b
tests: fix `test_install_collected_dependencies_first`
benoit-pierre Oct 15, 2017
09f66be
tests: mark `test_config_file_override_stack` as xfailed
benoit-pierre Oct 15, 2017
1f37d5c
TST: req: revert changes
xoviat Oct 16, 2017
061b70f
TST: xfail the PEP 518 test
xoviat Oct 16, 2017
15c9427
FIX: xfailed -> xfail
xoviat Oct 16, 2017
8f56787
MAINT: eliminate useless extra process
xoviat Oct 17, 2017
136496a
FIX: switch to logging
xoviat Oct 17, 2017
52778ea
FIX: backend: compat: remove PY2 cmdline option
xoviat Oct 17, 2017
5933684
ENH: backend: compat: isolate on PY2
xoviat Oct 17, 2017
bc9c758
ENH: add patch_setuptools
xoviat Oct 18, 2017
9eed561
FIX: patch setuptools
xoviat Oct 18, 2017
6565e09
FIX: add missing parentheses
xoviat Oct 18, 2017
f9e49e2
FIX: remove docstring
xoviat Oct 18, 2017
1bb15dc
FIX: remove docstring
xoviat Oct 18, 2017
9fba2b2
BUG: use absolute metadata directory
xoviat Oct 18, 2017
ff03aa6
FIX: ignore removal errors
xoviat Oct 18, 2017
1617915
TST: install_reqs: skip collection of build requirements
xoviat Oct 19, 2017
b2408a4
FIX: show output
xoviat Oct 19, 2017
a95cb5f
FIX: print output
xoviat Oct 19, 2017
b0c5ada
FIX: cleanup the build directory
xoviat Oct 19, 2017
6c8f12d
FIX: backport the setuptools patch
xoviat Oct 19, 2017
d23da97
FIX: syntax
xoviat Oct 19, 2017
f6c1ae2
FIX: backend: don't show the output
xoviat Oct 19, 2017
a513942
BUG: add only-binary to dependency installation
xoviat Oct 19, 2017
2c74bde
FIX: don't show stdout
xoviat Oct 19, 2017
a734911
FIX: apply option to all packages
xoviat Oct 19, 2017
378072c
TST: install_reqs: revert changes
xoviat Oct 19, 2017
9e67be6
ENH: patch setuptools
xoviat Oct 19, 2017
8f5e27a
FIX: req_install: show directories to tests
xoviat Oct 19, 2017
43870fc
BUG: Update the setuptools patch
xoviat Oct 19, 2017
056a851
Merge branch 'pep517' into pep517-work
xoviat Oct 19, 2017
3e4f521
BUG: Update the setuptools patch
xoviat Oct 19, 2017
81ff5f0
FIX: revert the namespace packages hack
xoviat Oct 19, 2017
753a947
BUG: patch distlib for Python 2
xoviat Oct 19, 2017
e9041d6
[squash]
xoviat Oct 19, 2017
58b8973
TST: functional: install: fix command
xoviat Oct 19, 2017
aaef5aa
FIX: fallback on Python 3.3
xoviat Oct 20, 2017
c9d571b
CI: travis: add back more jobs
xoviat Oct 20, 2017
a7f6d7b
[squash]
xoviat Oct 20, 2017
48ea32c
BUG: fix command-line flags for PyPy
xoviat Oct 20, 2017
cbca754
Merge branch 'master' into pep517
xoviat Mar 4, 2018
8cda666
prepare: revert changes
xoviat Mar 4, 2018
6ebfcd0
Create metadata directory.
xoviat Mar 4, 2018
a884794
Fix import
xoviat Mar 4, 2018
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
11 changes: 6 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ dist: trusty
matrix:
fast_finish: true
include:
- env: TOXENV=docs
- env: TOXENV=lint-py2
- env: TOXENV=lint-py3
- env: TOXENV=mypy
- env: TOXENV=packaging
# - env: TOXENV=docs
# - env: TOXENV=lint-py2
# - env: TOXENV=lint-py3
# - env: TOXENV=mypy
# - env: TOXENV=packaging
# PyPy jobs start first -- they are the slowest
- env: TOXENV=pypy
python: pypy
Expand All @@ -32,6 +32,7 @@ matrix:
python: nightly
allow_failures:
- python: nightly
- python: 2.7

install: travis_retry .travis/install.sh
script: .travis/run.sh
Expand Down
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ pyyaml
mock
scripttest>=1.3
https:/pypa/virtualenv/archive/master.zip#egg=virtualenv
setuptools>=36.6.0
1 change: 1 addition & 0 deletions news/4589.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement PEP 517 behavior for setuptools.
93 changes: 93 additions & 0 deletions src/pip/_internal/backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import ast
import importlib
import logging
import os
import sys
import tempfile
import textwrap
import platform

from pip._internal.utils.misc import call_subprocess, ensure_dir
from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM
from pip._internal.utils.temp_dir import TempDirectory

from sysconfig import get_paths
from copy import copy

logger = logging.getLogger(__name__)


class BuildBackendBase(object):
def __init__(self, cwd=None, env={}, backend_name='setuptools.build_meta'):
self.cwd = os.path.abspath(cwd)
self.backend_name = backend_name
self.env = env

def _log_debug_info(self, worker_name):
logger.debug(textwrap.dedent("""
{} runner data:
Current Directory: {}
System Backend: {}
System Path: {}
System Environment: {}
""").format(
worker_name,
self.cwd,
self.backend_name,
sys.path,
os.environ))


class BuildBackend(BuildBackendBase):
"""PEP 517 Build Backend"""
def __init__(self, *args, **kwargs):
super(BuildBackend, self).__init__(*args, **kwargs)
self.env = dict(os.environ)

def __getattr__(self, name):
"""Handles aribrary function invocations on the build backend."""
def method(*args, **kw):
self._log_debug_info('Parent')
return BuildBackendCaller(
self.cwd, self.env, self.backend_name)(name, *args, **kw)

return method


class BuildBackendCaller(BuildBackendBase):
def __call__(self, name, *args, **kwargs):
"""Handles aribrary function invocations on the build backend."""
tmpf = tempfile.NamedTemporaryFile(delete=False)
tmpf.close()
command_base = [sys.executable]
if platform.python_implementation() == 'PyPy':
command_base += ['-S', '-s']
elif sys.version_info < (3, 4):
command_base += ['-E', '-s']
else:
command_base += ['-I']
try:
call_subprocess(command_base + ['-c', textwrap.dedent(
'''
import importlib
import os
import sys

py_path = {py_path!r}
if py_path is not None:
sys.path[0:0] = py_path.split(os.pathsep)
mod = importlib.import_module({backend_name!r})
res = getattr(mod, {name!r})(*{args!r}, **{kwargs})
with open({result!r}, 'w') as fp:
fp.write(repr(res))
''').format(
py_path=self.env.get('PYTHONPATH'),
backend_name=self.backend_name,
name=name, args=args, kwargs=kwargs,
result=tmpf.name,
)], cwd=self.cwd, extra_environ=self.env, show_stdout=False)
with open(tmpf.name) as fp:
res = fp.read()
finally:
os.unlink(tmpf.name)
return ast.literal_eval(res)
155 changes: 155 additions & 0 deletions src/pip/_internal/operations/patch_setuptools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import os
import textwrap

def find_build_meta(prefix_path):
for root, dirnames, filenames in os.walk(prefix_path):
for filename in filenames:
if filename == 'build_meta.py':
return os.path.join(root, filename)

def patch_build_meta(prefix_path):

build_meta_path = find_build_meta(prefix_path)
os.remove(build_meta_path)
with open(build_meta_path, 'w+') as fp:
fp.write(textwrap.dedent("""
import os
import sys
import tokenize
import shutil
import contextlib

import setuptools
import distutils


class SetupRequirementsError(BaseException):
def __init__(self, specifiers):
self.specifiers = specifiers


class Distribution(setuptools.dist.Distribution):
def fetch_build_eggs(self, specifiers):
raise SetupRequirementsError(specifiers)

@classmethod
@contextlib.contextmanager
def patch(cls):
orig = distutils.core.Distribution
distutils.core.Distribution = cls
try:
yield
finally:
distutils.core.Distribution = orig


def _run_setup(setup_script='setup.py'):
# Note that we can reuse our build directory between calls
# Correctness comes first, then optimization later
__file__ = setup_script
__name__ = '__main__'
f = getattr(tokenize, 'open', open)(__file__)
code = f.read().replace('\\r\\n', '\\n')
f.close()
exec(compile(code, __file__, 'exec'), locals())


def _fix_config(config_settings):
config_settings = config_settings or {}
config_settings.setdefault('--global-option', [])
return config_settings


def _get_build_requires(config_settings):
config_settings = _fix_config(config_settings)
requirements = ['setuptools', 'wheel']

sys.argv = sys.argv[:1] + ['egg_info'] + \
config_settings["--global-option"]
try:
with Distribution.patch():
_run_setup()
except SetupRequirementsError as e:
requirements += e.specifiers

return requirements


def _get_immediate_subdirectories(a_dir):
return [name for name in os.listdir(a_dir)
if os.path.isdir(os.path.join(a_dir, name))]


def get_requires_for_build_wheel(config_settings=None):
config_settings = _fix_config(config_settings)
return _get_build_requires(config_settings)


def get_requires_for_build_sdist(config_settings=None):
config_settings = _fix_config(config_settings)
return _get_build_requires(config_settings)


def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', metadata_directory]
_run_setup()

dist_info_directory = metadata_directory
while True:
dist_infos = [f for f in os.listdir(dist_info_directory)
if f.endswith('.dist-info')]

if len(dist_infos) == 0 and \
len(_get_immediate_subdirectories(dist_info_directory)) == 1:
dist_info_directory = os.path.join(
dist_info_directory, os.listdir(dist_info_directory)[0])
continue

assert len(dist_infos) == 1
break

# PEP 517 requires that the .dist-info directory be placed in the
# metadata_directory. To comply, we MUST copy the directory to the root
if dist_info_directory != metadata_directory:
shutil.move(
os.path.join(dist_info_directory, dist_infos[0]),
metadata_directory)
shutil.rmtree(dist_info_directory, ignore_errors=True)

return dist_infos[0]


def build_wheel(wheel_directory, config_settings=None,
metadata_directory=None):
config_settings = _fix_config(config_settings)
wheel_directory = os.path.abspath(wheel_directory)
sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
config_settings["--global-option"]
_run_setup()
if wheel_directory != 'dist':
shutil.rmtree(wheel_directory)
shutil.copytree('dist', wheel_directory)

wheels = [f for f in os.listdir(wheel_directory)
if f.endswith('.whl')]

assert len(wheels) == 1
return wheels[0]


def build_sdist(sdist_directory, config_settings=None):
config_settings = _fix_config(config_settings)
sdist_directory = os.path.abspath(sdist_directory)
sys.argv = sys.argv[:1] + ['sdist'] + \
config_settings["--global-option"]
_run_setup()
if sdist_directory != 'dist':
shutil.rmtree(sdist_directory)
shutil.copytree('dist', sdist_directory)

sdists = [f for f in os.listdir(sdist_directory)
if f.endswith('.tar.gz')]

assert len(sdists) == 1
return sdists[0]
"""))
Loading