Event Stream
This example shows how to parse a WDL document into an event stream, printing that stream to the terminal.
sprocket_bio/examples/event_stream.py
import argparse
import pathlib
import sys
from sprocket_bio.diagnostics import Mode, emit_diagnostics
from sprocket_bio.grammar import Severity, SupportedVersion
from sprocket_bio.grammar.grammar import document
from sprocket_bio.grammar.parser import Event
from sprocket_bio.grammar.version import V1
def parse_args() -> argparse.Namespace:
"""Parses command-line arguments and returns them."""
parser = argparse.ArgumentParser(
description="Parses a WDL document and prints the event stream"
)
parser.add_argument(
"source_file",
type=pathlib.Path,
help="path to WDL document",
metavar="<source_file>",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
with open(args.source_file, "rt", encoding="utf-8") as f:
source = f.read()
# Parse the source string into a list of parser events.
events, diagnostics = document(
source, fallback_version=SupportedVersion.V1(V1.ZERO)
)
# Emit diagnostics, if there are any.
emit_diagnostics(
str(args.source_file), source, diagnostics, report_mode=Mode.FULL, colorize=True
)
# If any of the diagnostics are errors, exit.
if any([d.severity is Severity.ERROR for d in diagnostics]):
sys.exit(1)
# Get the byte representation of the source code.
source_bytes = source.encode("utf-8")
indent = 0
# Print all events in the stream.
for event in events:
match event:
case Event.NodeStarted(kind, _):
print(" " * indent + str(kind))
indent += 1
case Event.NodeFinished():
indent -= 1
case Event.Token(kind, span):
# Get the text in the source code represented by this span. We convert the string
# to bytes first, as `Span`s index bytes instead of Unicode code points. Not doing
# so will result in the wrong text being displayed.
token_text = source_bytes[span.start : span.end].decode("utf-8")
print(" " * indent + f"{kind}@{span} {token_text!r}")
if __name__ == "__main__":
main()
If you have the Python bindings installed, you can run the example yourself:
$ python -m sprocket_bio.examples.event_stream example.wdl
SyntaxKind.ROOT_NODE
SyntaxKind.VERSION_STATEMENT_NODE
SyntaxKind.VERSION_KEYWORD@0..7 'version'
SyntaxKind.WHITESPACE@7..8 ' '
SyntaxKind.VERSION@8..11 '1.3'
SyntaxKind.WHITESPACE@11..13 '\n\n'
SyntaxKind.TASK_DEFINITION_NODE
SyntaxKind.TASK_KEYWORD@13..17 'task'
SyntaxKind.WHITESPACE@17..18 ' '
SyntaxKind.IDENT@18..27 'say_hello'
SyntaxKind.WHITESPACE@27..28 ' '
SyntaxKind.OPEN_BRACE@28..29 '{'
SyntaxKind.WHITESPACE@29..34 '\n '
SyntaxKind.INPUT_SECTION_NODE
SyntaxKind.INPUT_KEYWORD@34..39 'input'
SyntaxKind.WHITESPACE@39..40 ' '
SyntaxKind.OPEN_BRACE@40..41 '{'
SyntaxKind.WHITESPACE@41..50 '\n '
SyntaxKind.UNBOUND_DECL_NODE
SyntaxKind.PRIMITIVE_TYPE_NODE
SyntaxKind.STRING_TYPE_KEYWORD@50..56 'String'
SyntaxKind.WHITESPACE@56..57 ' '
SyntaxKind.IDENT@57..65 'greeting'
SyntaxKind.WHITESPACE@65..70 '\n '
SyntaxKind.CLOSE_BRACE@70..71 '}'
SyntaxKind.WHITESPACE@71..77 '\n\n '
SyntaxKind.COMMAND_SECTION_NODE
SyntaxKind.COMMAND_KEYWORD@77..84 'command'
SyntaxKind.WHITESPACE@84..85 ' '
SyntaxKind.OPEN_HEREDOC@85..88 '<<<'
SyntaxKind.LITERAL_COMMAND_TEXT@88..103 '\n echo "'
SyntaxKind.PLACEHOLDER_NODE
SyntaxKind.PLACEHOLDER_OPEN@103..105 '~{'
SyntaxKind.ABANDONED
SyntaxKind.NAME_REF_EXPR_NODE
SyntaxKind.IDENT@105..113 'greeting'
SyntaxKind.CLOSE_BRACE@113..114 '}'
SyntaxKind.LITERAL_COMMAND_TEXT@114..128 ', world!"\n '
SyntaxKind.CLOSE_HEREDOC@128..131 '>>>'
SyntaxKind.WHITESPACE@131..137 '\n\n '
SyntaxKind.OUTPUT_SECTION_NODE
SyntaxKind.OUTPUT_KEYWORD@137..143 'output'
SyntaxKind.WHITESPACE@143..144 ' '
SyntaxKind.OPEN_BRACE@144..145 '{'
SyntaxKind.WHITESPACE@145..154 '\n '
SyntaxKind.BOUND_DECL_NODE
SyntaxKind.PRIMITIVE_TYPE_NODE
SyntaxKind.STRING_TYPE_KEYWORD@154..160 'String'
SyntaxKind.WHITESPACE@160..161 ' '
SyntaxKind.IDENT@161..164 'out'
SyntaxKind.WHITESPACE@164..165 ' '
SyntaxKind.ASSIGNMENT@165..166 '='
SyntaxKind.WHITESPACE@166..167 ' '
SyntaxKind.ABANDONED
SyntaxKind.CALL_EXPR_NODE
SyntaxKind.IDENT@167..178 'read_string'
SyntaxKind.OPEN_PAREN@178..179 '('
SyntaxKind.ABANDONED
SyntaxKind.CALL_EXPR_NODE
SyntaxKind.IDENT@179..185 'stdout'
SyntaxKind.OPEN_PAREN@185..186 '('
SyntaxKind.CLOSE_PAREN@186..187 ')'
SyntaxKind.CLOSE_PAREN@187..188 ')'
SyntaxKind.WHITESPACE@188..193 '\n '
SyntaxKind.CLOSE_BRACE@193..194 '}'
SyntaxKind.WHITESPACE@194..200 '\n\n '
SyntaxKind.REQUIREMENTS_SECTION_NODE
SyntaxKind.REQUIREMENTS_KEYWORD@200..212 'requirements'
SyntaxKind.WHITESPACE@212..213 ' '
SyntaxKind.OPEN_BRACE@213..214 '{'
SyntaxKind.WHITESPACE@214..223 '\n '
SyntaxKind.REQUIREMENTS_ITEM_NODE
SyntaxKind.IDENT@223..232 'container'
SyntaxKind.COLON@232..233 ':'
SyntaxKind.WHITESPACE@233..234 ' '
SyntaxKind.ABANDONED
SyntaxKind.LITERAL_STRING_NODE
SyntaxKind.DOUBLE_QUOTE@234..235 '"'
SyntaxKind.LITERAL_STRING_TEXT@235..248 'ubuntu:latest'
SyntaxKind.DOUBLE_QUOTE@248..249 '"'
SyntaxKind.WHITESPACE@249..254 '\n '
SyntaxKind.CLOSE_BRACE@254..255 '}'
SyntaxKind.WHITESPACE@255..256 '\n'
SyntaxKind.CLOSE_BRACE@256..257 '}'
SyntaxKind.WHITESPACE@257..258 '\n'
Click to view example.wdl source
sprocket_bio/examples/example.wdl
version 1.3
task say_hello {
input {
String greeting
}
command <<<
echo "~{greeting}, world!"
>>>
output {
String out = read_string(stdout())
}
requirements {
container: "ubuntu:latest"
}
}