diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a3a26a..ca73b57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning][]. requirement introduced by the R API package, see [#50](https://github.com/Boehringer-Ingelheim/dso/issues/50) ([#58](https://github.com/Boehringer-Ingelheim/dso/pull/58)). - Improve logging for "missing path" warning during `compile-config` ([#59](https://github.com/Boehringer-Ingelheim/dso/pull/59)). - Improve logging for missing parameters in `dvc.yaml` during `get-config` ([#59](https://github.com/Boehringer-Ingelheim/dso/pull/59)). +- Make sure internal calls to the dso pandocfilter use the same python and dso version as the parent command. This is important for the upcoming `dso-mgr` feature ([#61](https://github.com/Boehringer-Ingelheim/dso/pull/61)). ## v0.9.0 diff --git a/pyproject.toml b/pyproject.toml index 9d2136d..359a685 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,6 @@ urls.Documentation = "https://github.com/Boehringer-Ingelheim/dso" urls.Home-page = "https://github.com/Boehringer-Ingelheim/dso" urls.Source = "https://github.com/Boehringer-Ingelheim/dso" scripts.dso = "dso:cli" -scripts.dso_pandocfilter = "dso.pandocfilter:main" [tool.hatch.version] source = "vcs" diff --git a/src/dso/_util.py b/src/dso/_util.py index a766394..5a40f9f 100644 --- a/src/dso/_util.py +++ b/src/dso/_util.py @@ -5,7 +5,13 @@ from collections.abc import Sequence from functools import cache from importlib import resources -from importlib.abc import Traversable + +try: + # has been added in Python 3.11 + from importlib.resources.abc import Traversable +except ImportError: + # will be removed in Python 3.14 + from importlib.abc import Traversable from os import environ from pathlib import Path from typing import Literal diff --git a/src/dso/exec.py b/src/dso/exec.py index 18338b5..78b97d3 100644 --- a/src/dso/exec.py +++ b/src/dso/exec.py @@ -1,6 +1,8 @@ import os +import stat import subprocess import sys +import tempfile from contextlib import contextmanager from pathlib import Path from textwrap import dedent, indent @@ -39,7 +41,25 @@ def _render_quarto(quarto_dir: Path, report_dir: Path, before_script: str, cwd: if f.is_file(): f.unlink() - pandocfilter = "--filter dso_pandocfilter" if with_pandocfilter else "" + # Enable pandocfilter if requested. + # We create a temporary script that then calls the current python binary with the dso.pandocfilter module + # This may seem cumbersome, but we do it this way because + # * pandoc only supports a single binary for `--filter`, referring to subcommands or `-m` is not possible here + # * we want to ensure that exactly the same python/dso version is used for the pandocfilter as for the + # parent command (important when running through dso-mgr) + filter_script = None + if with_pandocfilter: + with tempfile.NamedTemporaryFile(delete=False, mode="w") as f: + f.write("#!/bin/bash\n") + f.write(f'{sys.executable} -m dso.pandocfilter "$@"\n') + filter_script = Path(f.name) + + filter_script.chmod(filter_script.stat().st_mode | stat.S_IEXEC) + + pandocfilter = f"--filter {filter_script}" + else: + pandocfilter = "" + # propagate quiet setting to quarto quiet = "--quiet" if bool(int(os.environ.get("DSO_QUIET", 0))) else "" script = dedent( @@ -56,6 +76,11 @@ def _render_quarto(quarto_dir: Path, report_dir: Path, before_script: str, cwd: """ ) res = subprocess.run(script, shell=True, executable="/bin/bash", cwd=cwd) + + # clean up + if filter_script is not None: + filter_script.unlink() + if res.returncode: sys.exit(res.returncode) diff --git a/src/dso/pandocfilter.py b/src/dso/pandocfilter.py index 21a27eb..326be5b 100644 --- a/src/dso/pandocfilter.py +++ b/src/dso/pandocfilter.py @@ -3,6 +3,8 @@ * warning box at the top * watermark to all PNG images + +Called internally by `dso exec quarto`. """ import sys @@ -89,10 +91,5 @@ def action(elem, doc): return elem -def main(doc=None): - """ - A pandoc filter to add warning boxes to documents and watermarks to plots - - Called internally by `dso exec quarto`. - """ - return run_filter(action, prepare=prepare, doc=doc) +if __name__ == "__main__": + run_filter(action, prepare=prepare, doc=None)