Commit 77716e17 authored by Xavier Thompson's avatar Xavier Thompson

[feat] Enable build of pyproject.toml projects

Enable zc.buildout.easy_install.build, which builds a project manually
from an unpacked sdist archive and is used by zc.recipe.egg:custom, to
build a project which only has a pyproject.toml but no setup.py.
parent 28a2f87c
......@@ -940,35 +940,41 @@ class Installer(object):
try:
setuptools.archive_util.unpack_archive(dist.location,
build_tmp)
if os.path.exists(os.path.join(build_tmp, 'setup.py')):
base = build_tmp
# Find pyproject.toml or setup.py
for filename in ('pyproject.toml', 'setup.py'):
if os.path.exists(os.path.join(build_tmp, filename)):
base = build_tmp
break
else:
setups = glob.glob(
os.path.join(build_tmp, '*', 'setup.py'))
if not setups:
raise distutils.errors.DistutilsError(
"Couldn't find a setup script in %s"
% os.path.basename(dist.location)
)
if len(setups) > 1:
for filename in ('pyproject.toml', 'setup.py'):
setups = glob.glob(
os.path.join(build_tmp, '*', filename))
if setups:
if len(setups) > 1:
raise distutils.errors.DistutilsError(
"Multiple %s in %s" % (
filename, os.path.basename(dist.location)))
base = os.path.dirname(setups[0])
break
else:
raise distutils.errors.DistutilsError(
"Multiple setup scripts in %s"
"Couldn't find a pyproject.toml nor setup.py in %s"
% os.path.basename(dist.location)
)
base = os.path.dirname(setups[0])
setup_cfg_dict = {'build_ext':build_ext}
patch_dict = (patch_dict or {}).get(re.sub('[<>=].*', '', spec))
# Apply patches.
if patch_dict:
setup_cfg_dict.update(
{'egg_info':{'tag_build':'+%s%03d' % (PATCH_MARKER,
patch_dict['patch_revision'])}})
patch_dict = patch_dict.get(re.sub('[<>=].*', '', spec))
for i, patch in enumerate(patch_dict['patches']):
url, md5sum = (patch.strip().split('#', 1) + [''])[:2]
download = zc.buildout.download.Download()
path, is_temp = download(url, md5sum=md5sum or None,
path=os.path.join(tmp, 'patch.%s' % i))
args = [patch_dict['patch_binary']] + patch_dict['patch_options']
path, is_temp = download(
url,
md5sum=md5sum or None,
path=os.path.join(tmp, 'patch.%s' % i))
args = [patch_dict['patch_binary']]
args.extend(patch_dict['patch_options'])
kwargs = {'cwd':base,
'stdin':open(path)}
popen = subprocess.Popen(args, **kwargs)
......@@ -976,12 +982,44 @@ class Installer(object):
if popen.returncode != 0:
raise subprocess.CalledProcessError(
popen.returncode, ' '.join(args))
setup_cfg = os.path.join(base, 'setup.cfg')
if not os.path.exists(setup_cfg):
f = open(setup_cfg, 'w')
f.close()
setuptools.command.setopt.edit_config(
setup_cfg, setup_cfg_dict)
# Attempt to determine whether setuptools is used.
def uses_setuptools():
if filename == 'setup.py':
return True
for setup in ('setup.py', 'setup.cfg'):
if os.path.exists(os.path.join(base, setup)):
return True
with open(os.path.join(base, 'pyproject.toml')) as f:
config = f.read()
pattern = "^build-backend\s*=\s*['\"]+setuptools"
if re.search(pattern, config, re.MULTILINE):
return True
return False
# Edit setup.cfg if required; warn if setuptools is not used.
if uses_setuptools():
setup_cfg_dict = {'build_ext': build_ext}
if patch_dict:
# TODO: find alternative for without setuptools.
setup_cfg_dict.update(
{'egg_info':{'tag_build':'+%s%03d' % (
PATCH_MARKER,
patch_dict['patch_revision'])}})
setup_cfg = os.path.join(base, 'setup.cfg')
if not os.path.exists(setup_cfg):
with open(setup_cfg, 'w'):
pass
setuptools.command.setopt.edit_config(
setup_cfg, setup_cfg_dict)
else:
if build_ext or patch_dict:
logger.warning(
"Build options call for editing setup.cfg "
"but project %s does not use setuptools. "
"Proceeding without."
% dist
)
dists = self._call_pip_wheel(base, self._dest, dist)
......
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