Skip to content

Commit e47e8db

Browse files
Adjusting tests to julia. (#2)
1 parent 2b15b07 commit e47e8db

File tree

14 files changed

+240
-126
lines changed

14 files changed

+240
-126
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ jobs:
1111

1212
run-tests:
1313

14-
name: Run tests for ${{ matrix.os }} on ${{ matrix.python-version }} and ${{ matrix.julia-version }}
14+
name: Run tests for ${{ matrix.os }} on ${{ matrix.python-version }}
1515
runs-on: ${{ matrix.os }}
1616

1717
strategy:
1818
fail-fast: false
1919
matrix:
2020
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
2121
python-version: ['3.7', '3.8', '3.9']
22-
julia-version: ['main_version']
2322

2423
steps:
2524
- uses: actions/checkout@v2
@@ -39,7 +38,7 @@ jobs:
3938
run: tox -e pytest -- -m "unit or (not integration and not end_to_end)" --cov=./ --cov-report=xml -n auto
4039

4140
- name: Upload coverage report for unit tests and doctests.
42-
if: runner.os == 'Linux' && matrix.python-version == '3.8' && matrix.julia-version == 'main_version'
41+
if: runner.os == 'Linux' && matrix.python-version == '3.8'
4342
shell: bash -l {0}
4443
run: bash <(curl -s https://codecov.io/bash) -F unit -c
4544

@@ -48,11 +47,11 @@ jobs:
4847
run: tox -e pytest -- -m end_to_end --cov=./ --cov-report=xml -n auto
4948

5049
- name: Upload coverage reports of end-to-end tests.
51-
if: runner.os == 'Linux' && matrix.python-version == '3.8' && matrix.julia-version == 'main_version'
50+
if: runner.os == 'Linux' && matrix.python-version == '3.8'
5251
shell: bash -l {0}
5352
run: bash <(curl -s https://codecov.io/bash) -F end_to_end -c
5453

5554
- name: Validate codecov.yml
56-
if: runner.os == 'Linux' && matrix.python-version == '3.8' && matrix.julia-version == 'main_version'
55+
if: runner.os == 'Linux' && matrix.python-version == '3.8'
5756
shell: bash -l {0}
5857
run: cat codecov.yml | curl --data-binary @- https://codecov.io/validate

.pre-commit-config.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ repos:
88
- id: check-merge-conflict
99
- id: check-vcs-permalinks
1010
- id: check-yaml
11-
exclude: meta.yaml
1211
- id: debug-statements
1312
- id: end-of-file-fixer
1413
- id: fix-byte-order-marker
@@ -33,7 +32,7 @@ repos:
3332
rev: v2.21.2
3433
hooks:
3534
- id: pyupgrade
36-
args: [--py36-plus]
35+
args: [--py37-plus]
3736
- repo: https://github.com/asottile/reorder_python_imports
3837
rev: v2.5.0
3938
hooks:

CHANGES.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ them in reverse chronological order. Releases follow `semantic versioning
88
<https://anaconda.org/conda-forge/pytask-julia>`_.
99

1010

11-
0.0.1 - 202X-XX-XX
11+
0.1.0 - 2022-xx-xx
1212
------------------
1313

14-
- :gh:`01` fixes ...
14+
- :gh:`2` polishes the first release of pytask-julia. (Thanks to :ghuser:`hmgaudecker`,
15+
:ghuser:`hildebrandecon`)

LICENSE

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
MIT License
32

43
Copyright (c) 2022, Tobias Raabe et al.
@@ -19,6 +18,3 @@ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1918
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
2019
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2120
OTHER DEALINGS IN THE SOFTWARE.
22-
23-
24-

README.rst

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ pytask-julia
1515
:alt: PyPI - License
1616
:target: https://pypi.org/project/pytask-julia
1717

18-
.. image:: https://img.shields.io/github/workflow/status/hmgaudecker/pytask-julia/main/main
19-
:target: https://github.com/hmgaudecker/pytask-julia/actions?query=branch%3Amain
18+
.. image:: https://img.shields.io/github/workflow/status/pytask-dev/pytask-julia/main/main
19+
:target: https://github.com/pytask-dev/pytask-julia/actions?query=branch%3Amain
2020

2121
.. image:: https://readthedocs.org/projects/pytask-julia/badge/?version=latest
2222
:target: https://pytask-julia.readthedocs.io/en/latest/?badge=latest
2323
:alt: Documentation Status
2424

25-
.. image:: https://codecov.io/gh/hmgaudecker/pytask-julia/branch/main/graph/badge.svg
26-
:target: https://codecov.io/gh/hmgaudecker/pytask-julia
25+
.. image:: https://codecov.io/gh/pytask-dev/pytask-julia/branch/main/graph/badge.svg
26+
:target: https://codecov.io/gh/pytask-dev/pytask-julia
2727

28-
.. image:: https://results.pre-commit.ci/badge/github/hmgaudecker/pytask-julia/main.svg
29-
:target: https://results.pre-commit.ci/latest/github/hmgaudecker/pytask-julia/main
28+
.. image:: https://results.pre-commit.ci/badge/github/pytask-dev/pytask-julia/main.svg
29+
:target: https://results.pre-commit.ci/latest/github/pytask-dev/pytask-julia/main
3030
:alt: pre-commit.ci status
3131

3232
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
@@ -36,7 +36,8 @@ pytask-julia
3636
Installation
3737
------------
3838

39-
pytask-julia is available on `PyPI <https://pypi.org/project/pytask-julia>`_ and `Anaconda.org <https://anaconda.org/conda-forge/pytask-julia>`_. Install it with
39+
pytask-julia is available on `PyPI <https://pypi.org/project/pytask-julia>`_ and
40+
`Anaconda.org <https://anaconda.org/conda-forge/pytask-julia>`_. Install it with
4041

4142
.. code-block:: console
4243
@@ -53,7 +54,13 @@ typing the following on the command line
5354
5455
$ julia -h
5556
56-
If an error is shown instead of a help page, you can install Julia ....
57+
If an error is shown instead of a help page, you can install Julia on Unix systems with
58+
59+
.. code-block:: console
60+
61+
$ conda install -c conda-forge julia
62+
63+
or choose one of the installers on this `page <https://julialang.org/downloads/>`_.
5764

5865

5966
Usage
@@ -77,8 +84,8 @@ Here is an example where you want to run ``script.julia``.
7784
def task_run_jl_script():
7885
pass
7986
80-
Note that, you need to apply the ``@pytask.mark.julia`` marker so that pytask-julia handles the
81-
task.
87+
Note that, you need to apply the ``@pytask.mark.julia`` marker so that pytask-julia
88+
handles the task.
8289

8390
If you are wondering why the function body is empty, know that pytask-julia replaces the
8491
body with a predefined internal function. See the section on implementation details for
@@ -88,8 +95,8 @@ more information.
8895
Multiple dependencies and products
8996
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9097

91-
What happens if a task has more dependencies? Using a list, the Julia script which should be
92-
executed must be found in the first position of the list.
98+
What happens if a task has more dependencies? Using a list, the Julia script which
99+
should be executed must be found in the first position of the list.
93100

94101
.. code-block:: python
95102
@@ -132,31 +139,65 @@ for a ``"source"`` key in the dictionary and, secondly, under the key ``0``.
132139
Command Line Arguments
133140
~~~~~~~~~~~~~~~~~~~~~~
134141

135-
The decorator can be used to pass command line arguments to ``julia``. See the
136-
following example.
142+
The decorator can be used to pass command line arguments to ``julia``. An important
143+
detail is that you need to differentiate between options passed to the Julia executable
144+
and arguments passed to the script.
145+
146+
First, pass options to the executable, then, use ``"--"`` as a separator, and after that
147+
arguments to the script. Provide all arguments in a tuple or a list as below.
148+
149+
The following shows how to pass both with the decorator.
137150

138151
.. code-block:: python
139152
140-
@pytask.mark.julia("value")
153+
@pytask.mark.julia(("--threads", "2", "--", "value"))
141154
@pytask.mark.depends_on("script.jl")
142155
@pytask.mark.produces("out.csv")
143156
def task_run_jl_script():
144157
pass
145158
159+
which executes the something similar to the following on the command line.
160+
161+
.. code-block:: console
162+
163+
$ julia --threads 2 -- value
164+
146165
And in your ``script.jl``, you can intercept the value with
147166

148167
.. code-block:: Julia
149168
150-
FIXME FOR YOUR LANGUAGE
151-
args <- commandArgs(trailingOnly=TRUE)
152-
arg <- args[1] # holds ``"value"``
169+
arg = ARGS[1] # holds ``"value"``
170+
171+
If you pass only of of them, either options for the executable or arguments to the
172+
script, you still need to include the separator.
173+
174+
.. code-block:: python
175+
176+
@pytask.mark.julia(("--verbose", "--")) # for options for the executable.
177+
@pytask.mark.depends_on("script.jl")
178+
def task_func():
179+
...
180+
181+
182+
@pytask.mark.julia(("--", "value")) # for arguments for the script.
183+
@pytask.mark.depends_on("script.jl")
184+
def task_func():
185+
...
186+
187+
The corresponding commands on the command line are
188+
189+
.. code-block:: console
190+
191+
$ julia --verbose -- script.jl
192+
193+
$ julia -- script.jl value
153194
154195
155196
Parametrization
156197
~~~~~~~~~~~~~~~
157198

158-
You can also parametrize the execution of scripts, meaning executing multiple Julia scripts
159-
as well as passing different command line arguments to the same Julia script.
199+
You can also parametrize the execution of scripts, meaning executing multiple Julia
200+
scripts as well as passing different command line arguments to the same Julia script.
160201

161202
The following task executes two Julia scripts which produce different outputs.
162203

@@ -173,23 +214,25 @@ The following task executes two Julia scripts which produce different outputs.
173214
def task_execute_julia_script():
174215
pass
175216
176-
And the R script includes something like
217+
And the Julia script includes something like
177218

178-
.. code-block:: r
219+
.. code-block:: julia
179220
180-
args <- commandArgs(trailingOnly=TRUE)
181-
produces <- args[1] # holds the path
221+
produces = ARGS[1] # holds the path
182222
183-
If you want to pass different command line arguments to the same Julia script, you have to
184-
include the ``@pytask.mark.julia`` decorator in the parametrization just like with
185-
``@pytask.mark.depends_on`` and ``@pytask.mark.produces``.
223+
If you want to pass different command line arguments to the same Julia script, you
224+
have to include the ``@pytask.mark.julia`` decorator in the parametrization just like
225+
with ``@pytask.mark.depends_on`` and ``@pytask.mark.produces``.
186226

187227
.. code-block:: python
188228
189229
@pytask.mark.depends_on("script.jl")
190230
@pytask.mark.parametrize(
191231
"produces, julia",
192-
[(BLD / "output_1.csv", "1"), (BLD / "output_2.csv", "2")],
232+
[
233+
(BLD / "output_1.csv", ("--", "1")),
234+
(BLD / "output_2.csv", ("--", "2")),
235+
],
193236
)
194237
def task_execute_julia_script():
195238
pass
@@ -220,9 +263,9 @@ The plugin is a convenient wrapper around
220263
to which you can always resort to when the plugin does not deliver functionality you
221264
need.
222265

223-
It is not possible to enter a post-mortem debugger when an error happens in the Julia script
224-
or enter the debugger when starting the script. If there exists a solution for that,
225-
hints as well as contributions are highly appreciated.
266+
It is not possible to enter a post-mortem debugger when an error happens in the Julia
267+
script or enter the debugger when starting the script. If there exists a solution for
268+
that, hints as well as contributions are highly appreciated.
226269

227270

228271
Changes

environment.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ channels:
55
- nodefaults
66

77
dependencies:
8-
- julia
98
- python
109
- pip
1110
- setuptools_scm
1211
- toml
1312

1413
# Package dependencies
14+
- julia
1515
- pytask >=0.1
1616
- pytask-parallel >=0.1
1717

@@ -24,3 +24,6 @@ dependencies:
2424
- pytest-cov
2525
- pytest-xdist
2626
- tox-conda
27+
28+
- pip:
29+
- -e .

setup.cfg

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[metadata]
2-
name = pytask-julia
2+
name = pytask_julia
33
description = A Pytask plugin for Julia
44
long_description = file: README.rst
55
long_description_content_type = text/x-rst
@@ -18,7 +18,6 @@ classifiers =
1818
Programming Language :: Python :: 3.7
1919
Programming Language :: Python :: 3.8
2020
Programming Language :: Python :: 3.9
21-
Programming Language :: Python :: 3.10
2221
project_urls =
2322
Changelog = https://github.com/pytask-dev/pytask-julia/blob/main/CHANGES.rst
2423
Documentation = https://github.com/pytask-dev/pytask-julia

src/pytask_julia/collect.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
from _pytask.parametrize import _copy_func
1616

1717

18+
_SEPARATOR = "--"
19+
"""str: Separates options for the Julia executable and arguments to the file."""
20+
21+
1822
def julia(options: Optional[Union[str, Iterable[str]]] = None):
1923
"""Specify command line options for Julia.
2024
@@ -24,8 +28,9 @@ def julia(options: Optional[Union[str, Iterable[str]]] = None):
2428
One or multiple command line options passed to Julia.
2529
2630
"""
27-
options = [] if options is None else _to_list(options)
31+
options = [_SEPARATOR] if options is None else _to_list(options)
2832
options = [str(i) for i in options]
33+
2934
return options
3035

3136

@@ -57,11 +62,10 @@ def pytask_collect_task_teardown(session, task):
5762
"""Perform some checks."""
5863
if get_specific_markers_from_task(task, "julia"):
5964
source = _get_node_from_dictionary(task.depends_on, "source")
60-
if isinstance(source, FilePathNode) and source.value.suffix not in [
61-
".jl"
62-
]:
65+
if isinstance(source, FilePathNode) and source.value.suffix not in [".jl"]:
6366
raise ValueError(
64-
"The first dependency of a Julia task must be the script to be executed."
67+
"The first dependency of a Julia task must be the script to be "
68+
"executed."
6569
)
6670

6771
julia_function = _copy_func(run_jl_script)
@@ -91,6 +95,24 @@ def _merge_all_markers(task):
9195
return mark
9296

9397

98+
_ERROR_MSG_MISSING_SEPARATOR = f"""The inputs of the @pytask.mark.julia decorator do not
99+
contain the separator to differentiate between options for the julia executable and
100+
arguments to the script. This was passed to the decorator:
101+
102+
{{}}
103+
104+
Construct the inputs to the decorator should contain, first, options to the executable,
105+
secondly, the separator - "{_SEPARATOR}" -, thirdly, arguments to the script.
106+
107+
Here is an example:
108+
109+
@pytask.mark.julia(("--threads", "1", "{_SEPARATOR}", "input.file"))
110+
111+
Even if you do not need the left or the right side of the decorator, you must put the
112+
separator at the correct position.
113+
"""
114+
115+
94116
def _prepare_cmd_options(session, task, args):
95117
"""Prepare the command line arguments to execute the do-file.
96118
@@ -101,7 +123,21 @@ def _prepare_cmd_options(session, task, args):
101123
source = _get_node_from_dictionary(
102124
task.depends_on, session.config["julia_source_key"]
103125
)
104-
return ["julia", source.path.as_posix(), *args]
126+
127+
if _SEPARATOR not in args:
128+
raise ValueError(_ERROR_MSG_MISSING_SEPARATOR.format(args))
129+
else:
130+
idx_sep = args.index(_SEPARATOR)
131+
executable_options = args[:idx_sep]
132+
script_arguments = args[idx_sep + 1 :]
133+
134+
return [
135+
"julia",
136+
*executable_options,
137+
_SEPARATOR,
138+
source.path.as_posix(),
139+
*script_arguments,
140+
]
105141

106142

107143
def _to_list(scalar_or_iter):

0 commit comments

Comments
 (0)