nf-meta 0.2.4__tar.gz → 0.3.0.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nf_meta-0.2.4/src/nf_meta.egg-info → nf_meta-0.3.0.dev0}/PKG-INFO +2 -2
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/README.md +1 -1
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/pyproject.toml +10 -1
- nf_meta-0.3.0.dev0/src/nf_meta/__main__.py +135 -0
- nf_meta-0.3.0.dev0/src/nf_meta/core/cache.py +39 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/errors.py +1 -1
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/events.py +1 -1
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/graph.py +3 -1
- nf_meta-0.3.0.dev0/src/nf_meta/core/models.py +742 -0
- nf_meta-0.3.0.dev0/src/nf_meta/core/nf_core_utils.py +521 -0
- nf_meta-0.3.0.dev0/src/nf_meta/core/nf_param_validation.py +124 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/session.py +17 -5
- nf_meta-0.3.0.dev0/src/nf_meta/editor/__init__.py +41 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/backend/__init__.py +1 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/backend/api.py +232 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/backend/serializers.py +40 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/base_editor.py +46 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/browser_editor.py +99 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/editor.py +20 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/frontend_dist/assets/index-BeQMBiE2.css +1 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/frontend_dist/assets/index-C23FgNmk.js +202 -0
- nf_meta-0.3.0.dev0/src/nf_meta/editor/frontend_dist/assets/nfcore-BTUAiOeh.svg +76 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/index.html +2 -2
- nf_meta-0.3.0.dev0/src/nf_meta/editor/utils.py +20 -0
- nf_meta-0.3.0.dev0/src/nf_meta/runner/__init__.py +41 -0
- nf_meta-0.3.0.dev0/src/nf_meta/runner/base_runner.py +54 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/runner/python_runner.py +125 -111
- nf_meta-0.3.0.dev0/src/nf_meta/runner/runner.py +50 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/runner/utils.py +55 -0
- nf_meta-0.3.0.dev0/src/nf_meta/runner/workflow_run.py +165 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0/src/nf_meta.egg-info}/PKG-INFO +2 -2
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta.egg-info/SOURCES.txt +12 -3
- nf_meta-0.2.4/src/nf_meta/__main__.py +0 -85
- nf_meta-0.2.4/src/nf_meta/core/models.py +0 -441
- nf_meta-0.2.4/src/nf_meta/core/nf_core_utils.py +0 -74
- nf_meta-0.2.4/src/nf_meta/editor/__init__.py +0 -66
- nf_meta-0.2.4/src/nf_meta/editor/backend/__init__.py +0 -1
- nf_meta-0.2.4/src/nf_meta/editor/backend/api.py +0 -141
- nf_meta-0.2.4/src/nf_meta/editor/backend/serializers.py +0 -25
- nf_meta-0.2.4/src/nf_meta/editor/frontend_dist/assets/index-Dn4aaNvP.js +0 -202
- nf_meta-0.2.4/src/nf_meta/editor/frontend_dist/assets/index-ESZ-ptZu.css +0 -1
- nf_meta-0.2.4/src/nf_meta/runner/__init__.py +0 -4
- nf_meta-0.2.4/src/nf_meta/runner/runner.py +0 -65
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/LICENSE +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/MANIFEST.in +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/setup.cfg +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/__init__.py +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/__init__.py +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/core/history.py +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/editor/frontend_dist/vite.svg +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/runner/cascade_runner.py +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta/runner/errors.py +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta.egg-info/dependency_links.txt +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta.egg-info/entry_points.txt +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta.egg-info/requires.txt +0 -0
- {nf_meta-0.2.4 → nf_meta-0.3.0.dev0}/src/nf_meta.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nf-meta
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0.dev0
|
|
4
4
|
Summary: nf-meta is a cli tool for building, validating and running meta-pipelines based on the Nextflow workflow language
|
|
5
5
|
Author-email: Julian Flesch <julian.flesch@qbic.uni-tuebingen.de>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -85,7 +85,7 @@ This project features a small editor which intends to ease the creation and upda
|
|
|
85
85
|
of these config files, by visualizing the config as a graph and
|
|
86
86
|
offering user-firendly form for entering and validating values.
|
|
87
87
|
|
|
88
|
-

|
|
88
|
+

|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
## Metapipeline Runners
|
|
@@ -61,7 +61,7 @@ This project features a small editor which intends to ease the creation and upda
|
|
|
61
61
|
of these config files, by visualizing the config as a graph and
|
|
62
62
|
offering user-firendly form for entering and validating values.
|
|
63
63
|
|
|
64
|
-

|
|
64
|
+

|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
## Metapipeline Runners
|
|
@@ -13,7 +13,7 @@ namespaces = false
|
|
|
13
13
|
|
|
14
14
|
[project]
|
|
15
15
|
name = "nf-meta"
|
|
16
|
-
version = "0.
|
|
16
|
+
version = "0.3.0-dev"
|
|
17
17
|
description = "nf-meta is a cli tool for building, validating and running meta-pipelines based on the Nextflow workflow language"
|
|
18
18
|
readme = "README.md"
|
|
19
19
|
authors = [
|
|
@@ -47,6 +47,7 @@ dev = [
|
|
|
47
47
|
"twine>=6.2.0",
|
|
48
48
|
"pytest>=9.0.3",
|
|
49
49
|
"pytest-mock>=3.15.1",
|
|
50
|
+
"mypy>=2.1.0",
|
|
50
51
|
"types-networkx>=3.6.1.20260408",
|
|
51
52
|
"types-pyyaml>=6.0.12.20260408",
|
|
52
53
|
"types-requests>=2.33.0.20260503",
|
|
@@ -54,3 +55,11 @@ dev = [
|
|
|
54
55
|
|
|
55
56
|
[tool.pytest.ini_options]
|
|
56
57
|
testpaths = ["tests"]
|
|
58
|
+
|
|
59
|
+
[tool.mypy]
|
|
60
|
+
python_version = "3.12"
|
|
61
|
+
mypy_path = "src"
|
|
62
|
+
|
|
63
|
+
[[tool.mypy.overrides]]
|
|
64
|
+
module = ["uvicorn", "uvicorn.*"]
|
|
65
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from nf_meta.core.errors import (
|
|
4
|
+
GraphValidationError,
|
|
5
|
+
ValidationError,
|
|
6
|
+
format_errors_for_cli,
|
|
7
|
+
)
|
|
8
|
+
from nf_meta.runner import (
|
|
9
|
+
run_metapipeline,
|
|
10
|
+
get_registered_runners,
|
|
11
|
+
RunOptions,
|
|
12
|
+
NfMetaRunnerError,
|
|
13
|
+
)
|
|
14
|
+
from nf_meta.core.graph import MetaworkflowGraph
|
|
15
|
+
from nf_meta.core.session import start_session
|
|
16
|
+
from nf_meta.editor import get_registered_editors, EditorOptions, run_editor
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@click.group()
|
|
20
|
+
@click.version_option()
|
|
21
|
+
def cli() -> None:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@click.command("editor")
|
|
26
|
+
@click.option("--verbose", "-v", is_flag=True, help="Enables verbose mode")
|
|
27
|
+
@click.option(
|
|
28
|
+
"--editor",
|
|
29
|
+
"-e",
|
|
30
|
+
type=click.Choice(get_registered_editors()),
|
|
31
|
+
default="browser",
|
|
32
|
+
help="Editor backend to use",
|
|
33
|
+
)
|
|
34
|
+
@click.option("--host", help="Host to bind the editor server to")
|
|
35
|
+
@click.option(
|
|
36
|
+
"--port",
|
|
37
|
+
type=int,
|
|
38
|
+
help="Port for the editor server (auto-assigned if omitted)",
|
|
39
|
+
)
|
|
40
|
+
@click.argument("config", required=False, type=click.Path())
|
|
41
|
+
def edit_browser(config, verbose, editor, host, port):
|
|
42
|
+
try:
|
|
43
|
+
start_session(config)
|
|
44
|
+
opts = EditorOptions(editor_name=editor)
|
|
45
|
+
if host is not None:
|
|
46
|
+
opts.host = host
|
|
47
|
+
if port is not None:
|
|
48
|
+
opts.port = port
|
|
49
|
+
run_editor(opts)
|
|
50
|
+
except (GraphValidationError, ValidationError) as e:
|
|
51
|
+
click.echo(format_errors_for_cli(e))
|
|
52
|
+
raise SystemExit(1)
|
|
53
|
+
except FileNotFoundError as e:
|
|
54
|
+
click.echo(click.style(e, fg="red"))
|
|
55
|
+
raise SystemExit(1)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@click.command("validate")
|
|
59
|
+
@click.argument("config", type=click.Path())
|
|
60
|
+
@click.option("--verbose", "-v", is_flag=True, help="Enables verbose mode")
|
|
61
|
+
def validate_config(config, verbose):
|
|
62
|
+
try:
|
|
63
|
+
g = MetaworkflowGraph.from_file(config)
|
|
64
|
+
click.echo(click.style("✓ Config is valid", fg="green"))
|
|
65
|
+
except (GraphValidationError, ValidationError) as e:
|
|
66
|
+
click.echo(format_errors_for_cli(e))
|
|
67
|
+
raise SystemExit(1)
|
|
68
|
+
except FileNotFoundError as e:
|
|
69
|
+
click.echo(click.style(e, fg="red"))
|
|
70
|
+
raise SystemExit(1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@click.command("run")
|
|
74
|
+
@click.argument("config", type=click.Path())
|
|
75
|
+
@click.option("--verbose", "-v", is_flag=True, help="Enables verbose mode")
|
|
76
|
+
@click.option(
|
|
77
|
+
"--runner",
|
|
78
|
+
"-r",
|
|
79
|
+
prompt=True,
|
|
80
|
+
type=click.Choice(get_registered_runners()),
|
|
81
|
+
default="python",
|
|
82
|
+
)
|
|
83
|
+
@click.option("--resume", is_flag=True, help="Resume a previous run")
|
|
84
|
+
@click.option(
|
|
85
|
+
"--output-lines",
|
|
86
|
+
"-l",
|
|
87
|
+
default="25",
|
|
88
|
+
type=int,
|
|
89
|
+
help="Number of lines of workflow output to stream to output window (Only for Python Runner!)",
|
|
90
|
+
)
|
|
91
|
+
@click.option("--start", "-s", type=str, help="ID of workflow to start from")
|
|
92
|
+
@click.option("--target", "-t", type=str, help="ID of workflow to run until")
|
|
93
|
+
@click.option(
|
|
94
|
+
"--profile",
|
|
95
|
+
"-p",
|
|
96
|
+
type=str,
|
|
97
|
+
help="Nextflow profile to apply globally, taking precedent over config values.",
|
|
98
|
+
)
|
|
99
|
+
@click.option(
|
|
100
|
+
"--stub",
|
|
101
|
+
is_flag=True,
|
|
102
|
+
help="Run all workflows as stub runs (passes -stub to Nextflow)",
|
|
103
|
+
)
|
|
104
|
+
def run(config, verbose, runner, resume, output_lines, start, target, profile, stub):
|
|
105
|
+
try:
|
|
106
|
+
run_options = RunOptions(
|
|
107
|
+
runner_name=runner,
|
|
108
|
+
verbose=verbose,
|
|
109
|
+
output_lines=output_lines,
|
|
110
|
+
nf_profile=profile,
|
|
111
|
+
stub=stub,
|
|
112
|
+
resume=resume,
|
|
113
|
+
start=start,
|
|
114
|
+
target=target,
|
|
115
|
+
)
|
|
116
|
+
g = MetaworkflowGraph.from_file(config)
|
|
117
|
+
run_metapipeline(g, run_options)
|
|
118
|
+
except (GraphValidationError, ValidationError) as e:
|
|
119
|
+
click.echo(format_errors_for_cli(e))
|
|
120
|
+
raise SystemExit(1)
|
|
121
|
+
except NfMetaRunnerError as e:
|
|
122
|
+
click.echo(click.style(e.message, fg="red"))
|
|
123
|
+
raise SystemExit(1)
|
|
124
|
+
except FileNotFoundError as e:
|
|
125
|
+
click.echo(click.style(e, fg="red"))
|
|
126
|
+
raise SystemExit(1)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
cli.add_command(edit_browser)
|
|
130
|
+
cli.add_command(validate_config)
|
|
131
|
+
cli.add_command(run)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
cli()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
_ENV_VAR = "NF_META_CACHE_DIR"
|
|
10
|
+
GLOBAL_CACHE_DIR: Path = Path(
|
|
11
|
+
os.environ.get(_ENV_VAR) or Path.home() / ".cache" / "nf-meta"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def schema_cache_path(url: str, version: str) -> Path:
|
|
16
|
+
key = hashlib.sha256(f"{url}@{version}".encode()).hexdigest()[:16]
|
|
17
|
+
return GLOBAL_CACHE_DIR / "schemas" / f"{key}.json"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def read_schema_cache(url: str, version: str) -> dict | None:
|
|
21
|
+
path = schema_cache_path(url, version)
|
|
22
|
+
if not path.exists():
|
|
23
|
+
return None
|
|
24
|
+
try:
|
|
25
|
+
with open(path) as f:
|
|
26
|
+
return json.load(f)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
logger.warning("Failed to read schema cache at %s: %s", path, e)
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def write_schema_cache(url: str, version: str, schema: dict) -> None:
|
|
33
|
+
path = schema_cache_path(url, version)
|
|
34
|
+
try:
|
|
35
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
with open(path, "w") as f:
|
|
37
|
+
json.dump(schema, f)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
logger.warning("Failed to write schema cache to %s: %s", path, e)
|
|
@@ -7,9 +7,9 @@ import networkx as nx
|
|
|
7
7
|
|
|
8
8
|
from .models import (
|
|
9
9
|
MetaworkflowConfig,
|
|
10
|
-
Workflow,
|
|
11
10
|
GlobalOptions,
|
|
12
11
|
Transition,
|
|
12
|
+
Workflow,
|
|
13
13
|
load_config,
|
|
14
14
|
dump_config,
|
|
15
15
|
CONFIG_VERSION_MAX,
|
|
@@ -167,6 +167,8 @@ class MetaworkflowGraph:
|
|
|
167
167
|
def validate_param_references(self, wf: Workflow):
|
|
168
168
|
errors = []
|
|
169
169
|
for ref in wf.field_refs:
|
|
170
|
+
if ref.namespace != "params":
|
|
171
|
+
continue # output references not yet validated
|
|
170
172
|
referenced_wf = self.get_workflow_by_id(ref.target_wf_id)
|
|
171
173
|
if not referenced_wf:
|
|
172
174
|
errors.append(
|