Skip to content
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

Expressions, Parameters and Renderers #55

Merged
merged 108 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
2e7e6e7
wip(renderers): can pick renderers dynamically
philtweir Jul 20, 2024
aad87a5
fix(renderers): make the renderer semantics less janky
philtweir Jul 20, 2024
c58c17e
feat(renderers): add the ability to pass renderer arguments via CLI/YAML
philtweir Jul 20, 2024
d792f76
feat(renderers): add way to output subworkflows to files
philtweir Jul 20, 2024
b2c10e2
feat: support list/tuple return values
philtweir Jul 24, 2024
f9e6c9b
feat(annotations): add ability to annotate variables
philtweir Aug 3, 2024
d5b8c65
fix: correct tests
philtweir Aug 3, 2024
470de20
wip: add configuration
philtweir Aug 3, 2024
be9b862
fix: scope thread pools to a single render call and add context copying
philtweir Aug 3, 2024
7c34dbe
fix: make sure the globals are updated when a subworkflow is running
philtweir Aug 4, 2024
c6dc355
fix: tests
philtweir Aug 6, 2024
a7c1fe9
fix: integrate flatten_all_nested configuration
philtweir Aug 6, 2024
dee6815
fix: correctly handle flattened nested tasks
philtweir Aug 6, 2024
363be81
fix: confirm tuples can be returned
philtweir Aug 6, 2024
7aeccd9
fix: step reference works as tuple
philtweir Aug 6, 2024
03c8c8b
fix: tidy up type parsing
philtweir Aug 6, 2024
b50b150
fix: nested raw is parseable
philtweir Aug 6, 2024
109dbf9
fix(annotations): correct name to AtRender
philtweir Aug 7, 2024
6cb2ca1
feat(sympy): handle arithmetic/structure manipulation of references
philtweir Aug 10, 2024
0f846e7
feat(sympy): more flexible parameter support
philtweir Aug 10, 2024
ff81ad4
fix: fix render load order
philtweir Aug 10, 2024
e3b9b28
feat(iterated): allow spreading
philtweir Aug 11, 2024
38825fa
feat(fields): make it possible to use a plain dict if configured for …
philtweir Aug 11, 2024
0f047fb
fix: is_raw_type should handle union types
philtweir Aug 11, 2024
9468595
feat(positional): allow positional arguments if configuration overrid…
philtweir Aug 11, 2024
333967f
fix(sympy): support none in dicts
philtweir Aug 11, 2024
079c00b
fix(sympy): support none in dicts
philtweir Aug 11, 2024
213c514
fix: expressions should consider Raw as a raw type
philtweir Aug 11, 2024
08db69f
fix: sorted should not break for two identical steps
philtweir Aug 11, 2024
3dd35d1
fix: efficiency improvements
philtweir Aug 12, 2024
7e8ab1a
fix: efficiency improvements
philtweir Aug 12, 2024
2aba6e6
fix: efficiency improvements
philtweir Aug 12, 2024
36c74f1
feat: add construct args to CLI
philtweir Aug 13, 2024
0517594
fix: make field separator configurable
philtweir Aug 14, 2024
9b5d03a
fix: construct kwargs used to set_configuration
philtweir Aug 14, 2024
77c46bf
fix: construct kwargs used to set_configuration
philtweir Aug 14, 2024
19f1a38
fix: ignore annotations when looking at fieldability
philtweir Aug 14, 2024
ca47bb8
feat(imports): retrieve annotations from imported modules
philtweir Aug 17, 2024
4bdcd8b
feat(fixed): add loopable parameters
philtweir Aug 17, 2024
5773fae
feat(fixed): add loopable parameters
philtweir Aug 17, 2024
0c2cbdc
fix: better error message for iterating a non-iterable
philtweir Aug 17, 2024
00036d0
fix: add is_firm
philtweir Aug 17, 2024
5b83266
fix: move indexing to find_field
philtweir Aug 18, 2024
fc5309e
fix: resolve the parameter deduplication
philtweir Aug 18, 2024
36d15c6
fix: resolve the parameter deduplication
philtweir Aug 18, 2024
f6de37f
fix: fixups in iteration
philtweir Aug 18, 2024
3dbe777
fix(typing): make types consistent in core
philtweir Aug 19, 2024
bd7ee4a
fix(typing): move @subworkflow to @workflow
philtweir Aug 19, 2024
71a35c3
fix: allow workflows to come from packages
philtweir Aug 19, 2024
03e5209
fix: allow workflows to come from packages
philtweir Aug 19, 2024
7d880c0
fix: allow workflows to come from packages
philtweir Aug 19, 2024
aee1ce1
fix: allow workflows to come from packages
philtweir Aug 19, 2024
fc7495e
feat(iterable): provide len for Fixed
philtweir Aug 19, 2024
093b1d6
fix: allow fields of parameters
philtweir Aug 19, 2024
362af32
fix: reduce number of workflow merges
philtweir Aug 19, 2024
828d58c
fix: render configuration
philtweir Aug 20, 2024
8988037
fix: render configuration
philtweir Aug 20, 2024
f03b58c
fix: address field and hashing consistency
philtweir Aug 20, 2024
8c00247
fix: correct logic for remapping before a workflow has a name
philtweir Aug 20, 2024
0be1fea
fix: remove duplicate __hash__ method
philtweir Aug 20, 2024
0bae23c
fix: tidy up 0.9.2 merge, mostly label corrections
philtweir Aug 24, 2024
8e03137
fix: tests not working
philtweir Aug 24, 2024
173b2c7
fix: make sure we can identify an iterated ref
philtweir Aug 24, 2024
0d8b3d1
docs: tidyup docstrings and structures
philtweir Aug 24, 2024
f1dd479
fix: throw import exceptions
philtweir Aug 24, 2024
5c2d7a2
fix: add configuration for simplify_ids
philtweir Aug 24, 2024
4aef9c4
docs: tidyup docstrings and structures
philtweir Aug 24, 2024
8c84ab2
chore: fix up typehints and disable mypy sympy checking, as sympy doe…
philtweir Aug 24, 2024
b4a4cbc
fix: unbreak the doublequotes
philtweir Aug 24, 2024
394e5a6
fix: unbreak the doublequotes
philtweir Aug 24, 2024
88472e4
fix: unbreak the doublequotes
philtweir Aug 24, 2024
861420b
fix: unbreak the doublequotes
philtweir Aug 24, 2024
99f26fd
wip: try 3.12 in test
philtweir Aug 24, 2024
3274ea9
fix: sort examples - TODO: fix explanatory text
philtweir Aug 24, 2024
1dc5692
chore: fix test linting - TODO: add docstrings
philtweir Aug 25, 2024
3871ef4
fix: make result ordering consistent
philtweir Aug 25, 2024
fc88fb4
fix: ensure that fieldability doesn't mean dask matches references as…
philtweir Aug 25, 2024
780a7d6
fix: restore 3.11 in test
philtweir Aug 25, 2024
3e589ee
ci: add 3.12 to the build matrix
philtweir Aug 25, 2024
0c45e51
fix: restore commented test
philtweir Aug 25, 2024
269e591
fix: mypy issue in tests on 3.11
philtweir Aug 25, 2024
4dfa8bd
chore: fix tests and types for mypy and ruff on 3.11 and 3.12
philtweir Aug 25, 2024
33874a3
ci: allow subclassing any for mypy to enable subclassing Symbol
philtweir Aug 25, 2024
3ec7e39
fix: make __make_reference__ pass workflow if none
philtweir Aug 25, 2024
d0e0d37
fix: remove variable re-use
philtweir Aug 25, 2024
e27db97
feat: can go upwards in fields
philtweir Aug 25, 2024
d890bd3
fix: do not lose the field structure when iterating
philtweir Aug 25, 2024
351d344
fix: add a catch for a bug in the first import
philtweir Aug 29, 2024
3bd55e4
fix: remove unnecessary abstractmethod annotation
philtweir Aug 30, 2024
a7c0d8d
fix: remove unnecessary abstractmethod annotation
philtweir Aug 30, 2024
c32469e
chore: Replace all Unions with | for consistency
KamenDimitrov97 Sep 2, 2024
f6f478b
chore: Refactored render.py:get_render_method for better readability,…
KamenDimitrov97 Sep 2, 2024
e76a0a9
chore: Formated methods
KamenDimitrov97 Sep 2, 2024
a0655c0
docs: Added docstrings to annotation tests
KamenDimitrov97 Sep 2, 2024
aa7d6e4
docs: Added docstrings for tests
KamenDimitrov97 Sep 2, 2024
3bff5e5
fix: Formating
KamenDimitrov97 Sep 2, 2024
7ae5a7a
fix: double-check importing correctly errors if render neither behave…
philtweir Sep 9, 2024
2a2d790
fix: check that importing a non-compliant render module throws an error
philtweir Sep 9, 2024
241f338
fix: double-check importing correctly errors if render neither behave…
philtweir Sep 9, 2024
fe5253c
fix: double-check importing correctly errors if render neither behave…
philtweir Sep 9, 2024
c28a31e
fix: ensure pytest ignores tests._lib
philtweir Sep 9, 2024
713882a
fix: correct name of default_config
philtweir Sep 10, 2024
6714786
fix: remove Graph import from dask.typing in backend_dask as it seems…
philtweir Sep 10, 2024
dd27801
ops: enable example tests in CI
KamenDimitrov97 Sep 17, 2024
b6677c0
feat: Added a test for default renderer
KamenDimitrov97 Sep 17, 2024
3b9ccfe
feat: Added a test for default renderer
KamenDimitrov97 Sep 17, 2024
f519c47
feat: Abstracted write_rendered_output from the main dewret CLI
KamenDimitrov97 Sep 30, 2024
a25d3c2
docs: Updated renderer tutorial with the protocols implementation nee…
KamenDimitrov97 Sep 30, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/python-static-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: python/mypy@v1.8.0
with:
paths: "./src"
- run: pip install .[test] && python -m mypy --strict --install-types --non-interactive ./src ./tests ./example
- run: pip install .[test] && python -m mypy --strict --install-types --allow-subclassing-any --non-interactive ./src ./tests ./example

audit:
runs-on: ubuntu-latest
Expand Down
24 changes: 14 additions & 10 deletions .github/workflows/python-test-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ on: [push, pull_request]
jobs:
unit-pip:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
KamenDimitrov97 marked this conversation as resolved.
Show resolved Hide resolved
steps:
- uses: actions/checkout@v4
- name: Set up Python

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: '3.11'
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip "hatchling < 1.22"
Expand All @@ -17,11 +21,11 @@ jobs:
run: |
pip install pytest pytest-cov
pip install --no-build-isolation --no-deps --disable-pip-version-check -e .
python -m pytest --doctest-modules --ignore=example
python -m pytest --doctest-modules --ignore=example --ignore=tests/_lib
python -m doctest -v docs/*.md
# name: Test examples
# run: |
# (cd example; examples=$(grep "^\\$ " *.py | sed "s/.*\\$ //g"); while IFS= read -r line; do PYTHONPATH=.:$PYTHONPATH eval $line; done <<< "$examples")
name: Test examples
run: |
(cd example; examples=$(grep "^\\$ " *.py | sed "s/.*\\$ //g"); while IFS= read -r line; do PYTHONPATH=.:$PYTHONPATH eval $line; done <<< "$examples")
unit-conda:
runs-on: ubuntu-latest
steps:
Expand All @@ -42,8 +46,8 @@ jobs:
conda install -c /tmp/output/noarch/*.conda --update-deps --use-local dewret -y
conda install pytest
$CONDA/bin/pytest
python -m pytest --doctest-modules --ignore=example
python -m pytest --doctest-modules --ignore=example --ignore=tests/_lib
python -m doctest -v docs/*.md
# name: Test examples
# run: |
# (cd example; examples=$(grep "^\\$ " *.py | sed "s/.*\\$ //g"); while IFS= read -r line; do PYTHONPATH=.:$PYTHONPATH eval $line; done <<< "$examples")
name: Test examples
run: |
(cd example; examples=$(grep "^\\$ " *.py | sed "s/.*\\$ //g"); while IFS= read -r line; do PYTHONPATH=.:$PYTHONPATH eval $line; done <<< "$examples")
4 changes: 2 additions & 2 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ and backends, as well as bespoke serialization or formatting.
>>>
>>> result = increment(num=3)
>>> workflow = construct(result, simplify_ids=True)
>>> cwl = render(workflow)
>>> cwl = render(workflow)["__root__"]
philtweir marked this conversation as resolved.
Show resolved Hide resolved
>>> yaml.dump(cwl, sys.stdout, indent=2)
class: Workflow
cwlVersion: 1.2
inputs:
increment-1-num:
default: 3
label: increment-1-num
label: num
type: int
outputs:
out:
Expand Down
71 changes: 62 additions & 9 deletions docs/renderer_tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,63 @@ class WorkflowDefinition:
}
```

## 3. Create a StepDefinition.
## 3. Ensuring Our Module is Recognized as a Render Module
To have our custom renderer identified by Dewret as a valid renderer, we need to implement the `BaseRenderModule` along with one of the two protocols: `RawRenderModule` or `StructuredRenderModule`.

#### Implementing BaseRenderModule
The `BaseRenderModule` defines the foundation for a custom renderer. To implement this protocol, we need to define the `default_config()` method, which provides default configurations for our renderer.

```python
def default_config() -> CWLRendererConfiguration:
"""Default configuration for this renderer.

This is a hook-like call to give a configuration dict that this renderer
will respect, and sets any necessary default values.

Returns: a dict with (preferably) raw type structures to enable easy setting
from YAML/JSON.
"""
return {
"allow_complex_types": False,
"factories_as_params": False,
}
```

After implementing `BaseRenderModule`, you need to implement either the `RawRenderModule` or `StructuredRenderModule` protocol, depending on how you want to handle the workflow rendering.

#### Implementing either RawRenderModule or StructuredRenderModule
The `StructuredRenderModule` is designed for structured workflows that are directly ready to be output in the respective format (e.g., CWL, Snakemake, etc.). The key method to implement is `render`, which converts a workflow into a structured, serializable format.
```python
def render(
self, workflow: WorkflowProtocol, **kwargs: RenderConfiguration
) -> dict[str, dict[str, RawType]]:
"""Turn a workflow into a serializable structure.

Returns: one or more subworkflows with a `__root__` key representing the outermost workflow, at least.
"""
...
```
In this method:
- You receive a workflow and potentially some optional configurations.
- You return a dictionary where the `__root__` key holds the primary workflow and any additional subworkflows are nested inside the returned structure.

If you prefer more flexibility and want the structuring to be handled by the user, you can implement the `RawRenderModule` protocol. This requires defining the `render_raw` method, which converts a workflow into raw, flat strings.
```python
def render_raw(
self, workflow: WorkflowProtocol, **kwargs: RenderConfiguration
) -> dict[str, str]:
"""Turn a workflow into flat strings.

Returns: one or more subworkflows with a `__root__` key representing the outermost workflow, at least.
"""
...
```
In this method:

- The workflow is rendered as raw, unstructured strings.
- The user is responsible for handling the structuring of the rendered output.

## 4. Create a StepDefinition.

Create a StepsDefinition class create each of the code blocks needed for a rule(step) to be executable in Snakemake.
When you have defined each block in your target workflow language task from [step 1](#1-understand-the-target-workflow-language),
Expand Down Expand Up @@ -128,7 +184,7 @@ class StepDefinition:
}
```

## 4. Create the Separate block definitions.
## 5. Create the Separate block definitions.

In this step, you'll define classes to handle the rendering of each code block required for a rule (step) to be executable in the target workflow language. Each of these classes will encapsulate the logic for converting parts of a workflow step into the target language format.

Expand Down Expand Up @@ -335,7 +391,7 @@ class OutputDefinition:

Integrate these block definitions into the StepDefinition class as demonstrated in [Step 3](#3-create-a-stepsdefinition). Each StepDefinition will use these block definitions to render the complete step in the target workflow language.

## 5. Helper methods.
## 6. Helper methods.

In this step, you'll define helper methods that will assist you in converting workflow components into the target workflow language format. In our case these methods will handle type conversion, extracting method arguments, and computing relative paths.

Expand Down Expand Up @@ -401,11 +457,11 @@ import inspect
import typing

from attrs import define
from dewret.utils import Raw, BasicType
from dewret.workflow import Lazy
from dewret.workflow import Reference, Raw, Workflow, Step, Task
from dewret.utils import BasicType
from dewret.workflow import Reference, Workflow, Step, Task

RawType = typing.Union[BasicType, list[str], list["RawType"], dict[str, "RawType"]]
RawType = BasicType | list[str] | list["RawType"] | dict[str, "RawType"]
```

## To run this example:
Expand All @@ -416,6 +472,3 @@ RawType = typing.Union[BasicType, list[str], list["RawType"], dict[str, "RawType
```shell
python snakemake_tasks.py
```

### Q: Should I add a brief description of dewret in step 1? Should link dewret types/docs etc here?
### A: Get details on how that happens and probably yes.
KamenDimitrov97 marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading