Source code for toil.wdl.wdl_types

from abc import ABC
from typing import Any, Dict, Optional

from toil.job import Promise


[docs]class WDLRuntimeError(RuntimeError): pass
[docs]class WDLType: """ Represents a primitive or compound WDL type: https://github.com/openwdl/wdl/blob/main/versions/development/SPEC.md#types """ def __init__(self, optional: bool = False): self.optional = optional @property def name(self) -> str: """ Type name as string. Used in display messages / 'mappings.out' if dev mode is enabled. """ raise NotImplementedError @property def default_value(self) -> Optional[str]: """ Default value if optional. """ return None
[docs] def create(self, value: Any, output: bool = False) -> Any: """ Calls at runtime. Returns an instance of the current type. An error may be raised if the value is not in the correct format. :param value: a Python object """ if value is None: # check if input is in fact an optional. if self.optional: return self.default_value else: raise WDLRuntimeError(f"Required input for '{self.name}' type not specified.") if isinstance(value, Promise): return value return self._create(value)
def _create(self, value: Any) -> Any: raise NotImplementedError
[docs] def __eq__(self, other: Any) -> bool: return self.name.__eq__(other)
[docs] def __str__(self) -> str: return self.name.__str__()
[docs] def __repr__(self) -> str: return self.name.__repr__()
[docs]class WDLCompoundType(WDLType, ABC): """ Represents a WDL compound type. """
[docs]class WDLStringType(WDLType): """ Represents a WDL String primitive type.""" @property def name(self) -> str: return 'String' @property def default_value(self) -> str: return '' def _create(self, value: Any) -> Any: return str(value)
[docs]class WDLIntType(WDLType): """ Represents a WDL Int primitive type.""" @property def name(self) -> str: return 'Int' def _create(self, value: Any) -> Any: return int(value)
[docs]class WDLFloatType(WDLType): """ Represents a WDL Float primitive type.""" @property def name(self) -> str: return 'Float' def _create(self, value: Any) -> Any: return float(value)
[docs]class WDLBooleanType(WDLType): """ Represents a WDL Boolean primitive type.""" @property def name(self) -> str: return 'Boolean' def _create(self, value: Any) -> Any: return True if value else False
[docs]class WDLFileType(WDLType): """ Represents a WDL File primitive type.""" @property def name(self) -> str: return 'File' @property def default_value(self) -> str: return '' def _create(self, value: Any) -> Any: if isinstance(value, (WDLFile, Promise)): # return the original file if it's passed from task to task. return value return WDLFile(file_path=value, imported=False)
[docs]class WDLArrayType(WDLCompoundType): """ Represents a WDL Array compound type.""" def __init__(self, element: WDLType, optional: bool = False): super().__init__(optional) self.element = element @property def name(self) -> str: return f'Array[{self.element.name}]' def _create(self, value: Any) -> Any: if not isinstance(value, list): raise WDLRuntimeError(f"Expected an array input for Array, but got '{type(value)}'") return [self.element.create(val) for val in value]
[docs]class WDLPairType(WDLCompoundType): """ Represents a WDL Pair compound type.""" def __init__(self, left: WDLType, right: WDLType, optional: bool = False): super().__init__(optional) self.left = left self.right = right @property def name(self) -> str: return f'Pair[{self.left.name}, {self.right.name}]' def _create(self, value: Any) -> Any: if isinstance(value, WDLPair): return value elif isinstance(value, tuple): if len(value) != 2: raise WDLRuntimeError('Only support Pair len == 2') left, right = value elif isinstance(value, dict): if 'left' not in value or 'right' not in value: raise WDLRuntimeError('Pair needs \'left\' and \'right\' keys') left = value.get('left') right = value.get('right') else: raise WDLRuntimeError(f"Expected a pair input for Pair, but got '{type(value)}'") return WDLPair(self.left.create(left), self.right.create(right))
[docs]class WDLMapType(WDLCompoundType): """ Represents a WDL Map compound type.""" def __init__(self, key: WDLType, value: WDLType, optional: bool = False): super().__init__(optional) self.key = key self.value = value @property def name(self) -> str: return f'Map[{self.key.name}, {self.value.name}]' def _create(self, value: Any) -> Any: if not isinstance(value, dict): raise WDLRuntimeError(f"Expected a map input for Map, but got '{type(value)}'") return {self.key.create(k): self.value.create(v) for k, v in value.items()}
[docs]class WDLFile: """ Represents a WDL File. """ def __init__(self, file_path: str, file_name: Optional[str] = None, imported: bool = False): """ :param file_path: Path to file. :param file_name: Optional. Preserved file name. :param imported: If True, this file has been imported to the fileStore via fileStore.importFile(). """ self.file_path = file_path self.file_name = file_name self.imported = imported
[docs]class WDLPair: """ Represents a WDL Pair literal defined at https://github.com/openwdl/wdl/blob/main/versions/development/SPEC.md#pair-literals """ def __init__(self, left: Any, right: Any): self.left = left self.right = right
[docs] def to_dict(self) -> Dict[str, Any]: return {'left': self.left, 'right': self.right}
[docs] def __eq__(self, other: Any) -> Any: if not isinstance(other, WDLPair): return False return self.left == other.left and self.right == other.right
[docs] def __repr__(self) -> str: return str(self.to_dict())