Skip to content

Commit 369b8e0

Browse files
authored
Merge pull request #1652 from pganssle/build_meta_legacy
Add build_meta_legacy backend
2 parents 64e60fc + e04a41e commit 369b8e0

File tree

3 files changed

+306
-214
lines changed

3 files changed

+306
-214
lines changed

changelog.d/1652.change.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added the ``build_meta:__legacy__`` backend, a "compatibility mode" PEP 517 backend that can be used as the default when ``build-backend`` is left unspecified in ``pyproject.toml``.

setuptools/build_meta.py

Lines changed: 137 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@
3535
import setuptools
3636
import distutils
3737

38+
__all__ = ['get_requires_for_build_sdist',
39+
'get_requires_for_build_wheel',
40+
'prepare_metadata_for_build_wheel',
41+
'build_wheel',
42+
'build_sdist',
43+
'__legacy__',
44+
'SetupRequirementsError']
3845

3946
class SetupRequirementsError(BaseException):
4047
def __init__(self, specifiers):
@@ -74,81 +81,11 @@ def _to_str(s):
7481
return s
7582

7683

77-
def _run_setup(setup_script='setup.py'):
78-
# Note that we can reuse our build directory between calls
79-
# Correctness comes first, then optimization later
80-
__file__ = setup_script
81-
__name__ = '__main__'
82-
f = getattr(tokenize, 'open', open)(__file__)
83-
code = f.read().replace('\\r\\n', '\\n')
84-
f.close()
85-
exec(compile(code, __file__, 'exec'), locals())
86-
87-
88-
def _fix_config(config_settings):
89-
config_settings = config_settings or {}
90-
config_settings.setdefault('--global-option', [])
91-
return config_settings
92-
93-
94-
def _get_build_requires(config_settings, requirements):
95-
config_settings = _fix_config(config_settings)
96-
97-
sys.argv = sys.argv[:1] + ['egg_info'] + \
98-
config_settings["--global-option"]
99-
try:
100-
with Distribution.patch():
101-
_run_setup()
102-
except SetupRequirementsError as e:
103-
requirements += e.specifiers
104-
105-
return requirements
106-
107-
10884
def _get_immediate_subdirectories(a_dir):
10985
return [name for name in os.listdir(a_dir)
11086
if os.path.isdir(os.path.join(a_dir, name))]
11187

11288

113-
def get_requires_for_build_wheel(config_settings=None):
114-
config_settings = _fix_config(config_settings)
115-
return _get_build_requires(config_settings, requirements=['wheel'])
116-
117-
118-
def get_requires_for_build_sdist(config_settings=None):
119-
config_settings = _fix_config(config_settings)
120-
return _get_build_requires(config_settings, requirements=[])
121-
122-
123-
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
124-
sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', _to_str(metadata_directory)]
125-
_run_setup()
126-
127-
dist_info_directory = metadata_directory
128-
while True:
129-
dist_infos = [f for f in os.listdir(dist_info_directory)
130-
if f.endswith('.dist-info')]
131-
132-
if len(dist_infos) == 0 and \
133-
len(_get_immediate_subdirectories(dist_info_directory)) == 1:
134-
dist_info_directory = os.path.join(
135-
dist_info_directory, os.listdir(dist_info_directory)[0])
136-
continue
137-
138-
assert len(dist_infos) == 1
139-
break
140-
141-
# PEP 517 requires that the .dist-info directory be placed in the
142-
# metadata_directory. To comply, we MUST copy the directory to the root
143-
if dist_info_directory != metadata_directory:
144-
shutil.move(
145-
os.path.join(dist_info_directory, dist_infos[0]),
146-
metadata_directory)
147-
shutil.rmtree(dist_info_directory, ignore_errors=True)
148-
149-
return dist_infos[0]
150-
151-
15289
def _file_with_extension(directory, extension):
15390
matching = (
15491
f for f in os.listdir(directory)
@@ -158,26 +95,137 @@ def _file_with_extension(directory, extension):
15895
return file
15996

16097

161-
def build_wheel(wheel_directory, config_settings=None,
162-
metadata_directory=None):
163-
config_settings = _fix_config(config_settings)
164-
wheel_directory = os.path.abspath(wheel_directory)
165-
sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
166-
config_settings["--global-option"]
167-
_run_setup()
168-
if wheel_directory != 'dist':
169-
shutil.rmtree(wheel_directory)
170-
shutil.copytree('dist', wheel_directory)
98+
class _BuildMetaBackend(object):
99+
100+
def _fix_config(self, config_settings):
101+
config_settings = config_settings or {}
102+
config_settings.setdefault('--global-option', [])
103+
return config_settings
104+
105+
def _get_build_requires(self, config_settings, requirements):
106+
config_settings = self._fix_config(config_settings)
107+
108+
sys.argv = sys.argv[:1] + ['egg_info'] + \
109+
config_settings["--global-option"]
110+
try:
111+
with Distribution.patch():
112+
self.run_setup()
113+
except SetupRequirementsError as e:
114+
requirements += e.specifiers
115+
116+
return requirements
117+
118+
def run_setup(self, setup_script='setup.py'):
119+
# Note that we can reuse our build directory between calls
120+
# Correctness comes first, then optimization later
121+
__file__ = setup_script
122+
__name__ = '__main__'
123+
f = getattr(tokenize, 'open', open)(__file__)
124+
code = f.read().replace('\\r\\n', '\\n')
125+
f.close()
126+
exec(compile(code, __file__, 'exec'), locals())
127+
128+
def get_requires_for_build_wheel(self, config_settings=None):
129+
config_settings = self._fix_config(config_settings)
130+
return self._get_build_requires(config_settings, requirements=['wheel'])
131+
132+
def get_requires_for_build_sdist(self, config_settings=None):
133+
config_settings = self._fix_config(config_settings)
134+
return self._get_build_requires(config_settings, requirements=[])
135+
136+
def prepare_metadata_for_build_wheel(self, metadata_directory,
137+
config_settings=None):
138+
sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',
139+
_to_str(metadata_directory)]
140+
self.run_setup()
141+
142+
dist_info_directory = metadata_directory
143+
while True:
144+
dist_infos = [f for f in os.listdir(dist_info_directory)
145+
if f.endswith('.dist-info')]
146+
147+
if (len(dist_infos) == 0 and
148+
len(_get_immediate_subdirectories(dist_info_directory)) == 1):
149+
150+
dist_info_directory = os.path.join(
151+
dist_info_directory, os.listdir(dist_info_directory)[0])
152+
continue
153+
154+
assert len(dist_infos) == 1
155+
break
156+
157+
# PEP 517 requires that the .dist-info directory be placed in the
158+
# metadata_directory. To comply, we MUST copy the directory to the root
159+
if dist_info_directory != metadata_directory:
160+
shutil.move(
161+
os.path.join(dist_info_directory, dist_infos[0]),
162+
metadata_directory)
163+
shutil.rmtree(dist_info_directory, ignore_errors=True)
164+
165+
return dist_infos[0]
166+
167+
def build_wheel(self, wheel_directory, config_settings=None,
168+
metadata_directory=None):
169+
config_settings = self._fix_config(config_settings)
170+
wheel_directory = os.path.abspath(wheel_directory)
171+
sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
172+
config_settings["--global-option"]
173+
self.run_setup()
174+
if wheel_directory != 'dist':
175+
shutil.rmtree(wheel_directory)
176+
shutil.copytree('dist', wheel_directory)
177+
178+
return _file_with_extension(wheel_directory, '.whl')
179+
180+
def build_sdist(self, sdist_directory, config_settings=None):
181+
config_settings = self._fix_config(config_settings)
182+
sdist_directory = os.path.abspath(sdist_directory)
183+
sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \
184+
config_settings["--global-option"] + \
185+
["--dist-dir", sdist_directory]
186+
self.run_setup()
187+
188+
return _file_with_extension(sdist_directory, '.tar.gz')
189+
190+
191+
class _BuildMetaLegacyBackend(_BuildMetaBackend):
192+
"""Compatibility backend for setuptools
193+
194+
This is a version of setuptools.build_meta that endeavors to maintain backwards
195+
compatibility with pre-PEP 517 modes of invocation. It exists as a temporary
196+
bridge between the old packaging mechanism and the new packaging mechanism,
197+
and will eventually be removed.
198+
"""
199+
def run_setup(self, setup_script='setup.py'):
200+
# In order to maintain compatibility with scripts assuming that
201+
# the setup.py script is in a directory on the PYTHONPATH, inject
202+
# '' into sys.path. (pypa/setuptools#1642)
203+
sys_path = list(sys.path) # Save the original path
204+
205+
script_dir = os.path.dirname(os.path.abspath(setup_script))
206+
if script_dir not in sys.path:
207+
sys.path.insert(0, script_dir)
208+
209+
try:
210+
super(_BuildMetaLegacyBackend,
211+
self).run_setup(setup_script=setup_script)
212+
finally:
213+
# While PEP 517 frontends should be calling each hook in a fresh
214+
# subprocess according to the standard (and thus it should not be
215+
# strictly necessary to restore the old sys.path), we'll restore
216+
# the original path so that the path manipulation does not persist
217+
# within the hook after run_setup is called.
218+
sys.path[:] = sys_path
171219

172-
return _file_with_extension(wheel_directory, '.whl')
220+
# The primary backend
221+
_BACKEND = _BuildMetaBackend()
173222

223+
get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel
224+
get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist
225+
prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel
226+
build_wheel = _BACKEND.build_wheel
227+
build_sdist = _BACKEND.build_sdist
174228

175-
def build_sdist(sdist_directory, config_settings=None):
176-
config_settings = _fix_config(config_settings)
177-
sdist_directory = os.path.abspath(sdist_directory)
178-
sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \
179-
config_settings["--global-option"] + \
180-
["--dist-dir", sdist_directory]
181-
_run_setup()
182229

183-
return _file_with_extension(sdist_directory, '.tar.gz')
230+
# The legacy backend
231+
__legacy__ = _BuildMetaLegacyBackend()

0 commit comments

Comments
 (0)