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
60 changes: 29 additions & 31 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-added-large-files
args: ['--maxkb=100']
Expand All @@ -24,50 +24,33 @@ repos:
- id: python-no-log-warn
- id: python-use-type-annotations
- id: text-unicode-replacement-char
- repo: https://github.com/asottile/pyupgrade
rev: v3.1.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/asottile/reorder_python_imports
rev: v3.8.5
rev: v3.9.0
hooks:
- id: reorder-python-imports
args: [--py37-plus, --add-import, 'from __future__ import annotations']
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.1.0
rev: v2.2.0
hooks:
- id: setup-cfg-fmt
- repo: https://github.com/PyCQA/docformatter
rev: v1.5.0
rev: v1.5.1
hooks:
- id: docformatter
args: [--in-place, --wrap-summaries, "88", --wrap-descriptions, "88", --blank]
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 22.12.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.215
hooks:
- id: flake8
types: [python]
additional_dependencies: [
flake8-alfred,
flake8-bugbear,
flake8-builtins,
flake8-comprehensions,
flake8-docstrings,
flake8-eradicate,
flake8-print,
flake8-pytest-style,
flake8-todo,
flake8-typing-imports,
flake8-unused-arguments,
pep8-naming,
pydocstyle,
Pygments,
]
- id: ruff
- repo: https://github.com/dosisod/refurb
rev: v1.9.1
hooks:
- id: refurb
args: [--ignore, FURB126]
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.16
hooks:
Expand All @@ -82,12 +65,27 @@ repos:
hooks:
- id: interrogate
args: [-v, --fail-under=40, src]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v0.991'
hooks:
- id: mypy
args: [
--no-strict-optional,
--ignore-missing-imports,
]
additional_dependencies: [
attrs>=21.3.0,
click,
types-PyYAML,
types-setuptools
]
pass_filenames: false
- repo: https://github.com/codespell-project/codespell
rev: v2.2.2
hooks:
- id: codespell
- repo: https://github.com/mgedmin/check-manifest
rev: "0.48"
rev: "0.49"
hooks:
- id: check-manifest
args: [--no-build-isolation]
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ releases are available on [PyPI](https://pypi.org/project/pytask-julia) and

## 0.3.0 - 2023-xx-xx

- {pull}`16` adds mypy, refurb, and ruff.
- {pull}`18` deprecates INI configurations and aligns the package with pytask v0.3.

## 0.2.1 - 2022-04-16
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ exclude *.yml
include README.md
include LICENSE
include pyproject.toml

recursive-include src py.typed
55 changes: 55 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,58 @@ build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
write_to = "src/pytask_julia/_version.py"


[tool.mypy]
files = ["src", "tests"]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true


[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
ignore_errors = true


[tool.ruff]
target-version = "py37"
select = ["ALL"]
fix = true
extend-ignore = [
# Numpy docstyle
"D107",
"D203",
"D212",
"D213",
"D402",
"D413",
"D415",
"D416",
"D417",
# Others.
"D404", # Do not start module docstring with "This".
"RET504", # unnecessary variable assignment before return.
"S101", # raise errors for asserts.
"B905", # strict parameter for zip that was implemented in py310.
"I", # ignore isort
"ANN101", # type annotating self
"ANN102", # type annotating cls
"FBT", # flake8-boolean-trap
"EM", # flake8-errmsg
"ANN401", # flake8-annotate typing.Any
"PD", # pandas-vet
]


[tool.ruff.per-file-ignores]
"tests/*" = ["D", "ANN"]


[tool.ruff.pydocstyle]
convention = "numpy"
1 change: 1 addition & 0 deletions src/pytask_julia/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""This module contains the main namespace."""
from __future__ import annotations

try:
Expand Down
42 changes: 26 additions & 16 deletions src/pytask_julia/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import subprocess
import types
from pathlib import Path
from typing import Any
from typing import Callable

from pytask import depends_on
from pytask import has_mark
Expand All @@ -13,6 +15,7 @@
from pytask import parse_nodes
from pytask import produces
from pytask import remove_marks
from pytask import Session
from pytask import Task
from pytask_julia.serialization import SERIALIZERS
from pytask_julia.shared import julia
Expand All @@ -33,12 +36,15 @@ def run_jl_script(


@hookimpl
def pytask_collect_task(session, path, name, obj):
def pytask_collect_task(
session: Session, path: Path, name: str, obj: Any
) -> Task | None:
"""Collect a task which is a function.

There is some discussion on how to detect functions in this `thread
<https://stackoverflow.com/q/624926/7523785>`_. :class:`types.FunctionType` does not
detect built-ins which is not possible anyway.

<https://stackoverflow.com/q/624926/7523785>`_. :class:`types.FunctionType`
does notdetect built-ins which is not possible anyway.

"""
__tracebackhide__ = True
Expand Down Expand Up @@ -76,7 +82,7 @@ def pytask_collect_task(session, path, name, obj):
task = Task(
base_name=name,
path=path,
function=_copy_func(run_jl_script),
function=_copy_func(run_jl_script), # type: ignore[arg-type]
depends_on=dependencies,
produces=products,
markers=markers,
Expand Down Expand Up @@ -104,30 +110,34 @@ def pytask_collect_task(session, path, name, obj):
)

return task
return None


def _parse_julia_mark(
mark, default_options, default_serializer, default_suffix, default_project
):
mark: Mark,
default_options: list[str] | None,
default_serializer: Callable[..., str] | str | None,
default_suffix: str | None,
default_project: str | None,
) -> Mark:
"""Parse a Julia mark."""
script, options, serializer, suffix, project = julia(**mark.kwargs)

parsed_kwargs = {}
for arg_name, value, default in [
for arg_name, value, default in (
("script", script, None),
("options", options, default_options),
("serializer", serializer, default_serializer),
]:
parsed_kwargs[arg_name] = value if value else default
):
parsed_kwargs[arg_name] = value or default

if (
isinstance(parsed_kwargs["serializer"], str)
proposed_suffix = (
SERIALIZERS[parsed_kwargs["serializer"]]["suffix"]
if isinstance(parsed_kwargs["serializer"], str)
and parsed_kwargs["serializer"] in SERIALIZERS
):
proposed_suffix = SERIALIZERS[parsed_kwargs["serializer"]]["suffix"]
else:
proposed_suffix = default_suffix
parsed_kwargs["suffix"] = suffix if suffix else proposed_suffix
else default_suffix
)
parsed_kwargs["suffix"] = suffix or proposed_suffix # type: ignore[assignment]

if isinstance(project, (str, Path)):
parsed_kwargs["project"] = project
Expand Down
5 changes: 2 additions & 3 deletions src/pytask_julia/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


@hookimpl
def pytask_parse_config(config):
def pytask_parse_config(config: dict[str, Any]) -> None:
"""Register the julia marker."""
config["markers"]["julia"] = "Tasks which are executed with Julia."
config["julia_serializer"] = config.get("julia_serializer", "json")
Expand All @@ -35,5 +35,4 @@ def _parse_value_or_whitespace_option(value: Any) -> None | list[str]:
return None
if isinstance(value, list):
return list(map(str, value))
else:
raise ValueError(f"'julia_options' is {value} and not a list.")
raise ValueError(f"'julia_options' is {value} and not a list.")
2 changes: 1 addition & 1 deletion src/pytask_julia/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


@hookimpl
def pytask_execute_task_setup(task):
def pytask_execute_task_setup(task: Task) -> None:
"""Check whether environment allows executing Julia files."""
marks = get_marks(task, "julia")
if marks:
Expand Down
9 changes: 5 additions & 4 deletions src/pytask_julia/parametrize.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""Parametrize tasks."""
from __future__ import annotations

from typing import Any

import pytask
from pytask import hookimpl


@hookimpl
def pytask_parametrize_kwarg_to_marker(obj, kwargs):
def pytask_parametrize_kwarg_to_marker(obj: Any, kwargs: dict[str, Any]) -> None:
"""Attach parametrized Julia arguments to the function with a marker."""
if callable(obj):
if "julia" in kwargs:
pytask.mark.julia(**kwargs.pop("julia"))(obj)
if callable(obj) and "julia" in kwargs:
pytask.mark.julia(**kwargs.pop("julia"))(obj)
3 changes: 2 additions & 1 deletion src/pytask_julia/plugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Register hook specifications and implementations."""
from __future__ import annotations

from pluggy import PluginManager
from pytask import hookimpl
from pytask_julia import collect
from pytask_julia import config
Expand All @@ -9,7 +10,7 @@


@hookimpl
def pytask_add_hooks(pm):
def pytask_add_hooks(pm: PluginManager) -> None:
"""Register hook implementations."""
pm.register(collect)
pm.register(config)
Expand Down
Empty file added src/pytask_julia/py.typed
Empty file.
7 changes: 5 additions & 2 deletions src/pytask_julia/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,17 @@ def create_file_name(task: Task, suffix: str) -> str:


def serialize_keyword_arguments(
serializer: str | Callable[dict[str, Any], str],
serializer: str | Callable[..., str],
path_to_serialized: Path,
kwargs: dict[str, Any],
) -> None:
"""Serialize keyword arguments."""
if callable(serializer):
serializer_func = serializer
elif isinstance(serializer, str) and serializer in SERIALIZERS:
serializer_func = SERIALIZERS[serializer]["serializer"]
serializer_func = SERIALIZERS[serializer][
"serializer"
] # type: ignore[assignment]
else: # pragma: no cover
raise ValueError(f"Serializer {serializer!r} is not known.")

Expand Down
6 changes: 4 additions & 2 deletions src/pytask_julia/shared.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""This module contains shared functions."""
from __future__ import annotations

from pathlib import Path
from typing import Any
from typing import Callable
from typing import Iterable
from typing import Sequence
Expand All @@ -9,7 +11,7 @@
def julia(
script: str | Path,
options: str | Iterable[str] | None = None,
serializer: str | Callable[..., str] | str | None = None,
serializer: Callable[..., str] | str | None = None,
suffix: str | None = None,
project: str | Path = None,
) -> tuple[
Expand Down Expand Up @@ -43,7 +45,7 @@ def julia(
return script, options, serializer, suffix, project


def _to_list(scalar_or_iter):
def _to_list(scalar_or_iter: Any) -> list[Any]:
"""Convert scalars and iterables to list.

Parameters
Expand Down
Loading