Skip to content
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: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ and pytest's many contributors, this project would not have been possible. Thank
Citation
--------

If you rely on pytask to manage your research project, please cite it with
If you rely on pytask to manage your research project, please cite it with the following
key to help others to discover the tool.

.. code-block::

Expand Down
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ all releases are available on `PyPI <https://pypi.org/project/pytask>`_ and
- :gh:`88` adds a ``profile`` command to show information on tasks like duration and
file size of products.
- :gh:`93` fixes the display of parametrized arguments in the console.
- :gh:`94` adds ``--show-locals`` which allows to print local variables in tracebacks.


0.0.14 - 2021-03-23
Expand Down
14 changes: 14 additions & 0 deletions docs/reference_guides/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@ The options
pdb = True


.. confval:: show_locals

If you want to print local variables of each stack frame in the tracebacks, set this
value to true.

.. code-block:: console

pytask build --show-locals

.. code-block:: ini

show_locals = True


.. confval:: strict_markers

If you want to raise an error for unregistered markers, pass
Expand Down
13 changes: 12 additions & 1 deletion docs/tutorials/how_to_debug.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ be more productive and gain more confidence in your code.
To facilitate debugging, pytask offers two command-line options.


Tracebacks
----------

You can enrich the display of tracebacks by show local variables in each stack frame.
Just execute pytask with

.. code-block:: console

$ pytask --show-locals


Debugging
---------

Expand All @@ -30,7 +41,7 @@ prompt will enter the debugger enabling you to discover the source of the except
.. tip::

Instead of Python's :mod:`pdb`, use `pdb++ <https://github.com/pdbpp/pdbpp>`_ which
is more convenient, colorful has some useful features like the `sticky mode
is more convenient, colorful, and has some useful features like the `sticky mode
<https://github.com/pdbpp/pdbpp#sticky-mode>`_.


Expand Down
2 changes: 2 additions & 0 deletions src/_pytask/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def pytask_add_hooks(pm):
from _pytask import collect
from _pytask import collect_command
from _pytask import config
from _pytask import console
from _pytask import database
from _pytask import debugging
from _pytask import execute
Expand All @@ -61,6 +62,7 @@ def pytask_add_hooks(pm):
pm.register(collect)
pm.register(collect_command)
pm.register(config)
pm.register(console)
pm.register(database)
pm.register(debugging)
pm.register(execute)
Expand Down
2 changes: 1 addition & 1 deletion src/_pytask/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def pytask_collect_log(session, reports, tasks):

console.print()

console.print(Traceback.from_exception(*report.exc_info))
console.print(Traceback.from_exception(*report.exc_info, show_locals=True))

console.print()

Expand Down
27 changes: 27 additions & 0 deletions src/_pytask/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
import sys
from typing import List

import click
from _pytask.config import hookimpl
from _pytask.shared import convert_truthy_or_falsy_to_bool
from _pytask.shared import get_first_non_none_value
from rich.console import Console
from rich.tree import Tree


_IS_WSL = "IS_WSL" in os.environ or "WSL_DISTRO_NAME" in os.environ
_IS_WINDOWS_TERMINAL = "WT_SESSION" in os.environ
_IS_WINDOWS = sys.platform == "win32"
Expand All @@ -29,6 +34,28 @@
console = Console(color_system=_COLOR_SYSTEM)


@hookimpl
def pytask_extend_command_line_interface(cli):
show_locals_option = click.Option(
["--show-locals"],
is_flag=True,
default=None,
help="Show local variables in tracebacks.",
)
cli.commands["build"].params.append(show_locals_option)


@hookimpl
def pytask_parse_config(config, config_from_file, config_from_cli):
config["show_locals"] = get_first_non_none_value(
config_from_cli,
config_from_file,
key="show_locals",
default=False,
callback=convert_truthy_or_falsy_to_bool,
)


def format_strings_as_flat_tree(strings: List[str], title: str, icon: str) -> str:
"""Format list of strings as flat tree."""
tree = Tree(title)
Expand Down
5 changes: 4 additions & 1 deletion src/_pytask/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def pytask_execute_task_log_end(report):
@hookimpl
def pytask_execute_log_end(session, reports):
session.execution_end = time.time()
show_locals = session.config["show_locals"]

n_successful = sum(report.success for report in reports)
n_failed = len(reports) - n_successful
Expand All @@ -183,7 +184,9 @@ def pytask_execute_log_end(session, reports):

console.print()

console.print(Traceback.from_exception(*report.exc_info))
console.print(
Traceback.from_exception(*report.exc_info, show_locals=show_locals)
)

console.print()
show_capture = session.config["show_capture"]
Expand Down
17 changes: 10 additions & 7 deletions src/_pytask/resolve_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,16 @@ def _has_node_changed(task_name: str, node_dict):
try:
state = node.state()
except NodeNotFoundError:
return True
try:
state_in_db = State[task_name, node.name].state
except orm.ObjectNotFound:
return True

return state != state_in_db
out = True
else:
try:
state_in_db = State[task_name, node.name].state
except orm.ObjectNotFound:
out = True
else:
out = state != state_in_db

return out


def _check_if_dag_has_cycles(dag):
Expand Down
26 changes: 26 additions & 0 deletions tests/test_console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import textwrap

import pytest
from pytask import cli


@pytest.mark.end_to_end
def test_printing_of_local_variables(tmp_path, runner):
source = """
def task_dummy():
a = 1
helper()

def helper():
b = 2
raise Exception
"""
tmp_path.joinpath("task_dummy.py").write_text(textwrap.dedent(source))

result = runner.invoke(cli, [tmp_path.as_posix(), "--show-locals"])
assert result.exit_code == 1

captured = result.output
assert " locals " in captured
assert "a = 1" in captured
assert "b = 2" in captured