Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Aug 2, 2024
2 parents 54936c7 + b7ee725 commit 0ab156c
Show file tree
Hide file tree
Showing 31 changed files with 255 additions and 431 deletions.
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

0 comments on commit 0ab156c

Please sign in to comment.