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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- `ewokstasks` directive displays task tags.

## [2.2.1] - 2026-04-21

### Fixed
Expand Down
33 changes: 33 additions & 0 deletions doc/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@

::::

Class tasks can be classified by using the [`tags` class argument](https://ewokscore.readthedocs.io/en/latest/howtoguides/task_discovery.html#how-to-tag-tasks). These tags will also be displayed if present

::::{tab-set}

:::{tab-item} Python

```{literalinclude} ../src/ewokssphinx/tests/dummy_tasks_tags.py
:language: python
```

:::

:::{tab-item} reST

```rst
.. ewokstasks:: ewokssphinx.tests.dummy_tasks_tags
:task-type: class
```

:::

:::{tab-item} Sphinx

```{ewokstasks} ewokssphinx.tests.dummy_tasks_tags
:task-type: class
```

:::

::::


## Class with pydantic model

Expand Down Expand Up @@ -119,6 +150,8 @@ If the task pydantic models contain themselves pydantic models, the nested model
::::




## Method

::::{tab-set}
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
requires-python = ">=3.10"
dependencies = [
"sphinx",
"ewokscore >=3.1.0",
"ewokscore >=5.1.0rc6",
"pydantic",
]

Expand Down
1 change: 1 addition & 0 deletions src/ewokssphinx/ewoks_task_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def discover_tasks(
"inputs": inputs,
"outputs": outputs,
"submodels": {k: _parse_pydantic_model(v) for k, v in submodels.items()},
"tags": task.get("tags", []),
}
_ = TaskDescription(**serialized_task)

Expand Down
5 changes: 5 additions & 0 deletions src/ewokssphinx/ewokssphinx.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@
.ewokssphinx-task .ewokssphinx-examples li>div {
margin: 0;
}

.ewokssphinx-task .ewokssphinx-tag {
border-radius: 0.75em;
padding: 0.1em 0.6em;
}
25 changes: 17 additions & 8 deletions src/ewokssphinx/sphinx_task_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ def _task_section(directive: SphinxDirective, task: dict[str, Any]) -> nodes.sec
if task["description"]:
section.extend(_rst_to_nodes(directive, task["description"]))

# Identifier + task type
section.append(
nodes.field_list(
"",
_field_node("Identifier", nodes.literal(text=task["task_identifier"])),
_field_node("Task type", nodes.Text(task["task_type"])),
)
)
# Identifier + task type + tags
fields = [
_field_node("Identifier", nodes.literal(text=task["task_identifier"])),
_field_node("Task type", nodes.Text(task["task_type"])),
]
tags = task.get("tags")
if tags:
fields.append(_field_node("Tags", _tags_node(tags)))
section.append(nodes.field_list("", *fields))

section.append(
_field_list(directive, {"inputs": task["inputs"], "outputs": task["outputs"]})
Expand Down Expand Up @@ -89,6 +90,14 @@ def _field_node(name: str, body: nodes.Element) -> nodes.field:
)


def _tags_node(tags: list[str]) -> nodes.inline:
tag_nodes = []
for tag in tags:
tag_nodes.append(nodes.literal(text=tag, classes=["ewokssphinx-tag"]))
tag_nodes.append(nodes.Text(" "))
return nodes.inline("", "", *tag_nodes[:-1], classes=["ewokssphinx-tags"])


def _term_node(name: str, is_required: bool) -> nodes.term:
"""
Create a term:
Expand Down
22 changes: 22 additions & 0 deletions src/ewokssphinx/tests/dummy_tasks_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ewokscore import Task


class XrfTask(Task, output_names=["result"], tags=["xrf", "imaging"]):
"""XRF task"""

def run(self):
pass


class XasTask(Task, output_names=["result"], tags=["xas"]):
"""XAS task"""

def run(self):
pass


class UntaggedTask(Task, output_names=["result"]):
"""Untagged task"""

def run(self):
pass
30 changes: 30 additions & 0 deletions src/ewokssphinx/tests/test_task_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from docutils import nodes
from sphinx.testing import restructuredtext


def test_ewokstasks_tags(app):
parsed_nodes = restructuredtext.parse(
app,
""".. ewokstasks:: ewokssphinx.tests.dummy_tasks_tags
:task-type: class
""",
)

assert _task_tags(parsed_nodes) == {
"XrfTask": ["imaging", "xrf"],
"XasTask": ["xas"],
"UntaggedTask": [],
}


def _task_tags(document: nodes.document) -> dict[str, list[str]]:
"""Map task names to their tags."""
tags = {}
for field_list in document.findall(nodes.field_list):
task_name = field_list.parent.next_node(nodes.title).astext()
tags[task_name] = [
node.astext()
for node in field_list.findall(nodes.literal)
if "ewokssphinx-tag" in node["classes"]
]
return tags
1 change: 1 addition & 0 deletions src/ewokssphinx/type_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class TaskDescription(BaseModel, extra="forbid"):
inputs: list[TaskParameter]
outputs: list[TaskParameter]
submodels: dict[str, list[TaskParameter]]
tags: list[str] = []


ParameterDescription = dict[str, str | list[Any] | bool | None]
Loading