Skip to content

Commit 8e450af

Browse files
author
Vasu Jaganath
committed
fix type and indent errors for CI
1 parent 88f8555 commit 8e450af

File tree

1 file changed

+82
-65
lines changed

1 file changed

+82
-65
lines changed

src/sophios/compiler.py

Lines changed: 82 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,14 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
841841
steps_list.append(step_i_copy)
842842
yaml_tree.update({'steps': steps_list}) # steps_list ?
843843

844+
# --------------------------------------------------------
845+
# Helpers for generating yaml_inputs for workflow execution from inputs_workflow
846+
# --------------------------------------------------------
844847
def type_includes_null(cwl_type: Any) -> bool:
845848
if isinstance(cwl_type, list):
846849
return "null" in cwl_type
850+
if isinstance(cwl_type, str) and cwl_type.endswith("?"):
851+
return True
847852
return False
848853

849854
def strip_null_from_union(cwl_type: Any) -> Any:
@@ -852,99 +857,111 @@ def strip_null_from_union(cwl_type: Any) -> Any:
852857
if len(non_null) == 1:
853858
return non_null[0]
854859
return non_null
860+
if isinstance(cwl_type, str) and cwl_type.endswith("?"):
861+
return cwl_type[:-1]
855862
return cwl_type
856863

857864
def emit_file_or_dir(type_name: str, value: Any, fmt: Any = None) -> Dict[str, Any]:
858-
obj = {
865+
obj: Dict[str, Any] = {
859866
"class": type_name,
860867
"location": value
861868
}
862869
if type_name == "File" and fmt:
863870
obj["format"] = fmt
864871
return obj
865872

866-
def populate_scalar_val(in_dict: Dict[str, Any]) -> Any:
873+
# --------------------------------------------------------
874+
# Scalar emission for each primitive type, as well as File and Directory
875+
# --------------------------------------------------------
876+
def populate_scalar_val(cwl_type: Any, value: Any, fmt: Any = None) -> Any:
877+
match cwl_type:
878+
case "File":
879+
obj: Dict[str, Any] = {
880+
"class": "File",
881+
"location": value
882+
}
883+
if fmt:
884+
obj["format"] = fmt
885+
return obj
886+
887+
case "Directory":
888+
return {
889+
"class": "Directory",
890+
"location": value
891+
}
892+
893+
case "string":
894+
return str(value)
895+
896+
case "int":
897+
return int(value)
898+
899+
case "float":
900+
return float(value)
901+
902+
case "boolean":
903+
return bool(value)
904+
905+
case _:
906+
# Unknown or already structured type
907+
return value
908+
909+
# --------------------------------------------------------
910+
# Main input handling for yaml_inputs
911+
# --------------------------------------------------------
912+
def populate_input_value(in_dict: Dict[str, Any]) -> Any:
867913
raw_type = in_dict["type"]
868914
value = in_dict.get("value")
869915
fmt = in_dict.get("format")
870916

871-
# Optional null handling is done outside this function
872-
cwl_type = strip_null_from_union(raw_type)
873-
874-
# File
875-
if cwl_type == "File":
876-
return emit_file_or_dir("File", value, fmt)
877-
878-
# Directory
879-
if cwl_type == "Directory":
880-
return emit_file_or_dir("Directory", value)
881-
882-
# Primitive types
883-
if cwl_type in ("string", "string?"):
884-
return str(value)
885-
886-
if cwl_type in ("int", "int?"):
887-
return int(value)
888-
889-
if cwl_type in ("float", "float?"):
890-
return float(value)
891-
892-
if cwl_type in ("boolean", "boolean?"):
893-
return bool(value)
917+
# ---------- Null handling ----------
918+
if value is None:
919+
if type_includes_null(raw_type):
920+
return None
921+
raise ValueError(
922+
f"Required input of type {raw_type} was not provided."
923+
)
894924

895-
# Fallback for unknown types
896-
return value
925+
# Normalize type (strip null / ?)
926+
cwl_type = strip_null_from_union(raw_type)
897927

898-
def populate_input_value(in_dict: Dict[str, Any]) -> Any:
899-
raw_type = in_dict["type"]
900-
value = in_dict.get("value")
928+
# Normalize type
929+
cwl_type = strip_null_from_union(raw_type)
901930

902-
# --- Handle optional null case ---
903-
if value is None:
904-
if type_includes_null(raw_type):
905-
return None # caller will omit key
906-
else:
907-
raise ValueError(
908-
f"Required input of type {raw_type} was not provided."
909-
)
910-
911-
# --- Handle array types ---
912-
# Case 1: {"type": "array", "items": ...}
913-
if isinstance(raw_type, dict) and raw_type.get("type") == "array":
914-
item_type = raw_type["items"]
931+
# ---------- Array handling ----------
932+
# Case: {"type": "array", "items": ...}
933+
if isinstance(cwl_type, dict) and cwl_type.get("type") == "array":
934+
item_type = strip_null_from_union(cwl_type["items"])
935+
# wrap scalar into list if necessary for lenient shape handling
936+
values = value if isinstance(value, list) else [value]
915937
return [
916-
populate_scalar_val({
917-
"type": item_type,
918-
"value": val,
919-
"format": in_dict.get("format")
920-
})
921-
for val in value
938+
populate_scalar_val(item_type, v, fmt)
939+
for v in values
922940
]
923941

924-
# Case 2: union including array
925-
if isinstance(raw_type, list):
926-
for t in raw_type:
942+
# Case: union including array
943+
if isinstance(cwl_type, list):
944+
for t in cwl_type:
927945
if isinstance(t, dict) and t.get("type") == "array":
928-
item_type = t["items"]
946+
item_type = strip_null_from_union(t["items"])
947+
# wrap scalar into list if necessary for lenient shape handling
948+
values = value if isinstance(value, list) else [value]
929949
return [
930-
populate_scalar_val({
931-
"type": item_type,
932-
"value": val,
933-
"format": in_dict.get("format")
934-
})
935-
for val in value
950+
populate_scalar_val(item_type, v, fmt)
951+
for v in values
936952
]
937953

938-
# --- Scalar case ---
939-
return populate_scalar_val(in_dict)
954+
# ---------- Scalar case ----------
955+
return populate_scalar_val(cwl_type, value, fmt)
940956

941-
# ------------------------------
942-
# Generate the final workflow inputs by populating the values from the inputs file.
943-
# ------------------------------
957+
# --------------------------------------------------------
958+
# Generate yaml_inputs by populating values from inputs_file_workflow
959+
# To be dumped in *_yaml_inputs.yml and passed to CWL workflow execution as --inputs-file
960+
# --------------------------------------------------------
944961
yaml_inputs: WorkflowInputsFile = {}
945962
for key, in_dict in inputs_file_workflow.items():
946963
val = populate_input_value(in_dict)
947-
# Omit optional-null values only
964+
# Omit optional null fields only
948965
if val is None:
949966
continue
950967
yaml_inputs[key] = val

0 commit comments

Comments
 (0)