Skip to content

Release v0.0.8 and require pytask v0.0.9. #11

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 12 commits into from
Oct 30, 2020
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: 3 additions & 1 deletion .conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ requirements:

run:
- python >=3.6
- pytask >=0.0.7
- pytask >=0.0.9

test:
requires:
- pytest
- pytask-parallel >=0.0.4
source_files:
- tox.ini
- tests
Expand All @@ -33,6 +34,7 @@ test:
- pytask --help
- pytask clean
- pytask markers
- pytask collect

- pytest tests

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: r-lib/actions/setup-tinytex@v1
if: runner.os != 'Windows'
- uses: goanpeca/setup-miniconda@v1
with:
auto-update-conda: true
Expand Down
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ all releases are available on `Anaconda.org
<https://anaconda.org/pytask/pytask-latex>`_.


0.0.8 - 2020-10-29
------------------

- :gh:`11` makes pytask-latex work with pytask v0.0.9.


0.0.7 - 2020-10-14
------------------

Expand Down
67 changes: 63 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,16 @@ Here is an example where you want to compile ``document.tex`` to a PDF.
def task_compile_latex_document():
pass

When the task is executed, you find a ``document.pdf`` in the same folder as your
``document.text``, but you could also compile the report into a another folder by
changing the path in ``produces``.

Note that, LaTeX document which will be compiled must be the first dependency. Add other
dependencies like images after the source file.

Multiple dependencies and products
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

What happens if a task has more dependencies? Using a list, the LaTeX document which
should be compiled must be found in the first position of the list.

.. code-block:: python

Expand All @@ -72,6 +79,38 @@ dependencies like images after the source file.
def task_compile_latex_document():
pass

If you use a dictionary to pass dependencies to the task, pytask-latex will, first, look
for a ``"source"`` key in the dictionary and, secondly, under the key ``0``.

.. code-block:: python

@pytask.mark.depends_on({"source": "document.tex", "image": "image.png"})
def task_compile_document():
pass


# or


@pytask.mark.depends_on({0: "document.tex", "image": "image.png"})
def task_compile_document():
pass


# or two decorators for the function, if you do not assign a name to the image.


@pytask.mark.depends_on({"source": "document.tex"})
@pytask.mark.depends_on("image.png")
def task_compile_document():
pass

The same applies to the compiled document which is either in the first position, under
the key ``"document"`` or ``0``.


Command Line Arguments
~~~~~~~~~~~~~~~~~~~~~~

To customize the compilation, you can pass some command line arguments to ``latexmk``
via the ``@pytask.mark.latex`` marker. The default is the following.
Expand Down Expand Up @@ -134,14 +173,34 @@ to include the latex decorator in the parametrization just like with
@pytask.mark.parametrize(
"produces, latex",
[
("document.pdf", (["--pdf", "interaction=nonstopmode"])),
("document.dvi", (["--dvi", "interaction=nonstopmode"])),
(
"document.pdf",
(["--pdf", "--interaction=nonstopmode", "--synctex=1", "--cd"],),
),
(
"document.dvi",
(["--dvi", "--interaction=nonstopmode", "--synctex=1", "--cd"],),
),
],
)
def task_compile_latex_document():
pass


Configuration
-------------

If you want to change the names of the keys which identify the source file and the
compiled document, change the following default configuration in your pytask
configuration file.

.. code-block:: ini

latex_source_key = source
latex_document_key = document



Changes
-------

Expand Down
3 changes: 2 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ dependencies:
- conda-verify

# Package dependencies
- pytask >= 0.0.7
- pytask >= 0.0.9
- pytask-parallel >= 0.0.4

# Misc
- bumpversion
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.0.7
current_version = 0.0.8
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+))(\-?((dev)?(?P<dev>\d+))?)
serialize =
{major}.{minor}.{patch}dev{dev}
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name="pytask-latex",
version="0.0.7",
version="0.0.8",
packages=find_packages(where="src"),
package_dir={"": "src"},
entry_points={"pytask": ["pytask_latex = pytask_latex.plugin"]},
Expand Down
2 changes: 1 addition & 1 deletion src/pytask_latex/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.0.7"
__version__ = "0.0.8"
149 changes: 82 additions & 67 deletions src/pytask_latex/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from _pytask.nodes import FilePathNode
from _pytask.nodes import PythonFunctionTask
from _pytask.parametrize import _copy_func
from _pytask.shared import to_list


DEFAULT_OPTIONS = ["--pdf", "--interaction=nonstopmode", "--synctex=1", "--cd"]
Expand All @@ -37,45 +36,9 @@ def latex(options: Optional[Union[str, Iterable[str]]] = None):
return options


def compile_latex_document(depends_on, produces, latex):
"""Compile a LaTeX document.

This function replaces the dummy function of an LaTeX task. It is a nice wrapper
around subprocess.

The output folder needs to be declared as a relative path to the directory where the
latex source lies.

1. It must be relative because bibtex / biber, which is necessary for
bibliographies, does not accept full paths as a safety measure.
2. Due to the ``--cd`` flag, latexmk will change the directory to the one where the
source files are. Thus, relative to the latex sources.

See this `discussion on Github
<https://github.com/James-Yu/LaTeX-Workshop/issues/1932#issuecomment-582416434>`_
for additional information.

"""
latex_document = to_list(depends_on)[0]
compiled_document = to_list(produces)[0]

if latex_document.stem != compiled_document.stem:
latex.append(f"--jobname={compiled_document.stem}")

# See comment in doc string.
out_relative_to_latex_source = Path(
os.path.relpath(compiled_document.parent, latex_document.parent)
).as_posix()

subprocess.run(
[
"latexmk",
*latex,
f"--output-directory={out_relative_to_latex_source}",
f"{latex_document.as_posix()}",
],
check=True,
)
def compile_latex_document(latex):
"""Replaces the dummy function provided by the user."""
subprocess.run(latex, check=True)


@hookimpl
Expand All @@ -88,52 +51,56 @@ def pytask_collect_task(session, path, name, obj):

"""
if name.startswith("task_") and callable(obj) and has_marker(obj, "latex"):
# Collect the task.
task = PythonFunctionTask.from_path_name_function_session(
path, name, obj, session
)
latex_function = _copy_func(compile_latex_document)
latex_function.pytaskmark = copy.deepcopy(task.function.pytaskmark)

merged_mark = _merge_all_markers(task)
args = latex(*merged_mark.args, **merged_mark.kwargs)
latex_function = functools.partial(latex_function, latex=args)

task.function = latex_function

return task


@hookimpl
def pytask_collect_task_teardown(task):
"""Perform some checks.

Remove check for task is none with pytask 0.0.9.

"""
if task is not None and get_specific_markers_from_task(task, "latex"):
if (len(task.depends_on) == 0) or (
not (
isinstance(task.depends_on[0], FilePathNode)
and task.depends_on[0].value.suffix == ".tex"
)
):
def pytask_collect_task_teardown(session, task):
"""Perform some checks."""
if get_specific_markers_from_task(task, "latex"):
source = _get_node_from_dictionary(
task.depends_on, session.config["latex_source_key"]
)
if not (isinstance(source, FilePathNode) and source.value.suffix == ".tex"):
raise ValueError(
"The first or sole dependency of a LaTeX task must be the document "
"which will be compiled and has a .tex extension."
)

if (len(task.produces) == 0) or (
not (
isinstance(task.produces[0], FilePathNode)
and task.produces[0].value.suffix in [".pdf", ".ps", ".dvi"]
)
document = _get_node_from_dictionary(
task.produces, session.config["latex_document_key"]
)
if not (
isinstance(document, FilePathNode)
and document.value.suffix in [".pdf", ".ps", ".dvi"]
):
raise ValueError(
"The first or sole product of a LaTeX task must point to a .pdf, .ps "
"or .dvi file which is the compiled document."
)

latex_function = _copy_func(compile_latex_document)
latex_function.pytaskmark = copy.deepcopy(task.function.pytaskmark)

merged_mark = _merge_all_markers(task)
args = latex(*merged_mark.args, **merged_mark.kwargs)
options = _prepare_cmd_options(session, task, args)
latex_function = functools.partial(latex_function, latex=options)

task.function = latex_function


def _get_node_from_dictionary(obj, key, fallback=0):
if isinstance(obj, Path):
pass
elif isinstance(obj, dict):
obj = obj.get(key) or obj.get(fallback)
return obj


def _merge_all_markers(task):
"""Combine all information from markers for the compile latex function."""
Expand All @@ -142,3 +109,51 @@ def _merge_all_markers(task):
for mark_ in latex_marks[1:]:
mark = mark.combined_with(mark_)
return mark


def _prepare_cmd_options(session, task, args):
"""Prepare the command line arguments to compile the LaTeX document.

The output folder needs to be declared as a relative path to the directory where the
latex source lies.

1. It must be relative because bibtex / biber, which is necessary for
bibliographies, does not accept full paths as a safety measure.
2. Due to the ``--cd`` flag, latexmk will change the directory to the one where the
source files are. Thus, relative to the latex sources.

See this `discussion on Github
<https://github.com/James-Yu/LaTeX-Workshop/issues/1932#issuecomment-582416434>`_
for additional information.

"""
latex_document = _get_node_from_dictionary(
task.depends_on, session.config["latex_source_key"]
).value
compiled_document = _get_node_from_dictionary(
task.produces, session.config["latex_document_key"]
).value

# Jobname controls the name of the compiled document. No suffix!
if latex_document.stem != compiled_document.stem:
jobname = [f"--jobname={compiled_document.stem}"]
else:
jobname = []

# The path to the output directory must be relative from the location of the source
# file. See docstring for more information.
out_relative_to_latex_source = Path(
os.path.relpath(compiled_document.parent, latex_document.parent)
).as_posix()

return (
[
"latexmk",
*args,
]
+ jobname
+ [
f"--output-directory={out_relative_to_latex_source}",
latex_document.as_posix(),
]
)
6 changes: 5 additions & 1 deletion src/pytask_latex/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@


@hookimpl
def pytask_parse_config(config):
def pytask_parse_config(config, config_from_file):
"""Register the latex marker in the configuration."""
config["markers"]["latex"] = "Tasks which compile LaTeX documents."
config["latex_source_key"] = config_from_file.get("latex_source_key", "source")
config["latex_document_key"] = config_from_file.get(
"latex_document_key", "document"
)
Loading