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

Implement PEP 660 allowing both "strict" and "lax/loose" approaches #3265

Merged
merged 55 commits into from Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
be3778e
include pep660 proof of concept
dholth Feb 4, 2022
2bddfdf
include pep660 proof of concept (#3082)
abravalheri Apr 11, 2022
c6106b7
Add dist_info_dir param to dist_info command
abravalheri Apr 13, 2022
ad803ae
Change dist_info to better control output directory
abravalheri Apr 3, 2022
e36951e
Merge branch 'upstream/main' into build-editable-aggregate
abravalheri May 19, 2022
e55e51d
Change build_meta to use --output-dir instead of --egg-base for dist-…
abravalheri Apr 3, 2022
1afb6c0
Make sure output_dir exists with dist_info
abravalheri Apr 4, 2022
0e6870b
Avoid creating dist_info_dir before the command runs
abravalheri Apr 13, 2022
da6dd05
Fix signature for build_editable according to PEP 660
abravalheri Apr 3, 2022
e7123c6
Fix flake8 errors with build_meta
abravalheri Apr 3, 2022
821d664
Add prepare_metadata_for_build_editable hook
abravalheri Apr 3, 2022
c642529
Editable rework dist_info to use --output-dir instead of --egg-base
abravalheri Jun 15, 2022
5bb97d0
Remove unecessary editable dependency
abravalheri Apr 3, 2022
3e9f441
Make sure setuptools itself can be installed with editable_wheel
abravalheri Apr 13, 2022
5866b85
Rely on wheel and bdist_wheel for editable_wheel
abravalheri Apr 4, 2022
aee3245
Re-use dist-info dir for build_editable
abravalheri Apr 4, 2022
33f2431
Always run editable install test
abravalheri Apr 4, 2022
06fbc36
Start adding APIs for handling multiple editable modes
abravalheri Apr 5, 2022
0bf1d4c
Rework PEP 660 PoC to re-use bdist_wheel
abravalheri Jun 15, 2022
7b402eb
Temporarily support deprecated namespace packages
abravalheri Apr 6, 2022
a31df2e
Remove unused function
abravalheri Apr 13, 2022
7ae5a69
Reorganise editable_wheel to allow different strategies
abravalheri Apr 9, 2022
a13adc8
Handle namespace_packages in editable_wheel
abravalheri Jun 15, 2022
14eb855
Rename variable for clarity
abravalheri Apr 9, 2022
8cb1344
Add namespace test
abravalheri Apr 9, 2022
f997500
Add initial implementation of editable strategy based on .pth file
abravalheri Jun 15, 2022
73c65b2
Move test from test_develop to test_editable_install
abravalheri Apr 9, 2022
59a39d9
Add test for PEP 420 packages
abravalheri Apr 9, 2022
a27b96b
Add tests for editable install focusing on namespaces
abravalheri Jun 15, 2022
1a531db
Add template for MetaPathFinder that can be used in editable mode
abravalheri Apr 9, 2022
dd9886c
Add test for namespaces created via package_dir
abravalheri Apr 9, 2022
f210f16
Relax file types in discovery
abravalheri Apr 9, 2022
994ca21
Add editable strategy with MetaPathFinder for top-level packages
abravalheri Apr 9, 2022
fba8717
Make sure top-level modules can be imported in editable install
abravalheri Apr 9, 2022
3ba7ec4
Add logging messages to editable install
abravalheri Apr 9, 2022
01ceef6
Fix error with Python 3.7
abravalheri Apr 10, 2022
55260a7
Prevent errors when __path__ is not set
abravalheri Apr 12, 2022
730b6e7
Prevent errors due to caching in sys.modules
abravalheri Apr 12, 2022
50afbf4
Add LinkTree strategy for build executable
abravalheri Apr 10, 2022
40f2f0f
Improve clarity of 'editable_wheel' code
abravalheri Apr 11, 2022
f5643f5
Initial editable MetaPathFinder for top-level pkgs
abravalheri Jun 15, 2022
4112379
Add more tests for editable install
abravalheri Apr 11, 2022
008a718
Add temporary workaround for packages.find.exclude
abravalheri Apr 22, 2022
f3786f3
Allow egg-info directory to be ignored in manifest
abravalheri Apr 11, 2022
06d52fe
Fix problems with link assertions on Windows
abravalheri Apr 12, 2022
9dc2588
Ignore transient warning
abravalheri May 19, 2022
92c90db
Add a better workaround for 3260 in tests for editable tree
abravalheri May 19, 2022
a4e16fe
Remove unnecessary fixture from tests
abravalheri Apr 17, 2022
99cf706
Test dynamic namespace path computation
abravalheri Apr 17, 2022
3c71c87
Correctly handle namespace spec via PathEntryFinder
abravalheri Apr 16, 2022
d9c4a41
Add editable strategy based on a link tree
abravalheri Jun 15, 2022
2ca60ad
Adequate tests to new internal API
abravalheri Apr 17, 2022
501aec9
Add missing methods to PathEntryFinder
abravalheri Apr 17, 2022
4687243
Avoid adding PathEntryFinder if not necessary
abravalheri Apr 17, 2022
daaf3ab
Ensure namespaces from ImportFinder handle additions to path
abravalheri Jun 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions bootstrap.egg-info/entry_points.txt
Expand Up @@ -2,6 +2,7 @@
egg_info = setuptools.command.egg_info:egg_info
build_py = setuptools.command.build_py:build_py
sdist = setuptools.command.sdist:sdist
editable_wheel = setuptools.command.editable_wheel:editable_wheel

[distutils.setup_keywords]
include_package_data = setuptools.dist:assert_bool
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Expand Up @@ -113,6 +113,7 @@ distutils.commands =
develop = setuptools.command.develop:develop
dist_info = setuptools.command.dist_info:dist_info
easy_install = setuptools.command.easy_install:easy_install
editable_wheel = setuptools.command.editable_wheel:editable_wheel
egg_info = setuptools.command.egg_info:egg_info
install = setuptools.command.install:install
install_egg_info = setuptools.command.install_egg_info:install_egg_info
Expand Down
29 changes: 28 additions & 1 deletion setuptools/build_meta.py
Expand Up @@ -46,6 +46,8 @@
'prepare_metadata_for_build_wheel',
'build_wheel',
'build_sdist',
'get_requires_for_build_editable',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abravalheri You forgot to add 'prepare_metadata_for_build_editable' to the __all__ list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much @dalcinl. I am addressing this on #3477.

'build_editable',
'__legacy__',
'SetupRequirementsError']

Expand Down Expand Up @@ -183,7 +185,7 @@ def get_requires_for_build_sdist(self, config_settings=None):
def prepare_metadata_for_build_wheel(self, metadata_directory,
config_settings=None):
sys.argv = sys.argv[:1] + [
'dist_info', '--egg-base', metadata_directory]
'dist_info', '--output-dir', metadata_directory]
with no_install_setup_requires():
self.run_setup()

Expand Down Expand Up @@ -249,6 +251,28 @@ def build_sdist(self, sdist_directory, config_settings=None):
'.tar.gz', sdist_directory,
config_settings)

# PEP660 hooks:
# build_editable
# get_requires_for_build_editable
# prepare_metadata_for_build_editable
def build_editable(
self, wheel_directory, config_settings=None, metadata_directory=None
):
# XXX can or should we hide our editable_wheel command normally?
return self._build_with_temp_dir(
["editable_wheel", "--dist-info-dir", metadata_directory],
".whl", wheel_directory, config_settings
)

def get_requires_for_build_editable(self, config_settings=None):
return self.get_requires_for_build_wheel(config_settings)

def prepare_metadata_for_build_editable(self, metadata_directory,
config_settings=None):
return self.prepare_metadata_for_build_wheel(
metadata_directory, config_settings
)


class _BuildMetaLegacyBackend(_BuildMetaBackend):
"""Compatibility backend for setuptools
Expand Down Expand Up @@ -295,9 +319,12 @@ def run_setup(self, setup_script='setup.py'):

get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel
get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist
get_requires_for_build_editable = _BACKEND.get_requires_for_build_editable
prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel
prepare_metadata_for_build_editable = _BACKEND.prepare_metadata_for_build_editable
build_wheel = _BACKEND.build_wheel
build_sdist = _BACKEND.build_sdist
build_editable = _BACKEND.build_editable


# The legacy backend
Expand Down
6 changes: 1 addition & 5 deletions setuptools/command/build_ext.py
Expand Up @@ -3,7 +3,6 @@
import itertools
from importlib.machinery import EXTENSION_SUFFIXES
from distutils.command.build_ext import build_ext as _du_build_ext
from distutils.file_util import copy_file
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler, get_config_var
from distutils.errors import DistutilsError
Expand Down Expand Up @@ -96,10 +95,7 @@ def copy_extensions_to_source(self):
# Always copy, even if source is older than destination, to ensure
# that the right extensions for the current Python/platform are
# used.
copy_file(
src_filename, dest_filename, verbose=self.verbose,
dry_run=self.dry_run
)
build_py.copy_file(src_filename, dest_filename)
if ext._needs_stub:
self.write_stub(package_dir or os.curdir, ext, True)

Expand Down
11 changes: 11 additions & 0 deletions setuptools/command/build_py.py
Expand Up @@ -36,6 +36,17 @@ def finalize_options(self):
if 'data_files' in self.__dict__:
del self.__dict__['data_files']
self.__updated_files = []
self.use_links = None

def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
link=None, level=1):
# Overwrite base class to allow using links
link = getattr(self, "use_links", None) if link is None else link
if link:
infile = str(Path(infile).resolve())
outfile = str(Path(outfile).resolve())
return super().copy_file(infile, outfile, preserve_mode,
preserve_times, link, level)

def run(self):
"""Build modules, packages, and copy data files to build directory"""
Expand Down
44 changes: 32 additions & 12 deletions setuptools/command/dist_info.py
Expand Up @@ -7,10 +7,12 @@
import re
import warnings
from inspect import cleandoc
from pathlib import Path

from distutils.core import Command
from distutils import log
from setuptools.extern import packaging
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning


class dist_info(Command):
Expand All @@ -19,28 +21,46 @@ class dist_info(Command):

user_options = [
('egg-base=', 'e', "directory containing .egg-info directories"
" (default: top of the source tree)"),
" (default: top of the source tree)"
" DEPRECATED: use --output-dir."),
('output-dir=', 'o', "directory inside of which the .dist-info will be"
"created (default: top of the source tree)"),
]

def initialize_options(self):
self.egg_base = None
self.output_dir = None
self.name = None
self.dist_info_dir = None

def finalize_options(self):
pass
if self.egg_base:
msg = "--egg-base is deprecated for dist_info command. Use --output-dir."
warnings.warn(msg, SetuptoolsDeprecationWarning)
self.output_dir = self.egg_base or self.output_dir

def run(self):
egg_info = self.get_finalized_command('egg_info')
egg_info.egg_base = self.egg_base
dist = self.distribution
project_dir = dist.src_root or os.curdir
self.output_dir = Path(self.output_dir or project_dir)

egg_info = self.reinitialize_command('egg_info')
egg_info.egg_base = str(self.output_dir)
egg_info.finalize_options()
egg_info.run()
name = _safe(self.distribution.get_name())
version = _version(self.distribution.get_version())
base = self.egg_base or os.curdir
dist_info_dir = os.path.join(base, f"{name}-{version}.dist-info")
log.info("creating '{}'".format(os.path.abspath(dist_info_dir)))
self.egg_info = egg_info

name = _safe(dist.get_name())
version = _version(dist.get_version())
self.name = f"{name}-{version}"
self.dist_info_dir = os.path.join(self.output_dir, f"{self.name}.dist-info")

def run(self):
self.output_dir.mkdir(parents=True, exist_ok=True)
self.egg_info.run()
egg_info_dir = self.egg_info.egg_info
log.info("creating '{}'".format(os.path.abspath(self.dist_info_dir)))
bdist_wheel = self.get_finalized_command('bdist_wheel')
bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir)
bdist_wheel.egg2dist(egg_info_dir, self.dist_info_dir)
assert os.path.exists(egg_info_dir) is False


def _safe(component: str) -> str:
Expand Down