Skip to content
Draft
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
41 changes: 41 additions & 0 deletions docs/examples/quickstart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# StreamFlow Quickstart Example

This directory contains a minimal working example for the StreamFlow quickstart guide.

## Files

- `hello-workflow.cwl` - Simple CWL workflow that echoes a message
- `inputs.yml` - Input parameters for the workflow
- `streamflow.yml` - StreamFlow configuration for local execution
- `streamflow-docker.yml` - Alternative configuration using Docker (optional)

## Running the Example

```bash
# Run locally
streamflow run streamflow.yml

# Check output
cat output.txt

# Run with Docker (optional - requires Docker)
streamflow run streamflow-docker.yml
```

## Expected Output

The workflow should create an `output.txt` file containing:
```
Hello from StreamFlow!
```

## What It Demonstrates

- Basic CWL CommandLineTool definition
- StreamFlow configuration structure
- Local execution (default)
- Docker deployment (optional)

## Documentation

See the complete quickstart guide: `docs/source/user-guide/quickstart.rst`
12 changes: 12 additions & 0 deletions docs/examples/quickstart/hello-workflow.cwl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cwlVersion: v1.2
class: CommandLineTool
baseCommand: echo
inputs:
message:
type: string
inputBinding:
position: 1
outputs:
output:
type: stdout
stdout: output.txt
1 change: 1 addition & 0 deletions docs/examples/quickstart/inputs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
message: "Hello from StreamFlow!"
8 changes: 8 additions & 0 deletions docs/examples/quickstart/streamflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: v1.0

workflows:
hello-workflow:
type: cwl
config:
file: hello-workflow.cwl
settings: inputs.yml
169 changes: 93 additions & 76 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,65 +22,78 @@

import streamflow.config.schema

project = 'StreamFlow'
copyright = '2023, Alpha Research Group, Computer Science Dept., University of Torino'
author = 'Iacopo Colonnelli'
version = '0.2'
release = '0.2.0'
project = "StreamFlow"
copyright = "2023, Alpha Research Group, Computer Science Dept., University of Torino"
author = "Iacopo Colonnelli"
version = "0.2"
release = "0.2.0"

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosectionlabel',
'sphinx.ext.extlinks',
'sphinx-jsonschema',
'sphinx_llms_txt',
'sphinx_rtd_theme'
"sphinx.ext.autodoc",
"sphinx.ext.autosectionlabel",
"sphinx.ext.extlinks",
"sphinx-jsonschema",
"sphinx_llms_txt",
"sphinx_rtd_theme",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = [
]
exclude_patterns = []

# -- Options for HTML output -------------------------------------------------

html_logo = 'images/streamflow_logo.png'
html_logo = "images/streamflow_logo.png"

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]

# Control table of contents depth
toctree_collapse = True


def setup(app):
app.add_css_file('theme_overrides.css')
app.add_css_file("theme_overrides.css")


# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
"logo_only": True
"logo_only": True,
"navigation_depth": 2, # Show 2-level TOC in sidebar
"collapse_navigation": False, # Keep navigation expanded
"includehidden": False, # Do not show hidden toctrees
"titles_only": True, # Show only titles
}

extlinks = {
'config-schema': ('https://raw.githubusercontent.com/alpha-unito/streamflow/' + release +
'/streamflow/config/schemas/v1.0/%s', 'GH#'),
'repo': ('https://github.com/alpha-unito/streamflow/tree/' + release + '/%s', 'GH#')
"config-schema": (
"https://raw.githubusercontent.com/alpha-unito/streamflow/"
+ release
+ "/streamflow/config/schemas/v1.0/%s",
"GH#",
),
"repo": (
"https://github.com/alpha-unito/streamflow/tree/" + release + "/%s",
"GH#",
),
}


Expand All @@ -107,18 +120,18 @@ def setup(app):

def _patched_simpletype(self, schema):
rows = []
if 'title' in schema and (not self.options['lift_title'] or self.nesting > 1):
del schema['title']
if "title" in schema and (not self.options["lift_title"] or self.nesting > 1):
del schema["title"]
self._check_description(schema, rows)
if 'type' in schema:
if '$ref' in schema:
if "type" in schema:
if "$ref" in schema:
ref = self._reference(schema)
rows.extend(self._prepend(self._cell('type'), ref))
del schema['type']
elif type(schema['type']) == list:
cells = [self._line(self._decodetype(t)) for t in schema['type']]
rows.extend(self._prepend(self._cell('type'), cells))
del schema['type']
rows.extend(self._prepend(self._cell("type"), ref))
del schema["type"]
elif type(schema["type"]) == list:
cells = [self._line(self._decodetype(t)) for t in schema["type"]]
rows.extend(self._prepend(self._cell("type"), cells))
del schema["type"]
rows.extend(_original_simpletype(self, schema))
return rows

Expand All @@ -128,18 +141,18 @@ def _patched_simpletype(self, schema):


def _patched_arraytype(self, schema):
if 'items' in schema:
if type(schema['items']) == list:
if "items" in schema:
if type(schema["items"]) == list:
return _original_arraytype(self, schema)
else:
schema['unique'] = 'uniqueItems' in schema['items']
if 'type' in schema['items']:
schema['type'] = schema['items']['type'] + '[]'
schema["unique"] = "uniqueItems" in schema["items"]
if "type" in schema["items"]:
schema["type"] = schema["items"]["type"] + "[]"
rows = self._simpletype(schema)
return rows
else:
rows = _original_arraytype(self, schema)
rows.extend(self._bool_or_object(schema, 'unique'))
rows.extend(self._bool_or_object(schema, "unique"))
return rows
else:
return _original_arraytype(self, schema)
Expand All @@ -150,8 +163,8 @@ def _patched_arraytype(self, schema):


def _patched_objecttype(self, schema):
if 'additionalProperties' in schema:
del schema['additionalProperties']
if "additionalProperties" in schema:
del schema["additionalProperties"]
return _original_objecttype(self, schema)


Expand All @@ -167,11 +180,11 @@ def _patched_objectproperties(self, schema, key):
for prop in schema[key].keys():
# insert spaces around the regexp OR operator
# allowing the regexp to be split over multiple lines.
proplist = prop.split('|')
dispprop = self._escape(' | '.join(proplist))
if 'required' in schema:
if prop in schema['required']:
dispprop = f'**{dispprop}**\n(required)'
proplist = prop.split("|")
dispprop = self._escape(" | ".join(proplist))
if "required" in schema:
if prop in schema["required"]:
dispprop = f"**{dispprop}**\n(required)"
label = self._cell(dispprop)

if isinstance(schema[key][prop], dict):
Expand All @@ -188,18 +201,18 @@ def _patched_objectproperties(self, schema, key):

def _patched_complexstructures(self, schema):
rows = []
if 'oneOf' in schema:
if "oneOf" in schema:
types = []
for obj in schema['oneOf']:
if 'type' in obj:
if obj['type'] == 'object' and '$ref' in obj:
for obj in schema["oneOf"]:
if "type" in obj:
if obj["type"] == "object" and "$ref" in obj:
types.extend(self._reference(obj))
elif obj['type'] != 'null':
types.append(self._line(self._decodetype(obj['type'])))
del obj['type']
if not list(filter(bool, schema['oneOf'])):
del schema['oneOf']
rows.extend(self._prepend(self._cell('type'), types))
elif obj["type"] != "null":
types.append(self._line(self._decodetype(obj["type"])))
del obj["type"]
if not list(filter(bool, schema["oneOf"])):
del schema["oneOf"]
rows.extend(self._prepend(self._cell("type"), types))
rows.extend(_original_complexstructures(self, schema))
return rows

Expand All @@ -210,28 +223,28 @@ def _patched_complexstructures(self, schema):

def patched_transform(self, schema):
table, definitions = original_transform(self, schema)
table['classes'] += ['jsonschema-table']
table["classes"] += ["jsonschema-table"]
return table, definitions


original_transform = sjs_wide_format.WideFormat.transform
sjs_wide_format.WideFormat.transform = patched_transform


def patched_run(self, schema, pointer=''):
if 'id' in schema:
del schema['id']
elif '$id' in schema:
del schema['$id']
if 'type' in schema:
del schema['type']
if 'required' in schema and 'properties' in schema:
def patched_run(self, schema, pointer=""):
if "id" in schema:
del schema["id"]
elif "$id" in schema:
del schema["$id"]
if "type" in schema:
del schema["type"]
if "required" in schema and "properties" in schema:
props = {}
for prop in schema['required']:
if prop in schema['properties']:
props[prop] = schema['properties'][prop]
del schema['properties'][prop]
schema['properties'] = {**props, **schema['properties']}
for prop in schema["required"]:
if prop in schema["properties"]:
props[prop] = schema["properties"][prop]
del schema["properties"][prop]
schema["properties"] = {**props, **schema["properties"]}
return original_run(self, schema, pointer)


Expand All @@ -240,19 +253,23 @@ def patched_run(self, schema, pointer=''):


def patched_from_url(self, url):
root_schema = json.loads(streamflow.config.schema.SfSchema().dump(version='v1.0'))
defs = root_schema.get('$defs', root_schema.get('definitions', {}))
root_schema = json.loads(streamflow.config.schema.SfSchema().dump(version="v1.0"))
defs = root_schema.get("$defs", root_schema.get("definitions", {}))
if url in defs:
schema = defs[url]
if '$ref' in schema and not schema['$ref'].startswith('#'):
ref_id, ref_pointer = self._splitpointer(urljoin(schema['$id'], schema['$ref']))
if "$ref" in schema and not schema["$ref"].startswith("#"):
ref_id, ref_pointer = self._splitpointer(
urljoin(schema["$id"], schema["$ref"])
)
ref_schema = defs[ref_id]
if ref_pointer:
ref_schema = self.resolve_pointer(ref_schema, ref_pointer)
schema = ref_schema | schema
schema['properties'] = ref_schema.get('properties', {}) | schema.get('properties', {})
schema['properties'] = dict(sorted(schema['properties'].items()))
del schema['$ref']
schema["properties"] = ref_schema.get("properties", {}) | schema.get(
"properties", {}
)
schema["properties"] = dict(sorted(schema["properties"].items()))
del schema["$ref"]
return json.dumps(schema), url
else:
raise self.error(
Expand Down
Loading
Loading