Skip to content

Do not capture DeprecationWarning and PendingDeprecationWarning by default. #277

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

Merged
merged 3 commits into from
May 22, 2022
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
3 changes: 3 additions & 0 deletions docs/source/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ releases are available on [PyPI](https://pypi.org/project/pytask) and
## 0.2.3 - 2022-xx-xx

- {pull}`276` fixes `pytask clean` when git is not installed. Fixes {issue}`275`.
- {pull}`277` ignores `DeprecationWarning` and `PendingDeprecationWarning` by default.
Previously, they were enabled, but they should be shown when testing the project with
pytest, not after the execution with pytask. Fixes {issue}`269`.

## 0.2.2 - 2022-05-14

Expand Down
22 changes: 0 additions & 22 deletions docs/source/how_to_guides/capture_warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,6 @@ configured by the `filterwarnings` configuration option.
Although not recommended, you can use the `--disable-warnings` command-line option to
suppress the warning summary entirely from the test run output.

## `DeprecationWarning` and `PendingDeprecationWarning`

By default pytask will display `DeprecationWarning` and `PendingDeprecationWarning`
warnings from user code and third-party libraries. This helps users keep their code
modern and avoid breakages when deprecated warnings are effectively removed.

Sometimes it is useful to hide some specific deprecation warnings that happen in code
that you have no control over (such as third-party libraries), in which case you might
use the warning filters options (ini or marks) to ignore those warnings.

For example:

```toml
[tool.pytask.ini_options]
filterwarnings = [
"ignore:.*U.*mode is deprecated:DeprecationWarning"
]
```

This will ignore all warnings of type `DeprecationWarning` where the start of the
message matches the regular expression `".*U.*mode is deprecated"`.

## Debugging warnings

Sometimes it is not clear which line of code triggered a warning. To find the location,
Expand Down
4 changes: 2 additions & 2 deletions src/_pytask/collect_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def _find_common_ancestor_of_all_nodes(
for task in tasks:
all_paths.append(task.path)
if show_nodes:
all_paths.extend(map(lambda x: x.path, tree_just_flatten(task.depends_on)))
all_paths.extend(map(lambda x: x.path, tree_just_flatten(task.produces)))
all_paths.extend(x.path for x in tree_just_flatten(task.depends_on))
all_paths.extend(x.path for x in tree_just_flatten(task.produces))

common_ancestor = find_common_ancestor(*all_paths, *paths)

Expand Down
7 changes: 0 additions & 7 deletions src/_pytask/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import functools
import re
import sys
import textwrap
import warnings
from collections import defaultdict
Expand Down Expand Up @@ -90,12 +89,6 @@ def catch_warnings_for_item(
# mypy can't infer that record=True means log is not None; help it.
assert log is not None

if not sys.warnoptions:
# If user is not explicitly configuring warning filters, show deprecation
# warnings by default (#2908).
warnings.filterwarnings("always", category=DeprecationWarning)
warnings.filterwarnings("always", category=PendingDeprecationWarning)

for arg in session.config["filterwarnings"]:
warnings.filterwarnings(*parse_warning_filter(arg, escape=False))

Expand Down
36 changes: 36 additions & 0 deletions tests/test_warnings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import subprocess
import textwrap

import pytest
Expand Down Expand Up @@ -119,3 +120,38 @@ def task_example():
assert result.exit_code == ExitCode.OK
assert ("Warnings" in result.output) is not add_config
assert ("warning!!!" in result.output) is not add_config


@pytest.mark.parametrize("warning", ["DeprecationWarning", "PendingDeprecationWarning"])
def test_deprecation_warnings_are_not_captured(tmp_path, warning):
path_to_warn_module = tmp_path.joinpath("warning.py")
source = """
import importlib.util
import sys
from pathlib import Path

def task_example():
spec = importlib.util.spec_from_file_location(
"warning", Path(__file__).parent / "warning.py"
)
warning_module = importlib.util.module_from_spec(spec)
sys.modules["warning"] = warning_module
spec.loader.exec_module(warning_module)
warning_module.warn_now()
"""
tmp_path.joinpath("task_example.py").write_text(textwrap.dedent(source))

warn_module = f"""
import warnings

def warn_now():
warnings.warn("warning!!!", {warning})
"""
path_to_warn_module.write_text(textwrap.dedent(warn_module))

# Cannot use runner since then warnings are not ignored by default.
result = subprocess.run(("pytask"), cwd=tmp_path, capture_output=True)

assert result.returncode == ExitCode.OK
assert "Warnings" not in result.stdout.decode()
assert "warning!!!" not in result.stdout.decode()