|
| 1 | +# Capture warnings |
| 2 | + |
| 3 | +pytask captures warnings during the execution. |
| 4 | + |
| 5 | +Here is an example with the most infamous warning in the world of scientific Python. |
| 6 | + |
| 7 | +```python |
| 8 | +import pandas as pd |
| 9 | +import pytask |
| 10 | + |
| 11 | + |
| 12 | +def _create_df(): |
| 13 | + df = pd.DataFrame({"a": range(10), "b": range(10, 20)}) |
| 14 | + df[df["a"] < 5]["b"] = 1 |
| 15 | + return df |
| 16 | + |
| 17 | + |
| 18 | +@pytask.mark.products("df.pkl") |
| 19 | +def task_warning(produces): |
| 20 | + df = _create_df() |
| 21 | + df.to_pickle(produces) |
| 22 | +``` |
| 23 | + |
| 24 | +Running pytask produces |
| 25 | + |
| 26 | +```{image} /_static/images/warning.svg |
| 27 | +``` |
| 28 | + |
| 29 | +## Controlling warnings |
| 30 | + |
| 31 | +You can use the `filterwarnings` option in `pyproject.toml` to configure pytasks |
| 32 | +behavior to warnings. For example, the configuration below will ignore all user warnings |
| 33 | +and specific deprecation warnings matching a regex, but will transform all other |
| 34 | +warnings into errors. |
| 35 | + |
| 36 | +```toml |
| 37 | +[tool.pytask.ini_options] |
| 38 | +filterwarnings = [ |
| 39 | + "error", |
| 40 | + "ignore::UserWarning", |
| 41 | + # note the use of single quote below to denote "raw" strings in TOML |
| 42 | + 'ignore:function ham\(\) is deprecated:DeprecationWarning', |
| 43 | +] |
| 44 | +``` |
| 45 | + |
| 46 | +When a warning matches more than one option in the list, the action for the last |
| 47 | +matching option is performed. |
| 48 | + |
| 49 | +## `@pytask.mark.filterwarnings` |
| 50 | + |
| 51 | +You can use the `@pytask.mark.filterwarnings` to add warning filters to specific test |
| 52 | +items, allowing you to have finer control of which warnings should be captured at test, |
| 53 | +class or even module level: |
| 54 | + |
| 55 | +```python |
| 56 | +import pandas as pd |
| 57 | +import pytask |
| 58 | + |
| 59 | + |
| 60 | +def _create_df(): |
| 61 | + df = pd.DataFrame({"a": range(10), "b": range(10, 20)}) |
| 62 | + df[df["a"] < 5]["b"] = 1 |
| 63 | + return df |
| 64 | + |
| 65 | + |
| 66 | +@pytask.mark.filterwarnings("ignore:.*:SettingWithCopyWarning") |
| 67 | +@pytask.mark.products("df.pkl") |
| 68 | +def task_warning(produces): |
| 69 | + df = _create_df() |
| 70 | + df.to_pickle(produces) |
| 71 | +``` |
| 72 | + |
| 73 | +Filters applied using a mark take precedence over filters passed on the command line or |
| 74 | +configured by the `filterwarnings` configuration option. |
| 75 | + |
| 76 | +## Disabling warnings summary |
| 77 | + |
| 78 | +Although not recommended, you can use the `--disable-warnings` command-line option to |
| 79 | +suppress the warning summary entirely from the test run output. |
| 80 | + |
| 81 | +## `DeprecationWarning` and `PendingDeprecationWarning` |
| 82 | + |
| 83 | +By default pytask will display `DeprecationWarning` and `PendingDeprecationWarning` |
| 84 | +warnings from user code and third-party libraries. This helps users keep their code |
| 85 | +modern and avoid breakages when deprecated warnings are effectively removed. |
| 86 | + |
| 87 | +Sometimes it is useful to hide some specific deprecation warnings that happen in code |
| 88 | +that you have no control over (such as third-party libraries), in which case you might |
| 89 | +use the warning filters options (ini or marks) to ignore those warnings. |
| 90 | + |
| 91 | +For example: |
| 92 | + |
| 93 | +```toml |
| 94 | +[tool.pytask.ini_options] |
| 95 | +filterwarnings = [ |
| 96 | + "ignore:.*U.*mode is deprecated:DeprecationWarning" |
| 97 | +] |
| 98 | +``` |
| 99 | + |
| 100 | +This will ignore all warnings of type `DeprecationWarning` where the start of the |
| 101 | +message matches the regular expression `".*U.*mode is deprecated"`. |
| 102 | + |
| 103 | +## Debugging warnings |
| 104 | + |
| 105 | +Sometimes it is not clear which line of code triggered a warning. To find the location, |
| 106 | +you can turn warnings into exceptions and then use the {option}`pytask build --pdb` flag |
| 107 | +to enter the debugger. |
| 108 | + |
| 109 | +You can use the configuration to convert warnings to errors by setting |
| 110 | + |
| 111 | +```toml |
| 112 | +[tool.pytask.ini_options] |
| 113 | +filterwarnings = ["error:.*"] |
| 114 | +``` |
| 115 | + |
| 116 | +and then run `pytask`. |
| 117 | + |
| 118 | +Or, you use a temporary environment variable. Here is an example for bash |
| 119 | + |
| 120 | +```console |
| 121 | +$ PYTHONWARNINGS=error pytask --pdb |
| 122 | +``` |
| 123 | + |
| 124 | +and here for Powershell |
| 125 | + |
| 126 | +```console |
| 127 | +$ $env:PYTHONWARNINGS = 'error' |
| 128 | +$ pytask |
| 129 | +$ Remove-Item env:\PYTHONWARNINGS |
| 130 | +``` |
0 commit comments