Example #1
0
 def call_as(self, items, meta):
     return D.Call(
         sp(self.filename, meta),
         items[0],
         items[1].value,
         items[2] if len(items) > 2 else dict(),
     )
Example #2
0
 def document(self, items, meta):
     imports = []
     structs = {}
     tasks = []
     workflow = None
     for item in items:
         if isinstance(item, D.Task):
             tasks.append(item)
         elif isinstance(item, D.Workflow):
             if workflow is not None:
                 raise Err.MultipleDefinitions(
                     sp(self.filename, meta),
                     "Document has multiple workflows")
             workflow = item
         elif isinstance(item, D.StructTypeDef):
             if item.name in structs:
                 raise Err.MultipleDefinitions(
                     sp(self.filename, meta),
                     "multiple structs named " + item.name)
             structs[item.name] = item
         elif isinstance(item, lark.Tree) and item.data == "version":
             pass
         elif isinstance(item, D.DocImport):
             imports.append(item)
         else:
             assert False
     return D.Document(sp(self.filename, meta), imports, structs, tasks,
                       workflow)
Example #3
0
 def task(self, items, meta):
     d = {}
     for item in items:
         if isinstance(item, dict):
             for k, v in item.items():
                 if k in d:
                     raise Err.MultipleDefinitions(
                         sp(self.filename, meta), "redundant sections in task"
                     )
                 d[k] = v
         else:
             assert isinstance(item, str)
             assert "name" not in d
             d["name"] = item.value
     return D.Task(
         sp(self.filename, meta),
         d["name"],
         d.get("inputs", []),
         d.get("decls", []),
         d["command"],
         d.get("outputs", []),
         d.get("parameter_meta", {}),
         d.get("runtime", {}),
         d.get("meta", {}),
     )
Example #4
0
 def decl(self, items, meta):
     return D.Decl(
         sp(self.filename, meta),
         items[0],
         items[1].value,
         (items[2] if len(items) > 2 else None),
     )
Example #5
0
def parse_wdl(wdl_path: Path,
              import_dirs: Optional[Sequence[Path]] = (),
              check_quant: bool = False,
              **_) -> Document:
    return Tree.load(str(wdl_path),
                     path=[str(path) for path in import_dirs],
                     check_quant=check_quant)
Example #6
0
def parse_document(
    txt: str, version: Optional[str] = None, uri: str = "", imported: bool = False
) -> D.Document:
    if version is None:
        # for now assume the version is 1.0 if the first line is "version <number>"
        # otherwise draft-2
        version = "draft-2"
        for line in txt.split("\n"):
            line = line.strip()
            if line and line[0] != "#":
                if line.startswith("version ") and line[8].isdigit():
                    version = "1.0"
                break
    if not txt.strip():
        return D.Document(
            SourcePosition(filename=uri, line=0, column=0, end_line=0, end_column=0),
            [],
            [],
            None,
            imported,
        )
    try:
        return _DocTransformer(uri, imported).transform(parse(txt, "document", version))
    except lark.exceptions.UnexpectedCharacters as exn:
        raise Err.ParserError(uri if uri != "" else "(in buffer)") from exn
    except lark.exceptions.UnexpectedToken as exn:
        raise Err.ParserError(uri if uri != "" else "(in buffer)") from exn
Example #7
0
 def task(self, items, meta):
     d = {"noninput_decls": []}
     for item in items:
         if isinstance(item, dict):
             for k, v in item.items():
                 if k == "noninput_decl":
                     d["noninput_decls"].append(v)
                 elif k in d:
                     raise Err.MultipleDefinitions(
                         sp(self.filename, meta),
                         "redundant sections in task")
                 else:
                     d[k] = v
         else:
             assert isinstance(item, str)
             assert "name" not in d
             d["name"] = item.value
     _check_keyword(sp(self.filename, meta), d["name"])
     return D.Task(
         sp(self.filename, meta),
         d["name"],
         d.get("inputs", None),
         d["noninput_decls"],
         d["command"],
         d.get("outputs", []),
         d.get("parameter_meta", {}),
         d.get("runtime", {}),
         d.get("meta", {}),
     )
Example #8
0
def load(uri: str, path: List[str] = [], check_quant: bool = True) -> Document:
    """
    Parse a WDL document given filename/URI, recursively descend into imported documents, then typecheck the tasks and workflow.

    :param path: local filesystem directories to search for imports, in addition to the current working directory

    :param check_quant: set to ``False`` to relax static typechecking of the optional (?) and nonempty (+) type quantifiers. This is discouraged, but may be useful for older WDL workflows which assume less-rigorous static validation of these annotations.
    """
    return Tree.load(uri, path, check_quant)
Example #9
0
 def _get_workflow_name(self, wdl_path: Path, kwargs: dict):
     if "workflow_name" in kwargs:
         return kwargs["workflow_name"]
     elif Tree:
         if "check_quant" not in kwargs:
             kwargs["check_quant"] = False
         doc = Tree.load(str(wdl_path),
                         path=[str(path) for path in self.import_dirs],
                         **kwargs)
         return doc.workflow.name
     else:  # TODO: test this
         return safe_string(wdl_path.stem)
Example #10
0
 def struct(self, items, meta):
     assert len(items) >= 1
     name = items[0]
     _check_keyword(sp(self.filename, meta), name)
     members = {}
     for d in items[1:]:
         assert not d.expr
         if d.name in members:
             raise Err.MultipleDefinitions(sp(self.filename, meta),
                                           "duplicate members in struct")
         members[d.name] = d.type
     return D.StructTypeDef(sp(self.filename, meta), name, members)
Example #11
0
 def workflow(self, items, meta):
     elements = []
     inputs = None
     outputs = None
     output_idents = None
     output_idents_pos = None
     parameter_meta = None
     meta_section = None
     for item in items[1:]:
         if isinstance(item, dict):
             if "inputs" in item:
                 assert inputs is None
                 inputs = item["inputs"]
             elif "outputs" in item:
                 if outputs is not None:
                     raise Err.MultipleDefinitions(
                         sp(self.filename, meta),
                         "redundant sections in workflow")
                 outputs = item["outputs"]
                 if "output_idents" in item:
                     assert output_idents is None
                     output_idents = item["output_idents"]
                     output_idents_pos = item["pos"]
             elif "meta" in item:
                 if meta_section is not None:
                     raise Err.MultipleDefinitions(
                         sp(self.filename, meta),
                         "redundant sections in workflow")
                 meta_section = item["meta"]
             elif "parameter_meta" in item:
                 if parameter_meta is not None:
                     raise Err.MultipleDefinitions(
                         sp(self.filename, meta),
                         "redundant sections in workflow")
                 parameter_meta = item["parameter_meta"]
             else:
                 assert False
         elif isinstance(item, (D.Call, D.Conditional, D.Decl, D.Scatter)):
             elements.append(item)
         else:
             assert False
     _check_keyword(sp(self.filename, meta), items[0].value)
     return D.Workflow(
         sp(self.filename, meta),
         items[0].value,
         inputs,
         elements,
         outputs,
         parameter_meta or dict(),
         meta_section or dict(),
         output_idents,
         output_idents_pos,
     )
Example #12
0
 def import_doc(self, items, meta):
     uri = items[0]
     if len(items) > 1 and isinstance(items[1], str):
         namespace = items[1].value
     else:
         namespace = uri
         try:
             namespace = namespace[namespace.rindex("/") + 1:]
         except ValueError:
             pass
         if namespace.endswith(".wdl"):
             namespace = namespace[:-4]
     _check_keyword(sp(self.filename, meta), namespace)
     aliases = [p for p in items[1:] if isinstance(p, tuple)]
     return D.DocImport(pos=sp(self.filename, meta),
                        uri=uri,
                        namespace=namespace,
                        aliases=aliases,
                        doc=None)
Example #13
0
 def document(self, items, meta):
     imports = []
     tasks = []
     workflow = None
     for item in items:
         if isinstance(item, D.Task):
             tasks.append(item)
         elif isinstance(item, D.Workflow):
             if workflow is not None:
                 raise Err.MultipleDefinitions(
                     sp(self.filename, meta), "Document has multiple workflows"
                 )
             workflow = item
         elif isinstance(item, lark.Tree) and item.data == "version":
             pass
         elif isinstance(item, dict) and "import" in item:
             imports.append(item["import"])
         else:
             assert False
     return D.Document(sp(self.filename, meta), imports, tasks, workflow, self.imported)
Example #14
0
def parse_document(txt: str,
                   version: Optional[str] = None,
                   uri: str = "") -> D.Document:
    if version is None:
        # for now assume the version is 1.0 if the first line is "version <number>"
        # otherwise draft-2
        version = "draft-2"
        for line in txt.split("\n"):
            line = line.strip()
            if line and line[0] != "#":
                if line.startswith("version ") and line[8].isdigit():
                    version = "1.0"
                break
    if not txt.strip():
        return D.Document(
            SourcePosition(filename=uri,
                           line=0,
                           column=0,
                           end_line=0,
                           end_column=0),
            [],
            {},
            [],
            None,
        )
    try:
        return _DocTransformer(uri).transform(parse(txt, "document", version))
    except lark.exceptions.UnexpectedInput as exn:
        pos = SourcePosition(
            filename=(uri if uri != "" else "(buffer)"),
            line=getattr(exn, "line", "?"),
            column=getattr(exn, "column", "?"),
            end_line=getattr(exn, "line", "?"),
            end_column=getattr(exn, "column", "?"),
        )
        raise Err.SyntaxError(pos, str(exn)) from None
    except lark.exceptions.VisitError as exn:
        raise exn.__context__
Example #15
0
 def scatter(self, items, meta):
     return D.Scatter(sp(self.filename, meta), items[0].value, items[1], items[2:])
Example #16
0
 def conditional(self, items, meta):
     return D.Conditional(sp(self.filename, meta), items[0], items[1:])
Example #17
0
 def scatter(self, items, meta):
     _check_keyword(sp(self.filename, meta), items[0].value)
     return D.Scatter(sp(self.filename, meta), items[0].value, items[1],
                      items[2:])
Example #18
0
 def call(self, items, meta):
     return D.Call(sp(self.filename, meta), items[0], None,
                   items[1] if len(items) > 1 else dict())