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

📦 Add --with-cython-tracing build setting #963

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ jobs:
github.event_name == 'push'
&& contains(github.ref, 'refs/tags/')
)
&& '0'
|| '1'
&& 'false'
|| 'true'
}}

test:
Expand Down
11 changes: 3 additions & 8 deletions .github/workflows/reusable-build-wheel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,9 @@ jobs:
uses: pypa/cibuildwheel@v2.16.2
env:
CIBW_ARCHS_MACOS: x86_64 arm64 universal2
CIBW_ENVIRONMENT: >- # Cython line tracing for coverage collection
COLOR="yes"
FORCE_COLOR="1"
MYPY_FORCE_COLOR="1"
PIP_CONSTRAINT="requirements/cython.txt"
PRE_COMMIT_COLOR="always"
PY_COLORS="1"
YARL_CYTHON_TRACING="${{ inputs.cython-tracing }}"
CIBW_CONFIG_SETTINGS: >- # Cython line tracing for coverage collection
--pure-python=false
--with-cython-tracing=${{ inputs.cython-tracing }}

- name: Upload built artifacts for testing and publishing
uses: actions/upload-artifact@v3
Expand Down
16 changes: 16 additions & 0 deletions CHANGES/962.contrib.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
It is now possible to request line tracing in Cython builds using the
``--with-cython-tracing`` :pep:`517` config setting
-- :user:`webknjaz`.

This can be used in CI and development environment to measure coverage
on Cython modules, but is not normally useful to the end-users or
downstream packagers.

Here's a usage example:

.. code-block:: console

$ python -Im pip install . --with-cython-tracing=true

For editable installs, this setting is on by default. Otherwise, it's
off unless requested explicitly.
80 changes: 69 additions & 11 deletions packaging/pep517_backend/_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
)


CYTHON_TRACING_CONFIG_SETTING = '--with-cython-tracing'
"""Config setting name toggle to include line tracing to C-exts."""

CYTHON_TRACING_ENV_VAR = 'YARL_CYTHON_TRACING'
"""Environment variable name toggle used to opt out of making C-exts."""

PURE_PYTHON_CONFIG_SETTING = '--pure-python'
"""Config setting name toggle that is used to opt out of making C-exts."""

Expand All @@ -86,19 +92,52 @@
"""A fallback for `--pure-python` is not set."""


def _make_pure_python(config_settings: dict[str, str] | None = None) -> bool:
def _is_truthy_setting_value(setting_value) -> bool:
truthy_values = {'', None, 'true', '1', 'on'}
return setting_value.lower() in truthy_values


def _get_setting_value(
config_settings: dict[str, str] | None = None,
config_setting_name: str | None = None,
env_var_name: str | None = None,
*,
default: bool = False,
) -> bool:
user_provided_setting_sources = (
(config_settings, PURE_PYTHON_CONFIG_SETTING, (KeyError, TypeError)),
(os.environ, PURE_PYTHON_ENV_VAR, KeyError),
(config_settings, config_setting_name, (KeyError, TypeError)),
(os.environ, env_var_name, KeyError),
)
for src_mapping, src_key, lookup_errors in user_provided_setting_sources:
if src_key is None:
continue

with suppress(lookup_errors): # type: ignore[arg-type]
candidate_val = src_mapping[src_key].lower() # type: ignore[index]
return candidate_val in truthy_values
return _is_truthy_setting_value(src_mapping[src_key]) # type: ignore[index]

return default


return PURE_PYTHON_MODE_CLI_FALLBACK
def _make_pure_python(config_settings: dict[str, str] | None = None) -> bool:
return _get_setting_value(
config_settings,
PURE_PYTHON_CONFIG_SETTING,
PURE_PYTHON_ENV_VAR,
default=PURE_PYTHON_MODE_CLI_FALLBACK,
)


def _include_cython_line_tracing(
config_settings: dict[str, str] | None = None,
*,
default=False,
) -> bool:
return _get_setting_value(
config_settings,
CYTHON_TRACING_CONFIG_SETTING,
CYTHON_TRACING_ENV_VAR,
default=default,
)


def _get_local_cython_config():
Expand Down Expand Up @@ -216,7 +255,7 @@ def _get_sanitized_long_description(self):


@contextmanager
def patched_env(env):
def patched_env(env: dict[str, str], cython_line_tracing_requested: bool):
"""Temporary set given env vars.

:param env: tmp env vars to set
Expand All @@ -227,7 +266,8 @@ def patched_env(env):
orig_env = os.environ.copy()
expanded_env = {name: expandvars(var_val) for name, var_val in env.items()}
os.environ.update(expanded_env)
if os.getenv('YARL_CYTHON_TRACING') == '1':

if cython_line_tracing_requested:
os.environ['CFLAGS'] = ' '.join((
os.getenv('CFLAGS', ''),
'-DCYTHON_TRACE_NOGIL=1', # Implies CYTHON_TRACE=1
Expand All @@ -248,6 +288,7 @@ def _run_in_temporary_directory() -> t.Iterator[Path]:

@contextmanager
def maybe_prebuild_c_extensions( # noqa: WPS210
line_trace_cython_when_unset: bool = False,
build_inplace: bool = False,
config_settings: dict[str, str] | None = None,
) -> t.Generator[None, t.Any, t.Any]:
Expand All @@ -259,12 +300,27 @@ def maybe_prebuild_c_extensions( # noqa: WPS210
:param config_settings: :pep:`517` config settings mapping.

"""
cython_line_tracing_requested = _include_cython_line_tracing(
config_settings,
default=line_trace_cython_when_unset,
)
is_pure_python_build = _make_pure_python(config_settings)

if is_pure_python_build:
print("*********************", file=_standard_error_stream)
print("* Pure Python build *", file=_standard_error_stream)
print("*********************", file=_standard_error_stream)

if cython_line_tracing_requested:
_warn_that(
f'The `{CYTHON_TRACING_CONFIG_SETTING !s}` setting requesting '
'Cython line tracing is set, but building C-extensions is not. '
'This option will not have any effect for in the pure-python '
'build mode.',
RuntimeWarning,
stacklevel=999,
)

yield
return

Expand Down Expand Up @@ -299,7 +355,7 @@ def maybe_prebuild_c_extensions( # noqa: WPS210
cli_kwargs = get_cli_kwargs_from_config(config['kwargs'])

cythonize_args = cli_flags + [py_ver_arg] + cli_kwargs + config['src']
with patched_env(config['env']):
with patched_env(config['env'], cython_line_tracing_requested):
_cythonize_cli_cmd(cythonize_args)
with patched_distutils_cmd_install():
with patched_dist_has_ext_modules():
Expand All @@ -322,6 +378,7 @@ def build_wheel(

"""
with maybe_prebuild_c_extensions(
line_trace_cython_when_unset=False,
build_inplace=False,
config_settings=config_settings,
):
Expand All @@ -348,8 +405,9 @@ def build_editable(

"""
with maybe_prebuild_c_extensions(
build_inplace=True,
config_settings=config_settings,
line_trace_cython_when_unset=True,
build_inplace=True,
config_settings=config_settings,
):
return _setuptools_build_editable(
wheel_directory=wheel_directory,
Expand Down
Loading