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

Merge with distutils@d7ffdb9c7 #4538

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2c93711
Distutils C++ support
sciyoshi Dec 14, 2023
26f4723
👹 Feed the hobgoblins (delint).
jaraco Feb 13, 2024
fbac766
Adjust tests further to accommodate C++ support.
sciyoshi Feb 14, 2024
9f176ac
👹 Feed the hobgoblins (delint).
jaraco Feb 14, 2024
5174927
Ignore sysconfig variables for LDCXXSHARED as it appears not to exist…
sciyoshi Mar 2, 2024
fa6e218
ENH: Extension should be able to accept PathLike sources objects
MridulS Feb 29, 2024
45a232a
Adjust expectation to match behavior.
jaraco Mar 2, 2024
9cc0c93
For consistency, ensure Extension.sources is always a pathlib.Path ob…
jaraco Mar 2, 2024
c489cdc
When computing input_opt, ensure src is a string (when it could be a …
jaraco Mar 3, 2024
f2a85c1
In filelist, allow for self.files to be pathlib objects.
jaraco Mar 3, 2024
53c82a2
Merge pull request #239 from DimitriPapadopoulos/extra_pairs_of_quotes
jaraco Apr 14, 2024
45740e0
Merge branch 'main' into feature/cpp-support
jaraco Apr 14, 2024
3048e1b
Merge https://github.com/jaraco/skeleton
jaraco Jul 10, 2024
1bcd839
Revert "Disable cygwin tests for now. Ref pypa/setuptools#3921"
jaraco Jul 10, 2024
f21f19a
find_library_file: port from doctest to normal test and fix for cygwin
lazka Jul 12, 2024
7d78834
test_customize_compiler_with_msvc_python: skip for cygwin
lazka Jul 12, 2024
683df4e
Merge pull request #270 from msys2-contrib/fix-cygwin-ci
jaraco Jul 15, 2024
813ab98
Prefer f-strings
jaraco Jul 15, 2024
76e1e71
Merge https://github.com/jaraco/skeleton
jaraco Jul 19, 2024
e27b973
Merge https://github.com/jaraco/skeleton
jaraco Jul 19, 2024
58afb01
Remove r string now that docstring is gone.
jaraco Jul 15, 2024
848c48b
👹 Feed the hobgoblins (delint).
jaraco Jul 19, 2024
d6a581f
👹 Feed the hobgoblins (delint).
jaraco Jul 19, 2024
d3c76bb
Allow path objects
InvincibleRMC Jul 19, 2024
12f2ef0
Need to include 'three' in the input.
jaraco Jul 19, 2024
8a9ca8b
Consolidate str and Path handling.
jaraco Jul 19, 2024
206ca2a
Expand convert_path to also accept pathlib.Path objects.
jaraco Jul 19, 2024
f7adff4
Prefer simply 'pathlib' for import.
jaraco Jul 19, 2024
b440f45
Extract a singledispatchmethod _copy for handling the copy of each da…
jaraco Jul 19, 2024
94b6d14
Use explicit registration for compatibility with older Pythons.
jaraco Jul 19, 2024
4d50db3
Prefer os.PathLike in convert_path
jaraco Jul 19, 2024
3debdcc
Simply accept pathlib objects and convert them early for compatibilty…
jaraco Jul 19, 2024
e88bd79
Convert needs to accept None for Setuptools' sake.
jaraco Jul 19, 2024
d48a881
In test_convert_path, utilize posixpath.join and ntpath.join for maxi…
jaraco Jul 19, 2024
8eb6b57
Wrap paths in PurePosixPath to ensure that any WindowsPaths don't get…
jaraco Jul 19, 2024
4232b01
convert_path no longer fails if passed a path with a trailing slash. …
jaraco Jul 19, 2024
b4df774
convert_path now converts to a platform-native path.Path, but then ca…
jaraco Jul 20, 2024
c67da35
Separate test_convert_path into two tests to avoid interactions in mo…
jaraco Jul 20, 2024
1e97e21
Remove expectation that a ValueError is raised for data_files being d…
jaraco Jul 20, 2024
4b3f16f
Simplify convert_path by simply relying on the logic in PurePath.
jaraco Jul 20, 2024
c4d3c3c
Harmonize convert_path tests across Unix and Windows.
jaraco Jul 20, 2024
a166815
Consolidate convert_path tests and just generate the expected value i…
jaraco Jul 20, 2024
01f9af2
Merge pull request pypa/distutils#272 from pypa/feature/pathlib-data-…
jaraco Jul 20, 2024
c9ec8f8
Merge branch 'main' into pathlike_ext
jaraco Jul 20, 2024
a74d289
Use simple import
jaraco Jul 20, 2024
e1e9f61
Merge pull request pypa/distutils#237 from pypa/pathlike_ext
jaraco Jul 20, 2024
cf47197
venv_install_options: add missing clear_argv fixture
lazka Jul 21, 2024
6a39d04
CI: add a job for running tests under MSVC CPython with GCC as the de…
lazka Jul 21, 2024
943fc82
mingw: make get_msvcr() a noop
lazka Jul 21, 2024
267fb5f
Remove unused RangeMap
lazka Jul 21, 2024
93ab2a5
Merge branch 'main' into feature/cpp-support
jaraco Aug 2, 2024
95088c5
Harmonize '-shared' parameter for C and C++ in Mingw32CCompiler
jaraco Aug 2, 2024
edc3808
In sysconfig.customize_compiler, initialize ldcxxshared from config v…
jaraco Aug 2, 2024
3e4b457
Refactored customize_compiler to reduce logical branches and extract …
jaraco Aug 2, 2024
fcef963
Don't add flags when the value is None, such as when on PyPy, LDCXXSH…
jaraco Aug 2, 2024
3e11381
Merge pull request pypa/distutils#228 from pypa/feature/cpp-support
jaraco Aug 2, 2024
ab3f84e
Merge pull request pypa/distutils#273 from msys2-contrib/tests-fix-ve…
jaraco Aug 2, 2024
de4e1be
Merge pull request pypa/distutils#274 from msys2-contrib/ci-msvc-pyth…
jaraco Aug 2, 2024
c9781ae
Rely on monkeysession to monkeypatch.
jaraco Aug 2, 2024
d7ffdb9
Apply isort. Ref pypa/distutils#240
jaraco Aug 2, 2024
c22938c
Merge https://github.com/pypa/distutils
jaraco Aug 2, 2024
3fc3c6f
Add news fragment.
jaraco Aug 2, 2024
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 newsfragments/4538.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Merged with distutils@d7ffdb9c7 including: Support for Pathlike objects in data files and extensions (pypa/distutils#272, pypa/distutils#237), native support for C++ compilers (pypa/distuils#228) and removed unused get_msvcr() (pypa/distutils#274).
145 changes: 0 additions & 145 deletions setuptools/_distutils/_collections.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from __future__ import annotations

import collections
import functools
import itertools
import operator
from collections.abc import Mapping
from typing import Any


# from jaraco.collections 3.5.1
Expand Down Expand Up @@ -60,144 +56,3 @@ def __contains__(self, other):

def __len__(self):
return len(list(iter(self)))


# from jaraco.collections 5.0.1
class RangeMap(dict):
"""
A dictionary-like object that uses the keys as bounds for a range.
Inclusion of the value for that range is determined by the
key_match_comparator, which defaults to less-than-or-equal.
A value is returned for a key if it is the first key that matches in
the sorted list of keys.

One may supply keyword parameters to be passed to the sort function used
to sort keys (i.e. key, reverse) as sort_params.

Create a map that maps 1-3 -> 'a', 4-6 -> 'b'

>>> r = RangeMap({3: 'a', 6: 'b'}) # boy, that was easy
>>> r[1], r[2], r[3], r[4], r[5], r[6]
('a', 'a', 'a', 'b', 'b', 'b')

Even float values should work so long as the comparison operator
supports it.

>>> r[4.5]
'b'

Notice that the way rangemap is defined, it must be open-ended
on one side.

>>> r[0]
'a'
>>> r[-1]
'a'

One can close the open-end of the RangeMap by using undefined_value

>>> r = RangeMap({0: RangeMap.undefined_value, 3: 'a', 6: 'b'})
>>> r[0]
Traceback (most recent call last):
...
KeyError: 0

One can get the first or last elements in the range by using RangeMap.Item

>>> last_item = RangeMap.Item(-1)
>>> r[last_item]
'b'

.last_item is a shortcut for Item(-1)

>>> r[RangeMap.last_item]
'b'

Sometimes it's useful to find the bounds for a RangeMap

>>> r.bounds()
(0, 6)

RangeMap supports .get(key, default)

>>> r.get(0, 'not found')
'not found'

>>> r.get(7, 'not found')
'not found'

One often wishes to define the ranges by their left-most values,
which requires use of sort params and a key_match_comparator.

>>> r = RangeMap({1: 'a', 4: 'b'},
... sort_params=dict(reverse=True),
... key_match_comparator=operator.ge)
>>> r[1], r[2], r[3], r[4], r[5], r[6]
('a', 'a', 'a', 'b', 'b', 'b')

That wasn't nearly as easy as before, so an alternate constructor
is provided:

>>> r = RangeMap.left({1: 'a', 4: 'b', 7: RangeMap.undefined_value})
>>> r[1], r[2], r[3], r[4], r[5], r[6]
('a', 'a', 'a', 'b', 'b', 'b')

"""

def __init__(
self,
source,
sort_params: Mapping[str, Any] = {},
key_match_comparator=operator.le,
):
dict.__init__(self, source)
self.sort_params = sort_params
self.match = key_match_comparator

@classmethod
def left(cls, source):
return cls(
source, sort_params=dict(reverse=True), key_match_comparator=operator.ge
)

def __getitem__(self, item):
sorted_keys = sorted(self.keys(), **self.sort_params)
if isinstance(item, RangeMap.Item):
result = self.__getitem__(sorted_keys[item])
else:
key = self._find_first_match_(sorted_keys, item)
result = dict.__getitem__(self, key)
if result is RangeMap.undefined_value:
raise KeyError(key)
return result

def get(self, key, default=None):
"""
Return the value for key if key is in the dictionary, else default.
If default is not given, it defaults to None, so that this method
never raises a KeyError.
"""
try:
return self[key]
except KeyError:
return default

def _find_first_match_(self, keys, item):
is_match = functools.partial(self.match, item)
matches = list(filter(is_match, keys))
if matches:
return matches[0]
raise KeyError(item)

def bounds(self):
sorted_keys = sorted(self.keys(), **self.sort_params)
return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item])

# some special values for the RangeMap
undefined_value = type('RangeValueUndefined', (), {})()

class Item(int):
"RangeMap Item"

first_item = Item(0)
last_item = Item(-1)
3 changes: 1 addition & 2 deletions setuptools/_distutils/bcppcompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,7 @@ def link( # noqa: C901
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
def_file = os.path.join(temp_dir, f'{modname}.def')
contents = ['EXPORTS']
for sym in export_symbols or []:
contents.append(f' {sym}=_{sym}')
contents.extend(f' {sym}=_{sym}' for sym in export_symbols)
self.execute(write_file, (def_file, contents), f"writing {def_file}")

# Borland C++ has problems with '/' in paths
Expand Down
18 changes: 7 additions & 11 deletions setuptools/_distutils/ccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
)
from .file_util import move_file
from .spawn import spawn
from .util import execute, split_quoted, is_mingw
from .util import execute, is_mingw, split_quoted


class CCompiler:
Expand Down Expand Up @@ -1124,10 +1124,10 @@ def show_compilers():
# commands that use it.
from distutils.fancy_getopt import FancyGetopt

compilers = []
for compiler in compiler_class.keys():
compilers.append(("compiler=" + compiler, None, compiler_class[compiler][2]))
compilers.sort()
compilers = sorted(
("compiler=" + compiler, None, compiler_class[compiler][2])
for compiler in compiler_class.keys()
)
pretty_printer = FancyGetopt(compilers)
pretty_printer.print_help("List of available compilers:")

Expand Down Expand Up @@ -1218,8 +1218,7 @@ def gen_preprocess_options(macros, include_dirs):
# shell at all costs when we spawn the command!
pp_opts.append("-D{}={}".format(*macro))

for dir in include_dirs:
pp_opts.append(f"-I{dir}")
pp_opts.extend(f"-I{dir}" for dir in include_dirs)
return pp_opts


Expand All @@ -1230,10 +1229,7 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
directories. Returns a list of command-line options suitable for use
with some compiler (depending on the two format strings passed in).
"""
lib_opts = []

for dir in library_dirs:
lib_opts.append(compiler.library_dir_option(dir))
lib_opts = [compiler.library_dir_option(dir) for dir in library_dirs]

for dir in runtime_library_dirs:
lib_opts.extend(always_iterable(compiler.runtime_library_dir_option(dir)))
Expand Down
7 changes: 4 additions & 3 deletions setuptools/_distutils/command/bdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ def show_formats():
"""Print list of available formats (arguments to "--format" option)."""
from ..fancy_getopt import FancyGetopt

formats = []
for format in bdist.format_commands:
formats.append(("formats=" + format, None, bdist.format_commands[format][1]))
formats = [
("formats=" + format, None, bdist.format_commands[format][1])
for format in bdist.format_commands
]
pretty_printer = FancyGetopt(formats)
pretty_printer.print_help("List of available distribution formats:")

Expand Down
5 changes: 1 addition & 4 deletions setuptools/_distutils/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,7 @@ def get_outputs(self):
# And build the list of output (built) filenames. Note that this
# ignores the 'inplace' flag, and assumes everything goes in the
# "build" tree.
outputs = []
for ext in self.extensions:
outputs.append(self.get_ext_fullpath(ext.name))
return outputs
return [self.get_ext_fullpath(ext.name) for ext in self.extensions]

def build_extensions(self):
# First, sanity-check the 'extensions' list
Expand Down
7 changes: 3 additions & 4 deletions setuptools/_distutils/command/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ def check_metadata(self):
"""
metadata = self.distribution.metadata

missing = []
for attr in 'name', 'version':
if not getattr(metadata, attr, None):
missing.append(attr)
missing = [
attr for attr in ('name', 'version') if not getattr(metadata, attr, None)
]

if missing:
self.warn("missing required meta-data: {}".format(', '.join(missing)))
Expand Down
68 changes: 39 additions & 29 deletions setuptools/_distutils/command/install_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

# contributed by Bastian Kleineidam

from __future__ import annotations

import functools
import os
from typing import Iterable

from ..core import Command
from ..util import change_root, convert_path
Expand Down Expand Up @@ -46,36 +50,42 @@ def finalize_options(self):
def run(self):
self.mkpath(self.install_dir)
for f in self.data_files:
if isinstance(f, str):
# it's a simple file, so copy it
f = convert_path(f)
if self.warn_dir:
self.warn(
"setup script did not provide a directory for "
f"'{f}' -- installing right in '{self.install_dir}'"
)
(out, _) = self.copy_file(f, self.install_dir)
self._copy(f)

@functools.singledispatchmethod
def _copy(self, f: tuple[str | os.PathLike, Iterable[str | os.PathLike]]):
# it's a tuple with path to install to and a list of files
dir = convert_path(f[0])
if not os.path.isabs(dir):
dir = os.path.join(self.install_dir, dir)
elif self.root:
dir = change_root(self.root, dir)
self.mkpath(dir)

if f[1] == []:
# If there are no files listed, the user must be
# trying to create an empty directory, so add the
# directory to the list of output files.
self.outfiles.append(dir)
else:
# Copy files, adding them to the list of output files.
for data in f[1]:
data = convert_path(data)
(out, _) = self.copy_file(data, dir)
self.outfiles.append(out)
else:
# it's a tuple with path to install to and a list of files
dir = convert_path(f[0])
if not os.path.isabs(dir):
dir = os.path.join(self.install_dir, dir)
elif self.root:
dir = change_root(self.root, dir)
self.mkpath(dir)

if f[1] == []:
# If there are no files listed, the user must be
# trying to create an empty directory, so add the
# directory to the list of output files.
self.outfiles.append(dir)
else:
# Copy files, adding them to the list of output files.
for data in f[1]:
data = convert_path(data)
(out, _) = self.copy_file(data, dir)
self.outfiles.append(out)

@_copy.register(str)
@_copy.register(os.PathLike)
def _(self, f: str | os.PathLike):
# it's a simple file, so copy it
f = convert_path(f)
if self.warn_dir:
self.warn(
"setup script did not provide a directory for "
f"'{f}' -- installing right in '{self.install_dir}'"
)
(out, _) = self.copy_file(f, self.install_dir)
self.outfiles.append(out)

def get_inputs(self):
return self.data_files or []
Expand Down
4 changes: 1 addition & 3 deletions setuptools/_distutils/command/install_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,7 @@ def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
build_dir = getattr(build_cmd, cmd_option)

prefix_len = len(build_dir) + len(os.sep)
outputs = []
for file in build_files:
outputs.append(os.path.join(output_dir, file[prefix_len:]))
outputs = [os.path.join(output_dir, file[prefix_len:]) for file in build_files]

return outputs

Expand Down
8 changes: 4 additions & 4 deletions setuptools/_distutils/command/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ def show_formats():
from ..archive_util import ARCHIVE_FORMATS
from ..fancy_getopt import FancyGetopt

formats = []
for format in ARCHIVE_FORMATS.keys():
formats.append(("formats=" + format, None, ARCHIVE_FORMATS[format][2]))
formats.sort()
formats = sorted(
("formats=" + format, None, ARCHIVE_FORMATS[format][2])
for format in ARCHIVE_FORMATS.keys()
)
FancyGetopt(formats).print_help("List of available source distribution formats:")


Expand Down
1 change: 1 addition & 0 deletions setuptools/_distutils/compat/py38.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def removeprefix(self, prefix):
return self[len(prefix) :]
else:
return self[:]

else:

def removesuffix(self, suffix):
Expand Down
Loading
Loading