Skip to content

Commit fed800d

Browse files
committed
Sync pep517_backend w/ YARL
1 parent 23f54da commit fed800d

File tree

7 files changed

+109
-75
lines changed

7 files changed

+109
-75
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"""PEP 517 build backend package pre-building Cython exts before setuptools."""
1+
"""PEP 517 build backend for optionally pre-building Cython."""

packaging/pep517_backend/_backend.py

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
"""PEP 517 build backend pre-building Cython exts before setuptools."""
1+
"""PEP 517 build backend wrapper for pre-building Cython for wheel."""
22

33
from __future__ import annotations
44

55
import os
6-
import typing as t # noqa: WPS111
7-
from contextlib import contextmanager, suppress
6+
import typing as _t # noqa: WPS111
7+
from contextlib import contextmanager, nullcontext, suppress
88
from functools import partial
99
from pathlib import Path
1010
from shutil import copytree
@@ -24,7 +24,7 @@
2424
build_editable as _setuptools_build_editable,
2525
)
2626
except ImportError:
27-
_setuptools_build_editable = None
27+
_setuptools_build_editable = None # type: ignore[assignment]
2828

2929

3030
# isort: split
@@ -44,7 +44,7 @@
4444
main as _cythonize_cli_cmd,
4545
)
4646

47-
from ._compat import chdir_cm, nullcontext_cm
47+
from ._compat import chdir_cm
4848
from ._cython_configuration import (
4949
get_local_cythonize_config as _get_local_cython_config,
5050
make_cythonize_cli_args_from_config as _make_cythonize_cli_args_from_config,
@@ -53,14 +53,18 @@
5353
from ._transformers import sanitize_rst_roles
5454

5555

56+
if _t.TYPE_CHECKING:
57+
import collections.abc as _c # noqa: WPS111, WPS301
58+
59+
5660
__all__ = ( # noqa: PLE0604, WPS410
5761
'build_sdist',
5862
'build_wheel',
5963
'get_requires_for_build_wheel',
6064
'prepare_metadata_for_build_wheel',
6165
*(
6266
()
63-
if _setuptools_build_editable is None
67+
if _setuptools_build_editable is None # type: ignore[redundant-expr]
6468
else (
6569
'build_editable',
6670
'get_requires_for_build_editable',
@@ -70,6 +74,9 @@
7074
)
7175

7276

77+
_ConfigDict = dict[str, str | list[str] | None]
78+
79+
7380
CYTHON_TRACING_CONFIG_SETTING = 'with-cython-tracing' # noqa: WPS462
7481
"""
7582
Config setting name toggle to include line tracing to C-exts.
@@ -87,7 +94,7 @@ def _is_truthy_setting_value(setting_value: str) -> bool:
8794

8895

8996
def _get_setting_value(
90-
config_settings: dict[str, str] | None = None,
97+
config_settings: _ConfigDict | None = None,
9198
config_setting_name: str | None = None,
9299
env_var_name: str | None = None,
93100
*,
@@ -102,15 +109,15 @@ def _get_setting_value(
102109
continue
103110

104111
with suppress(lookup_errors): # type: ignore[arg-type]
105-
return _is_truthy_setting_value(src_mapping[src_key]) # type: ignore[index]
112+
return _is_truthy_setting_value(src_mapping[src_key]) # type: ignore[arg-type,index]
106113

107114
return default
108115

109116

110117
def _include_cython_line_tracing(
111-
config_settings: dict[str, str] | None = None,
118+
config_settings: _ConfigDict | None = None,
112119
*,
113-
default=False,
120+
default: bool = False,
114121
) -> bool:
115122
return _get_setting_value(
116123
config_settings,
@@ -121,60 +128,65 @@ def _include_cython_line_tracing(
121128

122129

123130
@contextmanager
124-
def patched_distutils_cmd_install():
131+
def patched_distutils_cmd_install() -> _c.Iterator[None]:
125132
"""Make `install_lib` of `install` cmd always use `platlib`.
126133
127134
:yields: None
128135
"""
129136
# Without this, build_lib puts stuff under `*.data/purelib/` folder
130137
orig_finalize = _distutils_install_cmd.finalize_options
131138

132-
def new_finalize_options(self): # noqa: WPS430
139+
def new_finalize_options( # noqa: WPS430
140+
self: _distutils_install_cmd,
141+
) -> None:
133142
self.install_lib = self.install_platlib
134143
orig_finalize(self)
135144

136-
_distutils_install_cmd.finalize_options = new_finalize_options
145+
_distutils_install_cmd.finalize_options = new_finalize_options # type: ignore[method-assign]
137146
try: # noqa: WPS501
138147
yield
139148
finally:
140-
_distutils_install_cmd.finalize_options = orig_finalize
149+
_distutils_install_cmd.finalize_options = orig_finalize # type: ignore[method-assign]
141150

142151

143152
@contextmanager
144-
def patched_dist_has_ext_modules():
153+
def patched_dist_has_ext_modules() -> _c.Iterator[None]:
145154
"""Make `has_ext_modules` of `Distribution` always return `True`.
146155
147156
:yields: None
148157
"""
149158
# Without this, build_lib puts stuff under `*.data/platlib/` folder
150159
orig_func = _DistutilsDistribution.has_ext_modules
151160

152-
_DistutilsDistribution.has_ext_modules = lambda *_args, **_kwargs: True
161+
_DistutilsDistribution.has_ext_modules = lambda *_args, **_kwargs: True # type: ignore[method-assign]
153162
try: # noqa: WPS501
154163
yield
155164
finally:
156-
_DistutilsDistribution.has_ext_modules = orig_func
165+
_DistutilsDistribution.has_ext_modules = orig_func # type: ignore[method-assign]
157166

158167

159168
@contextmanager
160-
def patched_dist_get_long_description():
169+
def patched_dist_get_long_description() -> _c.Iterator[None]:
161170
"""Make `has_ext_modules` of `Distribution` always return `True`.
162171
163172
:yields: None
164173
"""
165174
# Without this, build_lib puts stuff under `*.data/platlib/` folder
166175
orig_func = _DistutilsDistributionMetadata.get_long_description
167176

168-
def _get_sanitized_long_description(self): # noqa: WPS430
177+
def _get_sanitized_long_description( # noqa: WPS430
178+
self: _DistutilsDistributionMetadata,
179+
) -> str:
180+
assert self.long_description is not None # noqa: S101 # typing
169181
return sanitize_rst_roles(self.long_description)
170182

171-
_DistutilsDistributionMetadata.get_long_description = (
183+
_DistutilsDistributionMetadata.get_long_description = ( # type: ignore[method-assign]
172184
_get_sanitized_long_description
173185
)
174186
try:
175187
yield
176188
finally:
177-
_DistutilsDistributionMetadata.get_long_description = orig_func
189+
_DistutilsDistributionMetadata.get_long_description = orig_func # type: ignore[method-assign]
178190

179191

180192
def _exclude_dir_path(
@@ -201,7 +213,7 @@ def _exclude_dir_path(
201213

202214

203215
@contextmanager
204-
def _in_temporary_directory(src_dir: Path) -> t.Iterator[None]:
216+
def _in_temporary_directory(src_dir: Path) -> _c.Iterator[None]:
205217
with TemporaryDirectory(prefix='.tmp-ansible-pylibssh-pep517-') as tmp_dir:
206218
tmp_dir_path = Path(tmp_dir)
207219
root_tmp_dir_path = tmp_dir_path.parent
@@ -224,8 +236,8 @@ def _prebuild_c_extensions(
224236
*,
225237
line_trace_cython_when_unset: bool = False,
226238
build_inplace: bool = False,
227-
config_settings: dict[str, str] | None = None,
228-
) -> t.Generator[None, t.Any, t.Any]:
239+
config_settings: _ConfigDict | None = None,
240+
) -> _c.Iterator[None]:
229241
"""Pre-build C-extensions in a temporary directory, when needed.
230242
231243
This context manager also patches metadata, setuptools and distutils.
@@ -240,19 +252,21 @@ def _prebuild_c_extensions(
240252
)
241253

242254
build_dir_ctx = (
243-
nullcontext_cm()
255+
nullcontext()
244256
if build_inplace
245257
else _in_temporary_directory(src_dir=Path.cwd().resolve())
246258
)
247259
with build_dir_ctx:
248260
config = _get_local_cython_config()
249261

250-
cythonize_args = _make_cythonize_cli_args_from_config(config)
262+
cythonize_args = _make_cythonize_cli_args_from_config(
263+
config,
264+
)
251265
with _patched_cython_env(
252266
config['env'],
253267
cython_line_tracing_requested=cython_line_tracing_requested,
254268
):
255-
_cythonize_cli_cmd(cythonize_args)
269+
_cythonize_cli_cmd(cythonize_args) # type: ignore[no-untyped-call]
256270
with patched_distutils_cmd_install():
257271
with patched_dist_has_ext_modules():
258272
yield
@@ -261,7 +275,7 @@ def _prebuild_c_extensions(
261275
@patched_dist_get_long_description()
262276
def build_wheel(
263277
wheel_directory: str,
264-
config_settings: dict[str, str] | None = None,
278+
config_settings: _ConfigDict | None = None,
265279
metadata_directory: str | None = None,
266280
) -> str:
267281
"""Produce a built wheel.
@@ -288,7 +302,7 @@ def build_wheel(
288302
@patched_dist_get_long_description()
289303
def build_editable(
290304
wheel_directory: str,
291-
config_settings: dict[str, str] | None = None,
305+
config_settings: _ConfigDict | None = None,
292306
metadata_directory: str | None = None,
293307
) -> str:
294308
"""Produce a built wheel for editable installs.
@@ -313,7 +327,7 @@ def build_editable(
313327

314328

315329
def get_requires_for_build_wheel(
316-
config_settings: dict[str, str] | None = None,
330+
config_settings: _ConfigDict | None = None,
317331
) -> list[str]:
318332
"""Determine additional requirements for building wheels.
319333
Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
"""Cross-interpreter compatibility shims."""
1+
"""Cross-python stdlib shims."""
22

3+
import collections.abc as _c # noqa: WPS111, WPS301
34
import os
4-
import typing as t # noqa: WPS111
5+
import sys
56
from contextlib import contextmanager
67
from pathlib import Path
78

89

9-
try:
10+
if sys.version_info >= (3, 11):
1011
from contextlib import chdir as chdir_cm
11-
except ImportError:
12+
13+
from tomllib import loads as load_toml_from_string
14+
else:
15+
from tomli import loads as load_toml_from_string
1216

1317
@contextmanager # type: ignore[no-redef]
14-
def chdir_cm(path: os.PathLike) -> t.Iterator[None]:
18+
def chdir_cm(path: 'os.PathLike[str]') -> _c.Iterator[None]:
1519
"""Temporarily change the current directory, recovering on exit."""
1620
original_wd = Path.cwd()
1721
os.chdir(path)
@@ -21,29 +25,7 @@ def chdir_cm(path: os.PathLike) -> t.Iterator[None]:
2125
os.chdir(original_wd)
2226

2327

24-
try:
25-
from contextlib import nullcontext as nullcontext_cm # noqa: F401
26-
except ImportError:
27-
28-
@contextmanager # type: ignore[no-redef]
29-
def nullcontext_cm(enter_result: t.Any = None) -> t.Iterator[t.Any]:
30-
"""Emit the incoming value.
31-
32-
A no-op context manager.
33-
"""
34-
yield enter_result
35-
36-
37-
try:
38-
# Python 3.11+
39-
from tomllib import loads as load_toml_from_string
40-
except ImportError:
41-
# before Python 3.11
42-
from tomli import loads as load_toml_from_string
43-
44-
4528
__all__ = ( # noqa: WPS410
4629
'chdir_cm',
4730
'load_toml_from_string',
48-
'nullcontext_cm',
4931
)

packaging/pep517_backend/_cython_configuration.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import os
6+
import typing as _t # noqa: WPS111
67
from contextlib import contextmanager
78
from pathlib import Path
89
from sys import version_info as _python_version_tuple
@@ -16,7 +17,20 @@
1617
)
1718

1819

19-
def get_local_cython_config() -> dict:
20+
if _t.TYPE_CHECKING:
21+
import collections.abc as _c # noqa: WPS111, WPS301
22+
23+
24+
class Config(_t.TypedDict):
25+
"""Data structure for the TOML config."""
26+
27+
env: dict[str, str]
28+
flags: dict[str, bool]
29+
kwargs: dict[str, str | dict[str, str]]
30+
src: list[str]
31+
32+
33+
def get_local_cython_config() -> Config:
2034
"""Grab optional build dependencies from pyproject.toml config.
2135
2236
:returns: config section from ``pyproject.toml``
@@ -70,10 +84,10 @@ def get_local_cython_config() -> dict:
7084
"""
7185
config_toml_txt = (Path.cwd().resolve() / 'pyproject.toml').read_text()
7286
config_mapping = load_toml_from_string(config_toml_txt)
73-
return config_mapping['tool']['local']['cython']
87+
return config_mapping['tool']['local']['cython'] # type: ignore[no-any-return]
7488

7589

76-
def get_local_cythonize_config() -> dict:
90+
def get_local_cythonize_config() -> Config:
7791
"""Grab optional build dependencies from pyproject.toml config.
7892
7993
:returns: config section from ``pyproject.toml``
@@ -127,10 +141,12 @@ def get_local_cythonize_config() -> dict:
127141
"""
128142
config_toml_txt = (Path.cwd().resolve() / 'pyproject.toml').read_text()
129143
config_mapping = load_toml_from_string(config_toml_txt)
130-
return config_mapping['tool']['local']['cythonize']
144+
return config_mapping['tool']['local']['cythonize'] # type: ignore[no-any-return]
131145

132146

133-
def make_cythonize_cli_args_from_config(config: dict) -> list[str]:
147+
def make_cythonize_cli_args_from_config(
148+
config: Config,
149+
) -> list[str]:
134150
"""Compose ``cythonize`` CLI args from config."""
135151
py_ver_arg = f'-{_python_version_tuple.major!s}'
136152

@@ -141,7 +157,11 @@ def make_cythonize_cli_args_from_config(config: dict) -> list[str]:
141157

142158

143159
@contextmanager
144-
def patched_env(env: dict[str, str], *, cython_line_tracing_requested: bool):
160+
def patched_env(
161+
env: dict[str, str],
162+
*,
163+
cython_line_tracing_requested: bool,
164+
) -> _c.Iterator[None]:
145165
"""Temporary set given env vars.
146166
147167
:param env: tmp env vars to set
@@ -150,7 +170,7 @@ def patched_env(env: dict[str, str], *, cython_line_tracing_requested: bool):
150170
:yields: None
151171
"""
152172
orig_env = os.environ.copy()
153-
expanded_env = {name: expandvars(var_val) for name, var_val in env.items()}
173+
expanded_env = {name: expandvars(var_val) for name, var_val in env.items()} # type: ignore[no-untyped-call]
154174
os.environ.update(expanded_env)
155175

156176
if cython_line_tracing_requested:

0 commit comments

Comments
 (0)