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
37 changes: 24 additions & 13 deletions src/pytask_latex/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,28 @@ def pytask_collect_task(
markers=markers,
)

if session.config["infer_latex_dependencies"]:
task = _add_latex_dependencies_retroactively(task, session)

return task
return None


def _add_latex_dependencies_retroactively(task: PTask, session: Session) -> PTask:
@hookimpl
def pytask_collect_modify_tasks(session: Session, tasks: list[PTask]) -> None:
"""Add dependencies from from LaTeX documents to tasks."""
if session.config["infer_latex_dependencies"]:
all_products = {
product.path
for task in tasks
for product in tree_leaves(task.produces)
if isinstance(product, PPathNode)
}
latex_tasks = [task for task in tasks if has_mark(task, "latex")]
for task in latex_tasks:
_add_latex_dependencies_retroactively(task, session, all_products)


def _add_latex_dependencies_retroactively(
task: PTask, session: Session, all_products: set[Path]
) -> None:
"""Add dependencies from LaTeX document to task.

Unfortunately, the dependencies have to be added retroactively, after the task has
Expand All @@ -234,23 +248,22 @@ def _add_latex_dependencies_retroactively(task: PTask, session: Session) -> PTas
"""
# Scan the LaTeX document for included files.
try:
latex_dependencies = set(
scanned_deps = set(
lds.scan(task.depends_on["_path_to_tex"].path) # type: ignore[attr-defined]
)
except Exception: # noqa: BLE001
warnings.warn(
"pytask-latex failed to scan latex document for dependencies.", stacklevel=1
)
latex_dependencies = set()
scanned_deps = set()

# Remove duplicated dependencies which have already been added by the user and those
# which do not exist.
existing_paths = {
task_deps = {
i.path for i in tree_leaves(task.depends_on) if isinstance(i, PPathNode)
}
new_deps = latex_dependencies - existing_paths
new_existing_deps = {i for i in new_deps if i.exists()}
new_numbered_deps = dict(enumerate(new_existing_deps))
additional_deps = scanned_deps - task_deps
new_deps = [i for i in additional_deps if i in all_products or i.exists()]

# Collect new dependencies and add them to the task.
task_path = task.path if isinstance(task, PTaskWithPath) else None
Expand All @@ -268,7 +281,7 @@ def _add_latex_dependencies_retroactively(task: PTask, session: Session) -> PTas
task_name=task.name,
),
),
new_numbered_deps,
new_deps,
)
task.depends_on[
"_scanned_dependencies"
Expand All @@ -277,8 +290,6 @@ def _add_latex_dependencies_retroactively(task: PTask, session: Session) -> PTas
# Mark the task as being delayed to avoid conflicts with unmatched dependencies.
task.markers.append(Mark("try_last", (), {}))

return task


def _collect_node(
session: Session, path: Path, node_info: NodeInfo
Expand Down
40 changes: 40 additions & 0 deletions tests/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,3 +584,43 @@ def test_use_task_without_path(tmp_path):
tmp_path.joinpath("document.tex").write_text(textwrap.dedent(latex_source))
session = build(paths=tmp_path)
assert session.exit_code == ExitCode.OK


@needs_latexmk
@skip_on_github_actions_with_win
@pytest.mark.end_to_end()
def test_collect_latex_document_with_product_from_another_task(runner, tmp_path):
"""Test simple compilation."""
task_source = """
import pytask
from pathlib import Path
from pytask import Product
from typing_extensions import Annotated

@pytask.mark.latex(script="document.tex", document="document.pdf")
def task_compile_document(): pass


def task_create_input_tex(
path: Annotated[Path, Product] = Path("duesterboys.tex")
) -> None:
path.write_text("weil du meine Mitten extrahierst.")
"""
tmp_path.joinpath("task_dummy.py").write_text(textwrap.dedent(task_source))

latex_source = r"""
\documentclass{report}
\begin{document}
\input{duesseldorf}
\input{duesterboys}
\end{document}
"""
tmp_path.joinpath("document.tex").write_text(textwrap.dedent(latex_source))
tmp_path.joinpath("duesseldorf.tex").write_text(
"Bin ich wieder nur so nett zu dir, "
)

result = runner.invoke(cli, ["collect", "--nodes", tmp_path.as_posix()])
assert result.exit_code == ExitCode.OK
assert "duesseldorf.tex" in result.output
assert "duesterboys.tex" in result.output