From 25fd4f4f8d81864476b372662555f8f8d78e1f01 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:24:06 +0400 Subject: [PATCH 01/21] Initial commit --- zefiro-core/Cargo.toml | 5 +- zefiro-core/zefiro-cwl-parser/Cargo.toml | 13 +++ .../examples/data/clt-step-schema.yml | 32 +++++++ .../examples/data/clt-step-values.yml | 4 + .../examples/data/wf-step-schema.yml | 64 +++++++++++++ .../examples/data/wf-step-values.yml | 6 ++ zefiro-core/zefiro-cwl-parser/src/lib.rs | 2 + .../src/schema/command_line_tool.rs | 63 +++++++++++++ .../zefiro-cwl-parser/src/schema/document.rs | 74 +++++++++++++++ .../zefiro-cwl-parser/src/schema/mod.rs | 5 + .../src/schema/requirements.rs | 94 +++++++++++++++++++ .../zefiro-cwl-parser/src/schema/types.rs | 54 +++++++++++ .../zefiro-cwl-parser/src/schema/workflow.rs | 91 ++++++++++++++++++ .../zefiro-cwl-parser/src/values/document.rs | 55 +++++++++++ .../zefiro-cwl-parser/src/values/mod.rs | 2 + .../zefiro-cwl-parser/src/values/types.rs | 54 +++++++++++ 16 files changed, 617 insertions(+), 1 deletion(-) create mode 100644 zefiro-core/zefiro-cwl-parser/Cargo.toml create mode 100644 zefiro-core/zefiro-cwl-parser/examples/data/clt-step-schema.yml create mode 100644 zefiro-core/zefiro-cwl-parser/examples/data/clt-step-values.yml create mode 100644 zefiro-core/zefiro-cwl-parser/examples/data/wf-step-schema.yml create mode 100644 zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml create mode 100644 zefiro-core/zefiro-cwl-parser/src/lib.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/document.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/mod.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/types.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/values/document.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/values/mod.rs create mode 100644 zefiro-core/zefiro-cwl-parser/src/values/types.rs diff --git a/zefiro-core/Cargo.toml b/zefiro-core/Cargo.toml index 2160189..6d98097 100644 --- a/zefiro-core/Cargo.toml +++ b/zefiro-core/Cargo.toml @@ -4,4 +4,7 @@ version = "0.1.0" edition = "2021" rust-version = "1.83.0" -[dependencies] +[workspace] +members = [ + "zefiro-cwl-parser" +] diff --git a/zefiro-core/zefiro-cwl-parser/Cargo.toml b/zefiro-core/zefiro-cwl-parser/Cargo.toml new file mode 100644 index 0000000..ee15551 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "zefiro-cwl-parser" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.95" +serde = { version = "1.0.216", features = ["derive"] } +serde_with = "3.12.0" +serde_yaml = "0.9.34" + +[dev-dependencies] +rstest = "0.24.0" diff --git a/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-schema.yml b/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-schema.yml new file mode 100644 index 0000000..1ab9a17 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-schema.yml @@ -0,0 +1,32 @@ +cwlVersion: v1.2 +class: CommandLineTool +id: step +inputs: + - id: in_file + type: File + inputBinding: + prefix: --in-file + - id: out_file + type: string + default: "output.txt" + inputBinding: + prefix: --out-file + - id: output_location_subdir + type: string + default: output/ +outputs: + - id: out_file + type: File + outputBinding: + glob: $(inputs.out_file) + outputEval: ${self[0].location += inputs.output_location_subdir; return self[0]} +requirements: + - class: DockerRequirement + dockerPull: step-image-uri:1.0 + - class: ResourceRequirement + coresMin: 2 + outdirMin: 1000 + ramMin: 1024 + - class: InlineJavascriptRequirement + - class: ToolTimeLimit + timelimit: $(60*60*1) diff --git a/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-values.yml b/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-values.yml new file mode 100644 index 0000000..74ed4a5 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/examples/data/clt-step-values.yml @@ -0,0 +1,4 @@ +in_file: + class: File + location: '{{ inputLocation }}/output/input-{{ readgroup }}.txt' +out_file: 'output.txt' diff --git a/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-schema.yml b/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-schema.yml new file mode 100644 index 0000000..9bc4fd2 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-schema.yml @@ -0,0 +1,64 @@ +class: Workflow +cwlVersion: v1.2 +id: step +inputs: + - id: step__in_file + type: + type: array + items: File + - id: step__out_file + type: string +outputs: + - id: step__out_file + type: File + outputSource: step/out_file +requirements: + - class: InlineJavascriptRequirement + - class: ScatterFeatureRequirement +steps: + - id: step + in: + - id: in_file + source: step__in_file + - id: out_file + source: step__out_file + out: + - id: out_file + run: + cwlVersion: v1.2 + class: CommandLineTool + id: step1 + inputs: + - id: in_file + type: File + inputBinding: + prefix: --in-file + - id: out_file + type: string + default: output.txt + inputBinding: + prefix: --out-file + - id: output_location_subdir + type: string + default: output/ + outputs: + - id: out_file + type: File + outputBinding: + glob: $(inputs.out_file) + outputEval: ${self[0].location += inputs.output_location_subdir; return self[0]} + requirements: + - class: DockerRequirement + dockerPull: step1-image:1.0 + - class: ResourceRequirement + coresMin: 2 + outdirMin: 1000 + ramMin: 1024 + - class: InlineJavascriptRequirement + - class: ToolTimeLimit + timelimit: $(60*60*1) + - class: WorkReuse + enableReuse: true + scatter: + - in_file + scatterMethod: dotproduct diff --git a/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml b/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml new file mode 100644 index 0000000..6f5d530 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml @@ -0,0 +1,6 @@ +step__in_file: +{% for readgroup in readgroups %} + - class: File + location: '{{ inputLocation }}/output/input-{{ readgroup }}.txt' +{% endfor %} +step__out_file: output.txt diff --git a/zefiro-core/zefiro-cwl-parser/src/lib.rs b/zefiro-core/zefiro-cwl-parser/src/lib.rs new file mode 100644 index 0000000..c61a87c --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/lib.rs @@ -0,0 +1,2 @@ +pub mod schema; +pub mod values; \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs new file mode 100644 index 0000000..a79b99b --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -0,0 +1,63 @@ +use crate::schema::types::{Any, CwlSchemaType, Documentation}; +use crate::schema::requirements::CommandLineToolRequirement; +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; + +/// This defines the schema of the CWL Command Line Tool Description document. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CommandLineTool { + pub cwl_version: String, + pub class: String, + pub doc: Option, + pub id: Option, + pub label: Option, + pub inputs: Vec, + pub outputs: Vec, + pub requirements: Vec, +} + +/// Represents an input parameter for a `CommandLineTool`. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandInputParameter +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CommandInputParameter { + pub id: String, + pub r#type: CwlSchemaType, + pub input_binding: Option, + pub default: Option, +} + +/// Represents an output parameter for a `CommandLineTool`. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandOutputParameter +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CommandOutputParameter { + pub id: String, + pub r#type: CwlSchemaType, + pub output_binding: Option, +} + +/// Describes how to bind an input or output to the command line. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandLineBinding +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CommandLineBinding { + pub position: Option, + pub prefix: Option, + pub value_from: Option, +} + +/// Describes output binding rules for a `CommandLineTool`. +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct OutputBinding { + pub glob: Option, + pub output_eval: Option, +} diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs new file mode 100644 index 0000000..5cc46f8 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -0,0 +1,74 @@ +use crate::schema::{command_line_tool::CommandLineTool, workflow::Workflow}; +use anyhow::{bail, ensure, Result}; +use serde::{Deserialize, Serialize}; +use serde_yaml::{self, Value}; +use std::{ + fs::File, io::{BufReader, Write}, str::FromStr +}; + +const SUPPORTED_VERSIONS: &[&str] = &["v1.2"]; + + +/// Represents a CWL Schema which can be either a CommandLineTool or a Workflow +/// +/// # Variants +/// +/// * `CommandLineTool` - Represents a single command line tool with its inputs and outputs +/// * `Workflow` - Represents a series of connected steps forming a complete workflow +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +pub enum CwlSchema { + CommandLineTool(CommandLineTool), + Workflow(Workflow), +} + +impl CwlSchema { + pub fn from_path(path: &str) -> Result { + let reader = BufReader::new(File::open(path)?); + Self::from_yaml(serde_yaml::from_reader(reader)?) + } + + pub fn from_yaml(value: Value) -> Result { + let version = value + .get("cwlVersion") + .and_then(Value::as_str) + .ok_or_else(|| anyhow::anyhow!("Failed to determine CWL specification version."))?; + ensure!(SUPPORTED_VERSIONS.contains(&version), "Unsupported CWL version: {version}"); + + match value.get("class").and_then(Value::as_str) { + Some("CommandLineTool") => Ok(Self::CommandLineTool(serde_yaml::from_value(value)?)), + Some("Workflow") => Ok(Self::Workflow(serde_yaml::from_value(value)?)), + Some(class) => bail!("Unsupported CWL document class: {class}"), + None => bail!("Failed to determine CWL document class."), + } + } + + pub fn to_string(&self) -> Result { + serde_yaml::to_string(self).map_err(Into::into) + } + + pub fn to_yaml(&self, writer: W) -> Result<()> { + serde_yaml::to_writer(writer, self).map_err(Into::into) + } +} + +impl FromStr for CwlSchema { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Self::from_yaml(serde_yaml::from_str(s)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case("examples/data/clt-step-schema.yml")] + #[case("examples/data/wf-step-schema.yml")] + fn test_parse_correct_schema(#[case] file_path: &str) { + CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); + } +} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs b/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs new file mode 100644 index 0000000..67f3d24 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs @@ -0,0 +1,5 @@ +pub mod workflow; +pub mod command_line_tool; +pub mod requirements; +pub mod types; +pub mod document; \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs new file mode 100644 index 0000000..ba9860f --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs @@ -0,0 +1,94 @@ +use crate::schema::types::Any; +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; + +const CPU_NUM_DEFAULT: u32 = 1; +const RAM_SIZE_IN_MB_DEFAULT: u32 = 1024; +const TMPDIR_MIN_IN_MB_DEFAULT: u32 = 1024; +const OUTDIR_MIN_IN_MB_DEFAULT: u32 = 1024; + + +/// Describes requirements for `Workflow`. +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "class")] +pub enum WorkflowRequirement { + InlineJavascriptRequirement(InlineJavascriptRequirement), + ScatterFeatureRequirement(ScatterFeatureRequirement), +} + +/// Describes requirements for `CommandLineTool`. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "class")] +pub enum CommandLineToolRequirement { + DockerRequirement(DockerRequirement), + ResourceRequirement(ResourceRequirement), + InlineJavascriptRequirement(InlineJavascriptRequirement), + ToolTimeLimit(ToolTimeLimit), + WorkReuse(WorkReuse) +} + +/// Specifies Docker container requirements. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#DockerRequirement +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DockerRequirement { + pub docker_pull: String, +} + +/// Specifies resource constraints for running the tool. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#ResourceRequirement +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ResourceRequirement { + #[serde(default = "ResourceRequirement::default_cores_min")] + pub cores_min: u32, + + #[serde(default = "ResourceRequirement::default_ram_min")] + pub ram_min: u32, + + #[serde(default = "ResourceRequirement::default_tmpdir_min")] + pub tmpdir_min: u32, + + #[serde(default = "ResourceRequirement::default_outdir_min")] + pub outdir_min: u32, +} + +impl ResourceRequirement { + fn default_cores_min() -> u32 { CPU_NUM_DEFAULT } + fn default_ram_min() -> u32 { RAM_SIZE_IN_MB_DEFAULT } + fn default_tmpdir_min() -> u32 { TMPDIR_MIN_IN_MB_DEFAULT } + fn default_outdir_min() -> u32 { OUTDIR_MIN_IN_MB_DEFAULT } +} + +/// Indicates that the workflow platform must support inline Javascript expressions +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#InlineJavascriptRequirement +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct InlineJavascriptRequirement; + +/// Specifies an upper limit on the execution time of a `CommandLineTool` (in seconds). +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#ToolTimeLimit +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ToolTimeLimit { + pub timelimit: Any, +} + +/// Specifies that the workflow platform must support the scatter and `scatterMethod` fields of `WorkflowStep`. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#ScatterFeatureRequirement +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ScatterFeatureRequirement; + + +/// Specifies a reusing output from past work of a `CommandLineTool`. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#WorkReuse +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkReuse { + pub enable_reuse: bool, +} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs new file mode 100644 index 0000000..54bdb47 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs @@ -0,0 +1,54 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use serde_yaml::Value as YValue; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum Any { + Any(YValue), +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum CwlSchemaType { + Null, + Boolean(bool), + Int(i32), + Long(i64), + Float(f32), + Double(f64), + String(String), + File(String), + Directory(String), + Map(HashMap), + Array(Vec) +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum Documentation { + SingleLine(String), + MultiLine(Vec), +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum Format { + Format(String), + Formats(Vec), +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum Scatter { + Parameter(String), + Parameters(Vec), +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum Source { + SingleSource(String), + MultiSources(Vec), +} diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs new file mode 100644 index 0000000..e993354 --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs @@ -0,0 +1,91 @@ +use crate::schema::command_line_tool::CommandLineTool; +use crate::schema::types::{Any, Documentation, Scatter, Source, CwlSchemaType}; +use crate::schema::requirements::WorkflowRequirement; +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; + +/// This defines the schema of the CWL Workflow Description document. +/// See: https://www.commonwl.org/v1.2/Workflow.html +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Workflow { + pub class: String, + pub cwl_version: String, + pub doc: Option, + pub id: String, + pub label: Option, + pub inputs: Vec, + pub outputs: Vec, + pub steps: Vec, + pub requirements: Vec +} + +/// Represents an input parameter for a `Workflow`. +/// See: https://www.commonwl.org/v1.2/Workflow.html#WorkflowInputParameter +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkflowInputParameter { + pub r#type: CwlSchemaType, + pub label: Option, + pub default: Option, + pub id: Option, +} + +/// Represents an output parameter for a `Workflow`. +/// See: https://www.commonwl.org/v1.2/Workflow.html#WorkflowOutputParameter +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkflowOutputParameter { + pub r#type: CwlSchemaType, + pub label: Option, + pub doc: Option, + pub id: Option, + pub output_source: Option +} + + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged, rename_all = "camelCase")] +pub enum WorkflowOutputParameterOutputSource { + OutputSource(String), + OutputSourceArray(Vec), +} + +/// Represents a `WorkflowStep` - an executable element of a workflow. +/// See: https://www.commonwl.org/v1.2/Workflow.html#WorkflowStep +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkflowStep { + pub r#in: Vec, + pub out: Vec, + pub run: CommandLineTool, + pub id: Option, + pub label: Option, + pub doc: Option, + pub scatter: Option, + pub scatter_method: Option, +} + +/// Defines the input parameters of the workflow step (`out` section). +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkflowStepInput { + pub id: String, + pub source: Option, + pub label: Option, + pub default: Option, + pub value_from: Option, +} + +/// Defines the output parameters of the workflow step (`in` section). +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkflowStepOutput { + pub id: String +} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs new file mode 100644 index 0000000..beb8e6c --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -0,0 +1,55 @@ +use crate::values::types::CwlValueType; +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use serde_yaml; +use std::{ + collections::HashMap, fs::File, io::{BufReader, Write}, ops::Deref +}; + +/// Represents a collection of CWL input/output values as key-value pairs +/// +/// # Fields +/// +/// * `values` - A map of parameter names to their corresponding CWL values. +/// The values are flattened during serialization/deserialization +/// to allow for a more natural YAML representation +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct CwlValues { + #[serde(flatten)] + values: HashMap +} + +impl Deref for CwlValues { + type Target = HashMap; + + fn deref(&self) -> &Self::Target { + &self.values + } +} + +impl CwlValues { + pub fn from_path(path: &str) -> Result { + let reader = BufReader::new(File::open(path)?); + Ok(serde_yaml::from_reader(reader)?) + } + + pub fn to_string(&self) -> Result { + Ok(serde_yaml::to_string(self)?) + } + + pub fn to_yaml(&self, writer: W) -> Result<()> { + serde_yaml::to_writer(writer, self).map_err(Into::into) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case("examples/data/clt-step-values.yml")] + fn test_parse_correct_values(#[case] file_path: &str) { + CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); + } +} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/values/mod.rs b/zefiro-core/zefiro-cwl-parser/src/values/mod.rs new file mode 100644 index 0000000..6705fde --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/values/mod.rs @@ -0,0 +1,2 @@ +pub mod types; +pub mod document; \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs new file mode 100644 index 0000000..2ce321a --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -0,0 +1,54 @@ +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +pub enum CwlInputClass { + File(String), + Directory(String), +} + +/// Represents a `File` object in CWL +/// see: https://www.commonwl.org/v1.2/CommandLineTool.html#File +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct CwlFile { + pub class: CwlInputClass, + pub location: String, +} + +impl CwlFile { + pub fn get_location(&self) -> String { + self.location.clone() + } +} + +/// Represents a `Directory` object in CWL +/// see: https://www.commonwl.org/v1.2/CommandLineTool.html#Directory +#[skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct CwlDirectory { + pub class: CwlInputClass, + pub location: String, +} + +impl CwlDirectory { + pub fn get_location(&self) -> String { + self.location.clone() + } +} + + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +pub enum CwlValueType { + Boolean(bool), + Int(i32), + Long(i64), + Float(f32), + Double(f64), + String(String), + CwlFile(CwlFile), + CwlDirectory(CwlDirectory), + Array(Vec) +} \ No newline at end of file From c1f3b241622b1e260cc7b5f2439692f3f86b6d12 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:59:59 +0400 Subject: [PATCH 02/21] Refactor and fix logs --- Cargo.lock | 755 +++++++++++++++++- Cargo.toml | 2 +- zefiro-core/Cargo.toml | 5 - .../src/schema/command_line_tool.rs | 10 + .../zefiro-cwl-parser/src/schema/types.rs | 19 +- .../zefiro-cwl-parser/src/values/document.rs | 15 +- .../zefiro-cwl-parser/src/values/types.rs | 26 +- 7 files changed, 791 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6873d6a..b3fe791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,752 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rstest" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.134" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.7.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.7.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" +dependencies = [ + "memchr", +] + [[package]] name = "zefiro" version = "0.1.0" @@ -11,8 +757,15 @@ name = "zefiro-cli" version = "0.1.0" [[package]] -name = "zefiro-core" +name = "zefiro-cwl-parser" version = "0.1.0" +dependencies = [ + "anyhow", + "rstest", + "serde", + "serde_with", + "serde_yaml", +] [[package]] name = "zefiro-ui" diff --git a/Cargo.toml b/Cargo.toml index 0c381c7..d631220 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [workspace] members = [ "zefiro-cli", - "zefiro-core", + "zefiro-core/zefiro-cwl-parser", "zefiro-ui" ] \ No newline at end of file diff --git a/zefiro-core/Cargo.toml b/zefiro-core/Cargo.toml index 6d98097..f6ef9be 100644 --- a/zefiro-core/Cargo.toml +++ b/zefiro-core/Cargo.toml @@ -3,8 +3,3 @@ name = "zefiro-core" version = "0.1.0" edition = "2021" rust-version = "1.83.0" - -[workspace] -members = [ - "zefiro-cwl-parser" -] diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index a79b99b..14a90a6 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -10,12 +10,22 @@ use serde_with::skip_serializing_none; #[serde(rename_all = "camelCase")] pub struct CommandLineTool { pub cwl_version: String, + pub class: String, + + #[serde(skip_serializing_if = "Option::is_none")] pub doc: Option, + + #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, + + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, + pub inputs: Vec, + pub outputs: Vec, + pub requirements: Vec, } diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs index 54bdb47..0f1562f 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs @@ -10,21 +10,18 @@ pub enum Any { } #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(untagged, rename_all = "camelCase")] +#[serde(untagged)] pub enum CwlSchemaType { - Null, - Boolean(bool), - Int(i32), - Long(i64), - Float(f32), - Double(f64), - String(String), - File(String), - Directory(String), + // Here can be any type: + // Null, Boolean, Int, Long, Float, Double, String, File, Directory + // array, string[], File[], Directory[] + Any(String), + + Array(Vec), Map(HashMap), - Array(Vec) } + #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged, rename_all = "camelCase")] pub enum Documentation { diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index beb8e6c..1e1258f 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -1,5 +1,5 @@ use crate::values::types::CwlValueType; -use anyhow::Result; +use anyhow::{Error, Result}; use serde::{Deserialize, Serialize}; use serde_yaml; use std::{ @@ -28,12 +28,17 @@ impl Deref for CwlValues { } impl CwlValues { - pub fn from_path(path: &str) -> Result { - let reader = BufReader::new(File::open(path)?); - Ok(serde_yaml::from_reader(reader)?) + pub fn from_path(path: &str) -> Result { + let reader = BufReader::new(File::open(path).map_err(|e| { + Error::msg(format!("Failed to open file '{}': {}", path, e)) + })?); + + serde_yaml::from_reader(reader).map_err(|e| { + Error::msg(format!("Failed to parse CWL values from '{}'; {}", path, e)) + }) } - pub fn to_string(&self) -> Result { + pub fn to_string(&self) -> Result { Ok(serde_yaml::to_string(self)?) } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs index 2ce321a..5301662 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -1,23 +1,14 @@ use serde::{Deserialize, Serialize}; -use serde_with::skip_serializing_none; - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum CwlInputClass { - File(String), - Directory(String), -} /// Represents a `File` object in CWL /// see: https://www.commonwl.org/v1.2/CommandLineTool.html#File -#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct CwlFile { - pub class: CwlInputClass, +pub struct File { + pub class: String, pub location: String, } -impl CwlFile { +impl File { pub fn get_location(&self) -> String { self.location.clone() } @@ -25,14 +16,13 @@ impl CwlFile { /// Represents a `Directory` object in CWL /// see: https://www.commonwl.org/v1.2/CommandLineTool.html#Directory -#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct CwlDirectory { - pub class: CwlInputClass, +pub struct Directory { + pub class: String, pub location: String, } -impl CwlDirectory { +impl Directory { pub fn get_location(&self) -> String { self.location.clone() } @@ -48,7 +38,7 @@ pub enum CwlValueType { Float(f32), Double(f64), String(String), - CwlFile(CwlFile), - CwlDirectory(CwlDirectory), + File(File), + Directory(Directory), Array(Vec) } \ No newline at end of file From 0565505b4ea1b3459e890ede1c9681d145730a74 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 12:10:40 +0400 Subject: [PATCH 03/21] Fix YAML format in cd.yml --- .github/workflows/cd.yml | 41 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index b207304..76da2ba 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -22,26 +22,25 @@ jobs: uses: orhun/git-cliff-action@v4 id: git-cliff - name: Run git-cliff to generate changelog - run: git-cliff -vv --latest --no-exec --github-repo ${{ github.repository }} --config cliff.toml id: changelog + run: git-cliff -vv --latest --no-exec --github-repo ${{ github.repository }} --config cliff.toml - publish-crates-io: - name: Publish on crates.io - runs-on: ubuntu-22.04 - needs: generate-changelog - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Verify package - run: cargo verify-project - - name: Run tests - run: cargo test --all-features - - name: Set the release version - run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> "$GITHUB_ENV" - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - uses: dtolnay/rust-toolchain@stable - # - name: Publish the zefiro-core library - # run: | - # cargo publish --manifest-path zefiro-core/Cargo.toml \ - # --locked --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file + publish-crates-io: + name: Publish on crates.io + runs-on: ubuntu-22.04 + needs: generate-changelog + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Verify package + run: cargo verify-project + - name: Run tests + run: cargo test --all-features + - name: Set the release version + run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> "$GITHUB_ENV" + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + # - name: Publish the zefiro-core library + # run: | + # cargo publish --manifest-path zefiro-core/Cargo.toml \ + # --locked --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file From 6d86037fdbd7d821bae2ea9d85e5777e1bb1ce47 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:31:28 +0400 Subject: [PATCH 04/21] Add first docs --- zefiro-core/zefiro-cwl-parser/Cargo.toml | 12 ++++++ .../zefiro-cwl-parser/src/schema/document.rs | 5 --- .../zefiro-cwl-parser/src/values/document.rs | 43 +++++++++++++++---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/Cargo.toml b/zefiro-core/zefiro-cwl-parser/Cargo.toml index ee15551..efa3fc9 100644 --- a/zefiro-core/zefiro-cwl-parser/Cargo.toml +++ b/zefiro-core/zefiro-cwl-parser/Cargo.toml @@ -1,7 +1,19 @@ [package] name = "zefiro-cwl-parser" version = "0.1.0" +description = """ +"The Common Workflow Language (CWL) object model that used in `zefiro`. +""" +authors = [ + "Nikita Syzrantsev " +] +categories = ["Common Workflow Language", "CWL"] +keywords = ["CWL", "CommanLineTool", "Workflow"] edition = "2021" +homepage = "https://github.com/zefiroproj/zefiro" +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/zefiroproj/zefiro" [dependencies] anyhow = "1.0.95" diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 5cc46f8..8436ad2 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -10,11 +10,6 @@ const SUPPORTED_VERSIONS: &[&str] = &["v1.2"]; /// Represents a CWL Schema which can be either a CommandLineTool or a Workflow -/// -/// # Variants -/// -/// * `CommandLineTool` - Represents a single command line tool with its inputs and outputs -/// * `Workflow` - Represents a series of connected steps forming a complete workflow #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum CwlSchema { diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index 1e1258f..185d828 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -6,13 +6,7 @@ use std::{ collections::HashMap, fs::File, io::{BufReader, Write}, ops::Deref }; -/// Represents a collection of CWL input/output values as key-value pairs -/// -/// # Fields -/// -/// * `values` - A map of parameter names to their corresponding CWL values. -/// The values are flattened during serialization/deserialization -/// to allow for a more natural YAML representation +/// Represents a collection of CWL input and output values as key-value pairs #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CwlValues { #[serde(flatten)] @@ -28,6 +22,15 @@ impl Deref for CwlValues { } impl CwlValues { + /// Serializes YAML `file` containing CWL values into CwlValues structure. + /// + /// ``` + /// use zefiro_cwl_parser::values::document::CwlValues; + /// + /// let yaml_file = "examples/data/clt-step-values.yml"; + /// + /// let values = CwlValues::from_path(yaml_file).expect("Failed to deserialize CWL values document"); + /// ``` pub fn from_path(path: &str) -> Result { let reader = BufReader::new(File::open(path).map_err(|e| { Error::msg(format!("Failed to open file '{}': {}", path, e)) @@ -38,10 +41,34 @@ impl CwlValues { }) } + /// Serializes YAML `string` containing CWL values into CwlValues structure. + /// + /// ``` + /// use zefiro_cwl_parser::values::document::CwlValues; + /// + /// let yaml_input = r#" + /// in_file: + /// class: File + /// location: 's3://bucket/path/to/input.txt' + /// out_file: 'output.txt' + /// "#; + /// + /// let values = CwlValues::from_string(yaml_input).expect("Failed to deserialize CWL values document"); + /// ``` + pub fn from_string(yaml_input: &str) -> Result { + serde_yaml::from_str(yaml_input).map_err(|e| { + Error::msg(format!("Failed to parse CWL values from string: {}", e)) + }) + } + + /// Deserializes CwlValues structure into `string`. pub fn to_string(&self) -> Result { - Ok(serde_yaml::to_string(self)?) + serde_yaml::to_string(self).map_err(|e| { + Error::msg(format!("Failed to serialize CWL values to string: {}", e)) + }) } + /// Deserializes CwlValues structure and writes it into `file`. pub fn to_yaml(&self, writer: W) -> Result<()> { serde_yaml::to_writer(writer, self).map_err(Into::into) } From 825503b931e4c5f2c2ed0667c0c7c98a48c4b93e Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 21:52:21 +0400 Subject: [PATCH 05/21] Add docs and refactor code --- zefiro-core/zefiro-cwl-parser/README.md | 77 +++++++++++++++++++ .../examples/data/wf-step-values.yml | 6 -- zefiro-core/zefiro-cwl-parser/src/lib.rs | 5 +- .../src/schema/command_line_tool.rs | 15 ++++ .../zefiro-cwl-parser/src/schema/document.rs | 61 ++++++++++++++- .../src/schema/requirements.rs | 16 ++-- .../zefiro-cwl-parser/src/schema/types.rs | 23 +++++- 7 files changed, 183 insertions(+), 20 deletions(-) create mode 100644 zefiro-core/zefiro-cwl-parser/README.md delete mode 100644 zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml diff --git a/zefiro-core/zefiro-cwl-parser/README.md b/zefiro-core/zefiro-cwl-parser/README.md new file mode 100644 index 0000000..8fae62f --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/README.md @@ -0,0 +1,77 @@ +# zefiro-cwl-parser + +A Rust library for parsing and working with Common Workflow Language (CWL) documents. + +## Overview + +* Supports only some fields of CWL v1.2 specification (see description of stuctures in the code) +* Can serialize and deserialize [CommandLineTool](https://www.commonwl.org/v1.2/CommandLineTool.html) and [Workflow](https://www.commonwl.org/v1.2/Workflow.html) documents + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +zefiro-cwl-parser = +``` + + +### Parsing CWL Schema Documents + +```rust +use zefiro_cwl_parser::CwlSchema; + +// Parse from file +let schema = CwlSchema::from_path("workflow.yml")?; + +// Parse from string +let yaml_str = r#" +cwlVersion: v1.2 +class: CommandLineTool +id: step +inputs: + - id: in_file + type: File + inputBinding: + prefix: --in-file + - id: out_file + type: string + default: "output.txt" + inputBinding: + prefix: --out-file + - id: output_location_subdir + type: string + default: output/ +outputs: + - id: out_file + type: File + outputBinding: + glob: $(inputs.out_file) + outputEval: ${self[0].location += inputs.output_location_subdir; return self[0]} +requirements: + - class: DockerRequirement + dockerPull: step-image-uri:1.0 + - class: InlineJavascriptRequirement +"#; +let schema = CwlSchema::from_string(yaml_str)?; +``` + + +### Parsing CWL Values Documents + +```rust +use zefiro_cwl_parser::CwlValues; + +// Parse input values from file +let values = CwlValues::from_path("values.yml")?; + +// Create values from string +let yaml_input = r#" +input_file: + class: File + location: 's3://bucket/input.txt' +output_file: 'output.txt' +"#; +let values = CwlValues::from_string(yaml_input)?; +``` \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml b/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml deleted file mode 100644 index 6f5d530..0000000 --- a/zefiro-core/zefiro-cwl-parser/examples/data/wf-step-values.yml +++ /dev/null @@ -1,6 +0,0 @@ -step__in_file: -{% for readgroup in readgroups %} - - class: File - location: '{{ inputLocation }}/output/input-{{ readgroup }}.txt' -{% endfor %} -step__out_file: output.txt diff --git a/zefiro-core/zefiro-cwl-parser/src/lib.rs b/zefiro-core/zefiro-cwl-parser/src/lib.rs index c61a87c..91ebe67 100644 --- a/zefiro-core/zefiro-cwl-parser/src/lib.rs +++ b/zefiro-core/zefiro-cwl-parser/src/lib.rs @@ -1,2 +1,5 @@ pub mod schema; -pub mod values; \ No newline at end of file +pub mod values; + +pub use crate::schema::document::CwlSchema; +pub use crate::values::document::CwlValues; \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 14a90a6..61404ca 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -36,8 +36,12 @@ pub struct CommandLineTool { #[serde(rename_all = "camelCase")] pub struct CommandInputParameter { pub id: String, + pub r#type: CwlSchemaType, + + #[serde(skip_serializing_if = "Option::is_none")] pub input_binding: Option, + pub default: Option, } @@ -48,7 +52,10 @@ pub struct CommandInputParameter { #[serde(rename_all = "camelCase")] pub struct CommandOutputParameter { pub id: String, + pub r#type: CwlSchemaType, + + #[serde(skip_serializing_if = "Option::is_none")] pub output_binding: Option, } @@ -58,8 +65,13 @@ pub struct CommandOutputParameter { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CommandLineBinding { + #[serde(skip_serializing_if = "Option::is_none")] pub position: Option, + + #[serde(skip_serializing_if = "Option::is_none")] pub prefix: Option, + + #[serde(skip_serializing_if = "Option::is_none")] pub value_from: Option, } @@ -68,6 +80,9 @@ pub struct CommandLineBinding { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct OutputBinding { + #[serde(skip_serializing_if = "Option::is_none")] pub glob: Option, + + #[serde(skip_serializing_if = "Option::is_none")] pub output_eval: Option, } diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 8436ad2..60186ca 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -1,5 +1,5 @@ use crate::schema::{command_line_tool::CommandLineTool, workflow::Workflow}; -use anyhow::{bail, ensure, Result}; +use anyhow::{bail, ensure, Error, Result}; use serde::{Deserialize, Serialize}; use serde_yaml::{self, Value}; use std::{ @@ -18,14 +18,24 @@ pub enum CwlSchema { } impl CwlSchema { + /// Serializes YAML `file` containing CWL values into CwlSchema structure. + /// + /// ``` + /// use zefiro_cwl_parser::schema::document::CwlSchema; + /// + /// let yaml_file = "examples/data/clt-step-schema.yml"; + /// + /// let values = CwlSchema::from_path(yaml_file).expect("Failed to deserialize CWL values document"); + /// ``` pub fn from_path(path: &str) -> Result { let reader = BufReader::new(File::open(path)?); Self::from_yaml(serde_yaml::from_reader(reader)?) } + /// Deserializes a YAML Value into a CwlSchema instance. pub fn from_yaml(value: Value) -> Result { let version = value - .get("cwlVersion") + .get("cwlVersion") .and_then(Value::as_str) .ok_or_else(|| anyhow::anyhow!("Failed to determine CWL specification version."))?; ensure!(SUPPORTED_VERSIONS.contains(&version), "Unsupported CWL version: {version}"); @@ -38,10 +48,57 @@ impl CwlSchema { } } + /// Serializes YAML `string` containing CWL values into CwlValues structure. + /// + /// # Examples + /// + /// ``` + /// use serde_yaml::Value; + /// use zefiro_cwl_parser::schema::document::CwlSchema; + /// + /// let yaml_str = r#" + /// cwlVersion: v1.2 + /// class: CommandLineTool + /// id: step + /// inputs: + /// - id: in_file + /// type: File + /// inputBinding: + /// prefix: --in-file + /// - id: out_file + /// type: string + /// default: "output.txt" + /// inputBinding: + /// prefix: --out-file + /// - id: output_location_subdir + /// type: string + /// default: output/ + /// outputs: + /// - id: out_file + /// type: File + /// outputBinding: + /// glob: $(inputs.out_file) + /// outputEval: ${self[0].location += inputs.output_location_subdir; return self[0]} + /// requirements: + /// - class: DockerRequirement + /// dockerPull: step-image-uri:1.0 + /// - class: InlineJavascriptRequirement + /// "#; + /// + /// let schema = CwlSchema::from_string(yaml_str).expect("Failed to parse CWL document"); + /// ``` + pub fn from_string(yaml_input: &str) -> Result { + serde_yaml::from_str(yaml_input).map_err(|e| { + Error::msg(format!("Failed to parse CWL schema from string: {}", e)) + }) + } + + /// Deserializes CwlValues structure into `string`. pub fn to_string(&self) -> Result { serde_yaml::to_string(self).map_err(Into::into) } + /// Deserializes CwlValues structure and writes it into `file`. pub fn to_yaml(&self, writer: W) -> Result<()> { serde_yaml::to_writer(writer, self).map_err(Into::into) } diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs index ba9860f..73b199a 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs @@ -43,24 +43,24 @@ pub struct DockerRequirement { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ResourceRequirement { - #[serde(default = "ResourceRequirement::default_cores_min")] + #[serde(default = "ResourceRequirement::cores_min")] pub cores_min: u32, - #[serde(default = "ResourceRequirement::default_ram_min")] + #[serde(default = "ResourceRequirement::ram_min")] pub ram_min: u32, - #[serde(default = "ResourceRequirement::default_tmpdir_min")] + #[serde(default = "ResourceRequirement::tmpdir_min")] pub tmpdir_min: u32, - #[serde(default = "ResourceRequirement::default_outdir_min")] + #[serde(default = "ResourceRequirement::outdir_min")] pub outdir_min: u32, } impl ResourceRequirement { - fn default_cores_min() -> u32 { CPU_NUM_DEFAULT } - fn default_ram_min() -> u32 { RAM_SIZE_IN_MB_DEFAULT } - fn default_tmpdir_min() -> u32 { TMPDIR_MIN_IN_MB_DEFAULT } - fn default_outdir_min() -> u32 { OUTDIR_MIN_IN_MB_DEFAULT } + fn cores_min() -> u32 { CPU_NUM_DEFAULT } + fn ram_min() -> u32 { RAM_SIZE_IN_MB_DEFAULT } + fn tmpdir_min() -> u32 { TMPDIR_MIN_IN_MB_DEFAULT } + fn outdir_min() -> u32 { OUTDIR_MIN_IN_MB_DEFAULT } } /// Indicates that the workflow platform must support inline Javascript expressions diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs index 0f1562f..7e39c77 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs @@ -12,12 +12,29 @@ pub enum Any { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum CwlSchemaType { - // Here can be any type: - // Null, Boolean, Int, Long, Float, Double, String, File, Directory - // array, string[], File[], Directory[] + /// Represents any value in field `type` + /// + /// Example: + /// + /// type: boolean + /// ... Any(String), + /// Represents an array type + /// + /// Example: + /// + /// - null + /// - type: array + /// items: File Array(Vec), + + /// Represents a map type + /// + /// Example: + /// + /// type: array + /// items: string Map(HashMap), } From 8810bf5b3213e33a622e6dadce2debdc466739bb Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 21:59:32 +0400 Subject: [PATCH 06/21] Fix ci fails --- .github/workflows/ci.yml | 4 +- Cargo.lock | 772 ---------------------- Cargo.toml | 2 +- zefiro-core/Cargo.toml | 5 + zefiro-core/zefiro-cwl-parser/Cargo.toml | 1 + zefiro-core/zefiro-cwl-parser/README.md | 2 +- zefiro-core/zefiro-cwl-parser/src/main.rs | 20 + 7 files changed, 30 insertions(+), 776 deletions(-) delete mode 100644 Cargo.lock create mode 100644 zefiro-core/zefiro-cwl-parser/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01d9c2d..7ad9303 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Check - run: cargo check --offline --verbose + run: cargo check --locked --verbose - name: Check without default features - run: cargo check --offline --no-default-features --verbose + run: cargo check --locked --no-default-features --verbose typos: name: Typos diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index b3fe791..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,772 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "cc" -version = "1.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-targets", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-macro", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "js-sys" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "pin-project-lite" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "proc-macro-crate" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "rstest" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" -dependencies = [ - "futures-timer", - "futures-util", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" -dependencies = [ - "cfg-if", - "glob", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn", - "unicode-ident", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "semver" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" - -[[package]] -name = "serde" -version = "1.0.217" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.217" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.134" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.7.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.7.0", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "2.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "time" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap 2.7.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "wasm-bindgen" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" -dependencies = [ - "memchr", -] - -[[package]] -name = "zefiro" -version = "0.1.0" - -[[package]] -name = "zefiro-cli" -version = "0.1.0" - -[[package]] -name = "zefiro-cwl-parser" -version = "0.1.0" -dependencies = [ - "anyhow", - "rstest", - "serde", - "serde_with", - "serde_yaml", -] - -[[package]] -name = "zefiro-ui" -version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index d631220..0c381c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [workspace] members = [ "zefiro-cli", - "zefiro-core/zefiro-cwl-parser", + "zefiro-core", "zefiro-ui" ] \ No newline at end of file diff --git a/zefiro-core/Cargo.toml b/zefiro-core/Cargo.toml index f6ef9be..22f5754 100644 --- a/zefiro-core/Cargo.toml +++ b/zefiro-core/Cargo.toml @@ -3,3 +3,8 @@ name = "zefiro-core" version = "0.1.0" edition = "2021" rust-version = "1.83.0" + +[workspace] +members = [ + "zefiro-cwl-parser" +] \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/Cargo.toml b/zefiro-core/zefiro-cwl-parser/Cargo.toml index efa3fc9..7066468 100644 --- a/zefiro-core/zefiro-cwl-parser/Cargo.toml +++ b/zefiro-core/zefiro-cwl-parser/Cargo.toml @@ -14,6 +14,7 @@ homepage = "https://github.com/zefiroproj/zefiro" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/zefiroproj/zefiro" +rust-version = "1.83.0" [dependencies] anyhow = "1.0.95" diff --git a/zefiro-core/zefiro-cwl-parser/README.md b/zefiro-core/zefiro-cwl-parser/README.md index 8fae62f..dfa5f3a 100644 --- a/zefiro-core/zefiro-cwl-parser/README.md +++ b/zefiro-core/zefiro-cwl-parser/README.md @@ -4,7 +4,7 @@ A Rust library for parsing and working with Common Workflow Language (CWL) docum ## Overview -* Supports only some fields of CWL v1.2 specification (see description of stuctures in the code) +* Supports only some fields of CWL v1.2 specification (see description of structures in the code) * Can serialize and deserialize [CommandLineTool](https://www.commonwl.org/v1.2/CommandLineTool.html) and [Workflow](https://www.commonwl.org/v1.2/Workflow.html) documents ## Usage diff --git a/zefiro-core/zefiro-cwl-parser/src/main.rs b/zefiro-core/zefiro-cwl-parser/src/main.rs new file mode 100644 index 0000000..cb8289f --- /dev/null +++ b/zefiro-core/zefiro-cwl-parser/src/main.rs @@ -0,0 +1,20 @@ +use zefiro_cwl_parser::values::{document::CwlValues, types::CwlValueType}; +use zefiro_cwl_parser::schema::document::CwlSchema; + +fn main() { + let file_path = "examples/data/clt-step-values.yml"; + let values = CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); + for (key, value) in values.iter() { + match value { + CwlValueType::File(value) => println!("{} {:?} {:?}", key, value, value.get_location()), + _ => println!("{} {:?}", key, value) + } + } + + let file_path = "examples/data/wf-step-schema.yml"; + let schema = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL values document"); + println!("{:?}", schema); + // for (key, value) in schema.iter() { + // println!("{:?}", value); + // } +} \ No newline at end of file From a4d44b00df921fbe609b72f66852ee2c979dbd35 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:12:23 +0400 Subject: [PATCH 07/21] Lint and format code --- Cargo.toml | 1 + zefiro-core/Cargo.toml | 7 +-- zefiro-core/zefiro-cwl-parser/src/lib.rs | 2 +- zefiro-core/zefiro-cwl-parser/src/main.rs | 20 --------- .../src/schema/command_line_tool.rs | 6 +-- .../zefiro-cwl-parser/src/schema/document.rs | 29 +++++++------ .../zefiro-cwl-parser/src/schema/mod.rs | 4 +- .../src/schema/requirements.rs | 24 +++++++---- .../zefiro-cwl-parser/src/schema/types.rs | 7 ++- .../zefiro-cwl-parser/src/schema/workflow.rs | 11 +++-- .../zefiro-cwl-parser/src/values/document.rs | 43 +++++++++---------- .../zefiro-cwl-parser/src/values/mod.rs | 2 +- .../zefiro-cwl-parser/src/values/types.rs | 5 +-- 13 files changed, 71 insertions(+), 90 deletions(-) delete mode 100644 zefiro-core/zefiro-cwl-parser/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 0c381c7..44714da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,6 @@ edition = "2021" members = [ "zefiro-cli", "zefiro-core", + "zefiro-core/zefiro-cwl-parser", "zefiro-ui" ] \ No newline at end of file diff --git a/zefiro-core/Cargo.toml b/zefiro-core/Cargo.toml index 22f5754..4bd5b2c 100644 --- a/zefiro-core/Cargo.toml +++ b/zefiro-core/Cargo.toml @@ -2,9 +2,4 @@ name = "zefiro-core" version = "0.1.0" edition = "2021" -rust-version = "1.83.0" - -[workspace] -members = [ - "zefiro-cwl-parser" -] \ No newline at end of file +rust-version = "1.83.0" \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/lib.rs b/zefiro-core/zefiro-cwl-parser/src/lib.rs index 91ebe67..d486f41 100644 --- a/zefiro-core/zefiro-cwl-parser/src/lib.rs +++ b/zefiro-core/zefiro-cwl-parser/src/lib.rs @@ -2,4 +2,4 @@ pub mod schema; pub mod values; pub use crate::schema::document::CwlSchema; -pub use crate::values::document::CwlValues; \ No newline at end of file +pub use crate::values::document::CwlValues; diff --git a/zefiro-core/zefiro-cwl-parser/src/main.rs b/zefiro-core/zefiro-cwl-parser/src/main.rs deleted file mode 100644 index cb8289f..0000000 --- a/zefiro-core/zefiro-cwl-parser/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use zefiro_cwl_parser::values::{document::CwlValues, types::CwlValueType}; -use zefiro_cwl_parser::schema::document::CwlSchema; - -fn main() { - let file_path = "examples/data/clt-step-values.yml"; - let values = CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); - for (key, value) in values.iter() { - match value { - CwlValueType::File(value) => println!("{} {:?} {:?}", key, value, value.get_location()), - _ => println!("{} {:?}", key, value) - } - } - - let file_path = "examples/data/wf-step-schema.yml"; - let schema = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL values document"); - println!("{:?}", schema); - // for (key, value) in schema.iter() { - // println!("{:?}", value); - // } -} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 61404ca..8f1e00c 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -1,5 +1,5 @@ -use crate::schema::types::{Any, CwlSchemaType, Documentation}; use crate::schema::requirements::CommandLineToolRequirement; +use crate::schema::types::{Any, CwlSchemaType, Documentation}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -36,7 +36,7 @@ pub struct CommandLineTool { #[serde(rename_all = "camelCase")] pub struct CommandInputParameter { pub id: String, - + pub r#type: CwlSchemaType, #[serde(skip_serializing_if = "Option::is_none")] @@ -82,7 +82,7 @@ pub struct CommandLineBinding { pub struct OutputBinding { #[serde(skip_serializing_if = "Option::is_none")] pub glob: Option, - + #[serde(skip_serializing_if = "Option::is_none")] pub output_eval: Option, } diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 60186ca..8e9cd48 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -3,12 +3,13 @@ use anyhow::{bail, ensure, Error, Result}; use serde::{Deserialize, Serialize}; use serde_yaml::{self, Value}; use std::{ - fs::File, io::{BufReader, Write}, str::FromStr + fs::File, + io::{BufReader, Write}, + str::FromStr, }; const SUPPORTED_VERSIONS: &[&str] = &["v1.2"]; - /// Represents a CWL Schema which can be either a CommandLineTool or a Workflow #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] @@ -19,12 +20,12 @@ pub enum CwlSchema { impl CwlSchema { /// Serializes YAML `file` containing CWL values into CwlSchema structure. - /// + /// /// ``` /// use zefiro_cwl_parser::schema::document::CwlSchema; - /// + /// /// let yaml_file = "examples/data/clt-step-schema.yml"; - /// + /// /// let values = CwlSchema::from_path(yaml_file).expect("Failed to deserialize CWL values document"); /// ``` pub fn from_path(path: &str) -> Result { @@ -35,10 +36,13 @@ impl CwlSchema { /// Deserializes a YAML Value into a CwlSchema instance. pub fn from_yaml(value: Value) -> Result { let version = value - .get("cwlVersion") + .get("cwlVersion") .and_then(Value::as_str) .ok_or_else(|| anyhow::anyhow!("Failed to determine CWL specification version."))?; - ensure!(SUPPORTED_VERSIONS.contains(&version), "Unsupported CWL version: {version}"); + ensure!( + SUPPORTED_VERSIONS.contains(&version), + "Unsupported CWL version: {version}" + ); match value.get("class").and_then(Value::as_str) { Some("CommandLineTool") => Ok(Self::CommandLineTool(serde_yaml::from_value(value)?)), @@ -51,11 +55,11 @@ impl CwlSchema { /// Serializes YAML `string` containing CWL values into CwlValues structure. /// /// # Examples - /// + /// /// ``` /// use serde_yaml::Value; /// use zefiro_cwl_parser::schema::document::CwlSchema; - /// + /// /// let yaml_str = r#" /// cwlVersion: v1.2 /// class: CommandLineTool @@ -88,9 +92,8 @@ impl CwlSchema { /// let schema = CwlSchema::from_string(yaml_str).expect("Failed to parse CWL document"); /// ``` pub fn from_string(yaml_input: &str) -> Result { - serde_yaml::from_str(yaml_input).map_err(|e| { - Error::msg(format!("Failed to parse CWL schema from string: {}", e)) - }) + serde_yaml::from_str(yaml_input) + .map_err(|e| Error::msg(format!("Failed to parse CWL schema from string: {}", e))) } /// Deserializes CwlValues structure into `string`. @@ -123,4 +126,4 @@ mod tests { fn test_parse_correct_schema(#[case] file_path: &str) { CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); } -} \ No newline at end of file +} diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs b/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs index 67f3d24..2d580dd 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/mod.rs @@ -1,5 +1,5 @@ -pub mod workflow; pub mod command_line_tool; +pub mod document; pub mod requirements; pub mod types; -pub mod document; \ No newline at end of file +pub mod workflow; diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs index 73b199a..fbaa05b 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs @@ -7,7 +7,6 @@ const RAM_SIZE_IN_MB_DEFAULT: u32 = 1024; const TMPDIR_MIN_IN_MB_DEFAULT: u32 = 1024; const OUTDIR_MIN_IN_MB_DEFAULT: u32 = 1024; - /// Describes requirements for `Workflow`. #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] @@ -25,7 +24,7 @@ pub enum CommandLineToolRequirement { ResourceRequirement(ResourceRequirement), InlineJavascriptRequirement(InlineJavascriptRequirement), ToolTimeLimit(ToolTimeLimit), - WorkReuse(WorkReuse) + WorkReuse(WorkReuse), } /// Specifies Docker container requirements. @@ -45,7 +44,7 @@ pub struct DockerRequirement { pub struct ResourceRequirement { #[serde(default = "ResourceRequirement::cores_min")] pub cores_min: u32, - + #[serde(default = "ResourceRequirement::ram_min")] pub ram_min: u32, @@ -57,10 +56,18 @@ pub struct ResourceRequirement { } impl ResourceRequirement { - fn cores_min() -> u32 { CPU_NUM_DEFAULT } - fn ram_min() -> u32 { RAM_SIZE_IN_MB_DEFAULT } - fn tmpdir_min() -> u32 { TMPDIR_MIN_IN_MB_DEFAULT } - fn outdir_min() -> u32 { OUTDIR_MIN_IN_MB_DEFAULT } + fn cores_min() -> u32 { + CPU_NUM_DEFAULT + } + fn ram_min() -> u32 { + RAM_SIZE_IN_MB_DEFAULT + } + fn tmpdir_min() -> u32 { + TMPDIR_MIN_IN_MB_DEFAULT + } + fn outdir_min() -> u32 { + OUTDIR_MIN_IN_MB_DEFAULT + } } /// Indicates that the workflow platform must support inline Javascript expressions @@ -83,7 +90,6 @@ pub struct ToolTimeLimit { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ScatterFeatureRequirement; - /// Specifies a reusing output from past work of a `CommandLineTool`. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html#WorkReuse #[skip_serializing_none] @@ -91,4 +97,4 @@ pub struct ScatterFeatureRequirement; #[serde(rename_all = "camelCase")] pub struct WorkReuse { pub enable_reuse: bool, -} \ No newline at end of file +} diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs index 7e39c77..1fa76ec 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/types.rs @@ -13,13 +13,13 @@ pub enum Any { #[serde(untagged)] pub enum CwlSchemaType { /// Represents any value in field `type` - /// + /// /// Example: - /// + /// /// type: boolean /// ... Any(String), - + /// Represents an array type /// /// Example: @@ -38,7 +38,6 @@ pub enum CwlSchemaType { Map(HashMap), } - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged, rename_all = "camelCase")] pub enum Documentation { diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs index e993354..894b6ee 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs @@ -1,6 +1,6 @@ use crate::schema::command_line_tool::CommandLineTool; -use crate::schema::types::{Any, Documentation, Scatter, Source, CwlSchemaType}; use crate::schema::requirements::WorkflowRequirement; +use crate::schema::types::{Any, CwlSchemaType, Documentation, Scatter, Source}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -18,7 +18,7 @@ pub struct Workflow { pub inputs: Vec, pub outputs: Vec, pub steps: Vec, - pub requirements: Vec + pub requirements: Vec, } /// Represents an input parameter for a `Workflow`. @@ -43,10 +43,9 @@ pub struct WorkflowOutputParameter { pub label: Option, pub doc: Option, pub id: Option, - pub output_source: Option + pub output_source: Option, } - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged, rename_all = "camelCase")] pub enum WorkflowOutputParameterOutputSource { @@ -87,5 +86,5 @@ pub struct WorkflowStepInput { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct WorkflowStepOutput { - pub id: String -} \ No newline at end of file + pub id: String, +} diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index 185d828..41aa0a5 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -3,14 +3,17 @@ use anyhow::{Error, Result}; use serde::{Deserialize, Serialize}; use serde_yaml; use std::{ - collections::HashMap, fs::File, io::{BufReader, Write}, ops::Deref + collections::HashMap, + fs::File, + io::{BufReader, Write}, + ops::Deref, }; /// Represents a collection of CWL input and output values as key-value pairs #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CwlValues { #[serde(flatten)] - values: HashMap + values: HashMap, } impl Deref for CwlValues { @@ -23,49 +26,45 @@ impl Deref for CwlValues { impl CwlValues { /// Serializes YAML `file` containing CWL values into CwlValues structure. - /// + /// /// ``` /// use zefiro_cwl_parser::values::document::CwlValues; - /// /// let yaml_file = "examples/data/clt-step-values.yml"; - /// /// let values = CwlValues::from_path(yaml_file).expect("Failed to deserialize CWL values document"); /// ``` pub fn from_path(path: &str) -> Result { - let reader = BufReader::new(File::open(path).map_err(|e| { - Error::msg(format!("Failed to open file '{}': {}", path, e)) - })?); - - serde_yaml::from_reader(reader).map_err(|e| { - Error::msg(format!("Failed to parse CWL values from '{}'; {}", path, e)) - }) + let reader = BufReader::new( + File::open(path) + .map_err(|e| Error::msg(format!("Failed to open file '{}': {}", path, e)))?, + ); + + serde_yaml::from_reader(reader) + .map_err(|e| Error::msg(format!("Failed to parse CWL values from '{}'; {}", path, e))) } /// Serializes YAML `string` containing CWL values into CwlValues structure. - /// + /// /// ``` /// use zefiro_cwl_parser::values::document::CwlValues; - /// + /// /// let yaml_input = r#" /// in_file: /// class: File /// location: 's3://bucket/path/to/input.txt' /// out_file: 'output.txt' /// "#; - /// + /// /// let values = CwlValues::from_string(yaml_input).expect("Failed to deserialize CWL values document"); /// ``` pub fn from_string(yaml_input: &str) -> Result { - serde_yaml::from_str(yaml_input).map_err(|e| { - Error::msg(format!("Failed to parse CWL values from string: {}", e)) - }) + serde_yaml::from_str(yaml_input) + .map_err(|e| Error::msg(format!("Failed to parse CWL values from string: {}", e))) } /// Deserializes CwlValues structure into `string`. pub fn to_string(&self) -> Result { - serde_yaml::to_string(self).map_err(|e| { - Error::msg(format!("Failed to serialize CWL values to string: {}", e)) - }) + serde_yaml::to_string(self) + .map_err(|e| Error::msg(format!("Failed to serialize CWL values to string: {}", e))) } /// Deserializes CwlValues structure and writes it into `file`. @@ -84,4 +83,4 @@ mod tests { fn test_parse_correct_values(#[case] file_path: &str) { CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); } -} \ No newline at end of file +} diff --git a/zefiro-core/zefiro-cwl-parser/src/values/mod.rs b/zefiro-core/zefiro-cwl-parser/src/values/mod.rs index 6705fde..6c0590c 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/mod.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/mod.rs @@ -1,2 +1,2 @@ +pub mod document; pub mod types; -pub mod document; \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs index 5301662..ae962f2 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -28,7 +28,6 @@ impl Directory { } } - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum CwlValueType { @@ -40,5 +39,5 @@ pub enum CwlValueType { String(String), File(File), Directory(Directory), - Array(Vec) -} \ No newline at end of file + Array(Vec), +} From 7c4411283e6b40c3d6301c8bc4c50b7e2f47974b Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:16:00 +0400 Subject: [PATCH 08/21] Remove --locked from ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ad9303..50fcb1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Check - run: cargo check --locked --verbose + run: cargo check --verbose - name: Check without default features - run: cargo check --locked --no-default-features --verbose + run: cargo check --no-default-features --verbose typos: name: Typos From ee3fc03812750123f597fc312ec595617818d9a4 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 20:36:56 +0400 Subject: [PATCH 09/21] Refactore code --- .github/workflows/cd.yml | 4 +--- zefiro-core/zefiro-cwl-parser/README.md | 2 +- .../src/schema/command_line_tool.rs | 3 +-- .../src/schema/requirements.rs | 18 ++++++++++++------ .../zefiro-cwl-parser/src/schema/workflow.rs | 2 +- .../zefiro-cwl-parser/src/values/types.rs | 4 ++-- 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 76da2ba..fdca208 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -33,9 +33,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Verify package - run: cargo verify-project - - name: Run tests - run: cargo test --all-features + run: cargo verify-project --manifest-path zefiro-core/zefiro-cwl-parser/Cargo.toml - name: Set the release version run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> "$GITHUB_ENV" - name: Install Rust toolchain diff --git a/zefiro-core/zefiro-cwl-parser/README.md b/zefiro-core/zefiro-cwl-parser/README.md index dfa5f3a..2f5a813 100644 --- a/zefiro-core/zefiro-cwl-parser/README.md +++ b/zefiro-core/zefiro-cwl-parser/README.md @@ -13,7 +13,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -zefiro-cwl-parser = +zefiro-cwl-parser = "0.1.0" ``` diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 8f1e00c..65e5a26 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -16,8 +16,7 @@ pub struct CommandLineTool { #[serde(skip_serializing_if = "Option::is_none")] pub doc: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub id: Option, + pub id: String, #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs index fbaa05b..0319651 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs @@ -1,4 +1,3 @@ -use crate::schema::types::Any; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -56,16 +55,16 @@ pub struct ResourceRequirement { } impl ResourceRequirement { - fn cores_min() -> u32 { + const fn cores_min() -> u32 { CPU_NUM_DEFAULT } - fn ram_min() -> u32 { + const fn ram_min() -> u32 { RAM_SIZE_IN_MB_DEFAULT } - fn tmpdir_min() -> u32 { + const fn tmpdir_min() -> u32 { TMPDIR_MIN_IN_MB_DEFAULT } - fn outdir_min() -> u32 { + const fn outdir_min() -> u32 { OUTDIR_MIN_IN_MB_DEFAULT } } @@ -81,7 +80,14 @@ pub struct InlineJavascriptRequirement; #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ToolTimeLimit { - pub timelimit: Any, + pub timelimit: Timelimit, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +pub enum Timelimit { + Seconds(u32), + Expression(String), } /// Specifies that the workflow platform must support the scatter and `scatterMethod` fields of `WorkflowStep`. diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs index 894b6ee..413305f 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs @@ -81,7 +81,7 @@ pub struct WorkflowStepInput { pub value_from: Option, } -/// Defines the output parameters of the workflow step (`in` section). +/// Defines the output parameters of the workflow step (`out` section). #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs index ae962f2..5bc1d57 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -23,8 +23,8 @@ pub struct Directory { } impl Directory { - pub fn get_location(&self) -> String { - self.location.clone() + pub fn get_location(&self) -> &str { + &self.location } } From a7ba5afc592632037a23ef13c255b9e476328506 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:00:59 +0400 Subject: [PATCH 10/21] Fix bug with File/Directory type selecting and refactor code --- zefiro-core/zefiro-cwl-parser/Cargo.toml | 1 + .../src/schema/command_line_tool.rs | 34 ++++++++++++++----- .../zefiro-cwl-parser/src/values/document.rs | 17 ++++++++++ .../zefiro-cwl-parser/src/values/types.rs | 17 ++++++---- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/Cargo.toml b/zefiro-core/zefiro-cwl-parser/Cargo.toml index 7066468..014c45b 100644 --- a/zefiro-core/zefiro-cwl-parser/Cargo.toml +++ b/zefiro-core/zefiro-cwl-parser/Cargo.toml @@ -24,3 +24,4 @@ serde_yaml = "0.9.34" [dev-dependencies] rstest = "0.24.0" +tempfile = "3.15.0" diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 65e5a26..4970adb 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -6,28 +6,43 @@ use serde_with::skip_serializing_none; /// This defines the schema of the CWL Command Line Tool Description document. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html #[skip_serializing_none] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommandLineTool { pub cwl_version: String, - pub class: String, - #[serde(skip_serializing_if = "Option::is_none")] pub doc: Option, - pub id: String, - #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, - pub inputs: Vec, - pub outputs: Vec, - pub requirements: Vec, } +impl CommandLineTool { + fn has_docker_requirement(&self) -> bool { + self.requirements + .iter() + .any(|req| matches!(req, CommandLineToolRequirement::DockerRequirement(_))) + } +} + +impl Serialize for CommandLineTool { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if !self.has_docker_requirement() { + return Err(serde::ser::Error::custom("CommandLineTool must have DockerRequirement")); + } + #[derive(Serialize)] + struct CommandLineToolHelper<'a>(&'a CommandLineTool); + CommandLineToolHelper(self).serialize(serializer) + } +} + /// Represents an input parameter for a `CommandLineTool`. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandInputParameter #[skip_serializing_none] @@ -74,7 +89,8 @@ pub struct CommandLineBinding { pub value_from: Option, } -/// Describes output binding rules for a `CommandLineTool`. +/// Describes how to find and capture output files or values from a CommandLineTool execution. +/// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandOutputBinding #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index 41aa0a5..b132180 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -68,6 +68,23 @@ impl CwlValues { } /// Deserializes CwlValues structure and writes it into `file`. + /// + /// ``` + /// use zefiro_cwl_parser::values::document::CwlValues; + /// use std::io::BufWriter; + /// + /// let yaml_input = r#" + /// in_file: + /// class: File + /// location: 's3://bucket/path/to/input.txt' + /// out_file: 'output.txt' + /// "#; + /// + /// let values = CwlValues::from_string(yaml_input).expect("Failed to deserialize CWL values document"); + /// let mut tmpfile = tempfile::tempfile().unwrap(); + /// let mut writer = BufWriter::new(tmpfile); + /// values.to_yaml(writer); + /// ``` pub fn to_yaml(&self, writer: W) -> Result<()> { serde_yaml::to_writer(writer, self).map_err(Into::into) } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs index 5bc1d57..65f3b05 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -1,10 +1,8 @@ use serde::{Deserialize, Serialize}; /// Represents a `File` object in CWL -/// see: https://www.commonwl.org/v1.2/CommandLineTool.html#File #[derive(Clone, Debug, Deserialize, Serialize)] pub struct File { - pub class: String, pub location: String, } @@ -15,10 +13,8 @@ impl File { } /// Represents a `Directory` object in CWL -/// see: https://www.commonwl.org/v1.2/CommandLineTool.html#Directory #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Directory { - pub class: String, pub location: String, } @@ -28,6 +24,14 @@ impl Directory { } } +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "class", rename_all = "PascalCase")] +pub enum Path { + File(File), + Directory(Directory), +} + +/// CWL value types with tagged enum for `File` and `Directory` #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum CwlValueType { @@ -37,7 +41,6 @@ pub enum CwlValueType { Float(f32), Double(f64), String(String), - File(File), - Directory(Directory), + Path(Path), Array(Vec), -} +} \ No newline at end of file From c3b38c6589d1e27e54c0949afa82a0bb9f81d6cc Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:12:41 +0400 Subject: [PATCH 11/21] Fix formatting --- zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs | 4 +++- zefiro-core/zefiro-cwl-parser/src/values/types.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 4970adb..055e0b6 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -35,7 +35,9 @@ impl Serialize for CommandLineTool { S: serde::Serializer, { if !self.has_docker_requirement() { - return Err(serde::ser::Error::custom("CommandLineTool must have DockerRequirement")); + return Err(serde::ser::Error::custom( + "CommandLineTool must have DockerRequirement", + )); } #[derive(Serialize)] struct CommandLineToolHelper<'a>(&'a CommandLineTool); diff --git a/zefiro-core/zefiro-cwl-parser/src/values/types.rs b/zefiro-core/zefiro-cwl-parser/src/values/types.rs index 65f3b05..7b3f807 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/types.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/types.rs @@ -43,4 +43,4 @@ pub enum CwlValueType { String(String), Path(Path), Array(Vec), -} \ No newline at end of file +} From f4735c706116f64cc13fe4fcb2350faceacbad1d Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:21:53 +0400 Subject: [PATCH 12/21] Update cd.yml and Cargo.toml of cwl-parser --- .github/workflows/cd.yml | 8 ++++---- zefiro-core/zefiro-cwl-parser/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index fdca208..a3b9a87 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -38,7 +38,7 @@ jobs: run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> "$GITHUB_ENV" - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - # - name: Publish the zefiro-core library - # run: | - # cargo publish --manifest-path zefiro-core/Cargo.toml \ - # --locked --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file + - name: Publish the zefiro-cwl-parser library + run: | + cargo publish --manifest-path zefiro-core/zefiro-cwl-parser/Cargo.toml \ + --locked --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file diff --git a/zefiro-core/zefiro-cwl-parser/Cargo.toml b/zefiro-core/zefiro-cwl-parser/Cargo.toml index 014c45b..26a9294 100644 --- a/zefiro-core/zefiro-cwl-parser/Cargo.toml +++ b/zefiro-core/zefiro-cwl-parser/Cargo.toml @@ -7,8 +7,8 @@ description = """ authors = [ "Nikita Syzrantsev " ] -categories = ["Common Workflow Language", "CWL"] -keywords = ["CWL", "CommanLineTool", "Workflow"] +categories = ["CWL serialization", "CWL deserialization", "Common Workflow Language"] +keywords = ["CWL", "CommandLineTool", "Workflow"] edition = "2021" homepage = "https://github.com/zefiroproj/zefiro" license = "Apache-2.0" From 1e71ffea3e3dca0c976509c20d9613db007b9f27 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:56:06 +0400 Subject: [PATCH 13/21] Add test and removed custom serializator --- .../src/schema/command_line_tool.rs | 26 +------------------ .../zefiro-cwl-parser/src/schema/document.rs | 19 +++++++++++--- .../zefiro-cwl-parser/src/values/document.rs | 14 +++++----- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 055e0b6..3030b64 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -6,7 +6,7 @@ use serde_with::skip_serializing_none; /// This defines the schema of the CWL Command Line Tool Description document. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html #[skip_serializing_none] -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CommandLineTool { pub cwl_version: String, @@ -21,30 +21,6 @@ pub struct CommandLineTool { pub requirements: Vec, } -impl CommandLineTool { - fn has_docker_requirement(&self) -> bool { - self.requirements - .iter() - .any(|req| matches!(req, CommandLineToolRequirement::DockerRequirement(_))) - } -} - -impl Serialize for CommandLineTool { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - if !self.has_docker_requirement() { - return Err(serde::ser::Error::custom( - "CommandLineTool must have DockerRequirement", - )); - } - #[derive(Serialize)] - struct CommandLineToolHelper<'a>(&'a CommandLineTool); - CommandLineToolHelper(self).serialize(serializer) - } -} - /// Represents an input parameter for a `CommandLineTool`. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandInputParameter #[skip_serializing_none] diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 8e9cd48..d894c44 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -19,7 +19,7 @@ pub enum CwlSchema { } impl CwlSchema { - /// Serializes YAML `file` containing CWL values into CwlSchema structure. + /// Deserializes YAML `file` containing CWL values into CwlSchema structure. /// /// ``` /// use zefiro_cwl_parser::schema::document::CwlSchema; @@ -52,7 +52,7 @@ impl CwlSchema { } } - /// Serializes YAML `string` containing CWL values into CwlValues structure. + /// Deserializes YAML `string` containing CWL values into CwlValues structure. /// /// # Examples /// @@ -96,12 +96,23 @@ impl CwlSchema { .map_err(|e| Error::msg(format!("Failed to parse CWL schema from string: {}", e))) } - /// Deserializes CwlValues structure into `string`. + /// Serializes CwlSchema structure into `string`. pub fn to_string(&self) -> Result { serde_yaml::to_string(self).map_err(Into::into) } - /// Deserializes CwlValues structure and writes it into `file`. + /// Serializes CwlSchema structure and writes it into `file`. + /// ``` + /// use zefiro_cwl_parser::schema::document::CwlSchema; + /// use std::fs::File; + /// use std::io::BufWriter; + /// + /// let yaml_file = "examples/data/clt-step-schema.yml"; + /// let schema = CwlSchema::from_path(yaml_file).expect("Failed to serialize CWL schema document"); + /// let mut tmpfile = tempfile::tempfile().unwrap(); + /// let mut writer = BufWriter::new(tmpfile); + /// schema.to_yaml(writer); + /// ``` pub fn to_yaml(&self, writer: W) -> Result<()> { serde_yaml::to_writer(writer, self).map_err(Into::into) } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index b132180..b6a1ace 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -25,7 +25,7 @@ impl Deref for CwlValues { } impl CwlValues { - /// Serializes YAML `file` containing CWL values into CwlValues structure. + /// Deserializes YAML `file` containing CWL values into CwlValues structure. /// /// ``` /// use zefiro_cwl_parser::values::document::CwlValues; @@ -39,10 +39,10 @@ impl CwlValues { ); serde_yaml::from_reader(reader) - .map_err(|e| Error::msg(format!("Failed to parse CWL values from '{}'; {}", path, e))) + .map_err(|e| Error::msg(format!("Failed to deserialize CWL values from '{}'; {}", path, e))) } - /// Serializes YAML `string` containing CWL values into CwlValues structure. + /// Deserializes YAML `string` containing CWL values into CwlValues structure. /// /// ``` /// use zefiro_cwl_parser::values::document::CwlValues; @@ -58,16 +58,16 @@ impl CwlValues { /// ``` pub fn from_string(yaml_input: &str) -> Result { serde_yaml::from_str(yaml_input) - .map_err(|e| Error::msg(format!("Failed to parse CWL values from string: {}", e))) + .map_err(|e| Error::msg(format!("Failed to deserialize CWL values from string: {}", e))) } /// Deserializes CwlValues structure into `string`. pub fn to_string(&self) -> Result { serde_yaml::to_string(self) - .map_err(|e| Error::msg(format!("Failed to serialize CWL values to string: {}", e))) + .map_err(|e| Error::msg(format!("Failed to dserialize CWL values to string: {}", e))) } - /// Deserializes CwlValues structure and writes it into `file`. + /// Serializes CwlValues structure and writes it into `file`. /// /// ``` /// use zefiro_cwl_parser::values::document::CwlValues; @@ -80,7 +80,7 @@ impl CwlValues { /// out_file: 'output.txt' /// "#; /// - /// let values = CwlValues::from_string(yaml_input).expect("Failed to deserialize CWL values document"); + /// let values = CwlValues::from_string(yaml_input).expect("Failed to serialize CWL values document"); /// let mut tmpfile = tempfile::tempfile().unwrap(); /// let mut writer = BufWriter::new(tmpfile); /// values.to_yaml(writer); From 43cd16de583053c81e64d2366adeec5c9aeea917 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:57:02 +0400 Subject: [PATCH 14/21] Fix formatting --- .../zefiro-cwl-parser/src/values/document.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index b6a1ace..60874b3 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -38,8 +38,12 @@ impl CwlValues { .map_err(|e| Error::msg(format!("Failed to open file '{}': {}", path, e)))?, ); - serde_yaml::from_reader(reader) - .map_err(|e| Error::msg(format!("Failed to deserialize CWL values from '{}'; {}", path, e))) + serde_yaml::from_reader(reader).map_err(|e| { + Error::msg(format!( + "Failed to deserialize CWL values from '{}'; {}", + path, e + )) + }) } /// Deserializes YAML `string` containing CWL values into CwlValues structure. @@ -57,8 +61,12 @@ impl CwlValues { /// let values = CwlValues::from_string(yaml_input).expect("Failed to deserialize CWL values document"); /// ``` pub fn from_string(yaml_input: &str) -> Result { - serde_yaml::from_str(yaml_input) - .map_err(|e| Error::msg(format!("Failed to deserialize CWL values from string: {}", e))) + serde_yaml::from_str(yaml_input).map_err(|e| { + Error::msg(format!( + "Failed to deserialize CWL values from string: {}", + e + )) + }) } /// Deserializes CwlValues structure into `string`. From b5f787633d749ade37ea79891162fb27e1c88afb Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 23:05:45 +0400 Subject: [PATCH 15/21] Add tests --- zefiro-core/zefiro-cwl-parser/src/schema/document.rs | 10 ++++++++++ zefiro-core/zefiro-cwl-parser/src/values/document.rs | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index d894c44..c31fe6f 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -130,6 +130,7 @@ impl FromStr for CwlSchema { mod tests { use super::*; use rstest::rstest; + use std::io::BufWriter; #[rstest] #[case("examples/data/clt-step-schema.yml")] @@ -137,4 +138,13 @@ mod tests { fn test_parse_correct_schema(#[case] file_path: &str) { CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); } + + #[rstest] + #[case("examples/data/clt-step-schema.yml", tempfile::tempfile().unwrap())] + #[case("examples/data/wf-step-schema.yml", tempfile::tempfile().unwrap())] + fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { + let schema = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); + let writer = BufWriter::new(output_path); + let _ = schema.to_yaml(writer); + } } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index 60874b3..f55d104 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -102,10 +102,19 @@ impl CwlValues { mod tests { use super::*; use rstest::rstest; + use std::io::BufWriter; #[rstest] #[case("examples/data/clt-step-values.yml")] fn test_parse_correct_values(#[case] file_path: &str) { CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); } + + #[rstest] + #[case("examples/data/clt-step-values.yml", tempfile::tempfile().unwrap())] + fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { + let schema = CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); + let writer = BufWriter::new(output_path); + let _ = schema.to_yaml(writer); + } } From bca35519525d603a246e6ffb2fee19f629cd732a Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sat, 4 Jan 2025 23:07:08 +0400 Subject: [PATCH 16/21] Fix formatting --- zefiro-core/zefiro-cwl-parser/src/schema/document.rs | 3 ++- zefiro-core/zefiro-cwl-parser/src/values/document.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index c31fe6f..322b7d7 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -143,7 +143,8 @@ mod tests { #[case("examples/data/clt-step-schema.yml", tempfile::tempfile().unwrap())] #[case("examples/data/wf-step-schema.yml", tempfile::tempfile().unwrap())] fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { - let schema = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); + let schema = + CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); let writer = BufWriter::new(output_path); let _ = schema.to_yaml(writer); } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index f55d104..c1d15a8 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -113,7 +113,8 @@ mod tests { #[rstest] #[case("examples/data/clt-step-values.yml", tempfile::tempfile().unwrap())] fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { - let schema = CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); + let schema = + CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); let writer = BufWriter::new(output_path); let _ = schema.to_yaml(writer); } From 01f2db81c6eb39ce95f8fb20da08cd215bf8462c Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:53:24 +0400 Subject: [PATCH 17/21] Update tests --- .../zefiro-cwl-parser/src/schema/document.rs | 44 ++++++++++++++++--- .../zefiro-cwl-parser/src/values/document.rs | 41 ++++++++++++++--- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 322b7d7..f21f795 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -131,6 +131,7 @@ mod tests { use super::*; use rstest::rstest; use std::io::BufWriter; + use std::io::Read; #[rstest] #[case("examples/data/clt-step-schema.yml")] @@ -140,12 +141,45 @@ mod tests { } #[rstest] - #[case("examples/data/clt-step-schema.yml", tempfile::tempfile().unwrap())] - #[case("examples/data/wf-step-schema.yml", tempfile::tempfile().unwrap())] - fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { + #[case("examples/data/clt-step-schema.yml", tempfile::NamedTempFile::new().unwrap())] + #[case("examples/data/wf-step-schema.yml", tempfile::NamedTempFile::new().unwrap())] + fn test_save_schema_to_yaml( + #[case] file_path: &str, + #[case] temp_file: tempfile::NamedTempFile, + ) { let schema = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); - let writer = BufWriter::new(output_path); - let _ = schema.to_yaml(writer); + let output_path = temp_file.path().to_path_buf(); + + // Write the schema to the temporary file + { + let writer = BufWriter::new(File::create(&output_path).expect("Failed to create file")); + schema + .to_yaml(writer) + .expect("Failed to serialize schema to YAML"); + } + + // Verify the written content by reading it back + let written_content = { + let mut reader = + BufReader::new(File::open(&output_path).expect("Failed to open temporary file")); + let mut content = String::new(); + reader + .read_to_string(&mut content) + .expect("Failed to read written content"); + content + }; + + // Parse both as CwlSchema and compare the resulting structures instead of raw YAML + let original_schema = + CwlSchema::from_path(file_path).expect("Failed to parse original file"); + let written_schema = + CwlSchema::from_string(&written_content).expect("Failed to parse written content"); + + assert_eq!( + serde_yaml::to_value(&original_schema).unwrap(), + serde_yaml::to_value(&written_schema).unwrap(), + "Serialized content doesn't match original" + ); } } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index c1d15a8..969ed94 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -103,6 +103,7 @@ mod tests { use super::*; use rstest::rstest; use std::io::BufWriter; + use std::io::Read; #[rstest] #[case("examples/data/clt-step-values.yml")] @@ -111,11 +112,41 @@ mod tests { } #[rstest] - #[case("examples/data/clt-step-values.yml", tempfile::tempfile().unwrap())] - fn test_save_schema_to_yaml(#[case] file_path: &str, #[case] output_path: File) { + #[case("examples/data/clt-step-values.yml", tempfile::NamedTempFile::new().unwrap())] + fn test_cwlvalues_to_yaml(#[case] file_path: &str, #[case] temp_file: tempfile::NamedTempFile) { let schema = - CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); - let writer = BufWriter::new(output_path); - let _ = schema.to_yaml(writer); + CwlValues::from_path(file_path).expect("Failed to deserialize CWL schema document"); + let output_path = temp_file.path().to_path_buf(); + + // Write the schema to the temporary file + { + let writer = BufWriter::new(File::create(&output_path).expect("Failed to create file")); + schema + .to_yaml(writer) + .expect("Failed to serialize schema to YAML"); + } + + // Verify the written content by reading it back + let written_content = { + let mut reader = + BufReader::new(File::open(&output_path).expect("Failed to open temporary file")); + let mut content = String::new(); + reader + .read_to_string(&mut content) + .expect("Failed to read written content"); + content + }; + + // Parse both as CwlValues and compare the resulting structures instead of raw YAML + let original_schema: CwlValues = + CwlValues::from_path(file_path).expect("Failed to parse original file"); + let written_schema = + CwlValues::from_string(&written_content).expect("Failed to parse written content"); + + assert_eq!( + serde_yaml::to_value(&original_schema).unwrap(), + serde_yaml::to_value(&written_schema).unwrap(), + "Serialized content doesn't match original" + ); } } From b7d238974d44e20542cfc7a1e7d3a79573bbb0f9 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:57:50 +0400 Subject: [PATCH 18/21] Reduce code of tests --- .../zefiro-cwl-parser/src/schema/document.rs | 52 +++++-------------- .../zefiro-cwl-parser/src/values/document.rs | 47 +++++------------ 2 files changed, 27 insertions(+), 72 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index f21f795..10cab7a 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -131,55 +131,31 @@ mod tests { use super::*; use rstest::rstest; use std::io::BufWriter; - use std::io::Read; #[rstest] #[case("examples/data/clt-step-schema.yml")] #[case("examples/data/wf-step-schema.yml")] - fn test_parse_correct_schema(#[case] file_path: &str) { + fn test_cwlschema_from_path(#[case] file_path: &str) { CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); } #[rstest] - #[case("examples/data/clt-step-schema.yml", tempfile::NamedTempFile::new().unwrap())] - #[case("examples/data/wf-step-schema.yml", tempfile::NamedTempFile::new().unwrap())] - fn test_save_schema_to_yaml( - #[case] file_path: &str, - #[case] temp_file: tempfile::NamedTempFile, - ) { - let schema = - CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema document"); - let output_path = temp_file.path().to_path_buf(); - - // Write the schema to the temporary file - { - let writer = BufWriter::new(File::create(&output_path).expect("Failed to create file")); - schema - .to_yaml(writer) - .expect("Failed to serialize schema to YAML"); - } - - // Verify the written content by reading it back - let written_content = { - let mut reader = - BufReader::new(File::open(&output_path).expect("Failed to open temporary file")); - let mut content = String::new(); - reader - .read_to_string(&mut content) - .expect("Failed to read written content"); - content - }; + #[case("examples/data/clt-step-schema.yml")] + #[case("examples/data/wf-step-schema.yml")] + fn test_cwlschema_to_yaml(#[case] file_path: &str) { + let values = CwlSchema::from_path(file_path).expect("Failed to deserialize CWL schema"); + let temp_file = tempfile::NamedTempFile::new().unwrap(); - // Parse both as CwlSchema and compare the resulting structures instead of raw YAML - let original_schema = - CwlSchema::from_path(file_path).expect("Failed to parse original file"); - let written_schema = - CwlSchema::from_string(&written_content).expect("Failed to parse written content"); + // Write values to temp file + let writer = BufWriter::new(File::create(temp_file.path()).unwrap()); + values.to_yaml(writer).expect("Failed to write YAML"); + // Read and parse written content + let written_values = CwlSchema::from_path(temp_file.path().to_str().unwrap()) + .expect("Failed to read written YAML"); assert_eq!( - serde_yaml::to_value(&original_schema).unwrap(), - serde_yaml::to_value(&written_schema).unwrap(), - "Serialized content doesn't match original" + serde_yaml::to_value(&values).unwrap(), + serde_yaml::to_value(&written_values).unwrap() ); } } diff --git a/zefiro-core/zefiro-cwl-parser/src/values/document.rs b/zefiro-core/zefiro-cwl-parser/src/values/document.rs index 969ed94..6244e30 100644 --- a/zefiro-core/zefiro-cwl-parser/src/values/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/values/document.rs @@ -103,50 +103,29 @@ mod tests { use super::*; use rstest::rstest; use std::io::BufWriter; - use std::io::Read; #[rstest] #[case("examples/data/clt-step-values.yml")] - fn test_parse_correct_values(#[case] file_path: &str) { + fn test_cwlvalues_from_path(#[case] file_path: &str) { CwlValues::from_path(file_path).expect("Failed to deserialize CWL values document"); } #[rstest] - #[case("examples/data/clt-step-values.yml", tempfile::NamedTempFile::new().unwrap())] - fn test_cwlvalues_to_yaml(#[case] file_path: &str, #[case] temp_file: tempfile::NamedTempFile) { - let schema = - CwlValues::from_path(file_path).expect("Failed to deserialize CWL schema document"); - let output_path = temp_file.path().to_path_buf(); - - // Write the schema to the temporary file - { - let writer = BufWriter::new(File::create(&output_path).expect("Failed to create file")); - schema - .to_yaml(writer) - .expect("Failed to serialize schema to YAML"); - } - - // Verify the written content by reading it back - let written_content = { - let mut reader = - BufReader::new(File::open(&output_path).expect("Failed to open temporary file")); - let mut content = String::new(); - reader - .read_to_string(&mut content) - .expect("Failed to read written content"); - content - }; + #[case("examples/data/clt-step-values.yml")] + fn test_cwlvalues_to_yaml(#[case] file_path: &str) { + let values = CwlValues::from_path(file_path).expect("Failed to deserialize CWL values"); + let temp_file = tempfile::NamedTempFile::new().unwrap(); - // Parse both as CwlValues and compare the resulting structures instead of raw YAML - let original_schema: CwlValues = - CwlValues::from_path(file_path).expect("Failed to parse original file"); - let written_schema = - CwlValues::from_string(&written_content).expect("Failed to parse written content"); + // Write values to temp file + let writer = BufWriter::new(File::create(temp_file.path()).unwrap()); + values.to_yaml(writer).expect("Failed to write YAML"); + // Read and parse written content + let written_values = CwlValues::from_path(temp_file.path().to_str().unwrap()) + .expect("Failed to read written YAML"); assert_eq!( - serde_yaml::to_value(&original_schema).unwrap(), - serde_yaml::to_value(&written_schema).unwrap(), - "Serialized content doesn't match original" + serde_yaml::to_value(&values).unwrap(), + serde_yaml::to_value(&written_values).unwrap() ); } } From 1fc7002b46dc9decc5536cd86bcdaf7c2354b4c6 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sun, 5 Jan 2025 18:27:30 +0400 Subject: [PATCH 19/21] Add new tests and reformat code --- .../src/schema/command_line_tool.rs | 20 ++++++++- .../zefiro-cwl-parser/src/schema/document.rs | 44 +++++++++++++++++-- .../src/schema/requirements.rs | 2 + .../zefiro-cwl-parser/src/schema/workflow.rs | 19 ++++++-- 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs index 3030b64..23dda70 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/command_line_tool.rs @@ -1,4 +1,4 @@ -use crate::schema::requirements::CommandLineToolRequirement; +use crate::schema::requirements::{CommandLineToolRequirement, SUPPORTED_CWL_VERSIONS}; use crate::schema::types::{Any, CwlSchemaType, Documentation}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -6,21 +6,37 @@ use serde_with::skip_serializing_none; /// This defines the schema of the CWL Command Line Tool Description document. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html #[skip_serializing_none] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Default)] #[serde(rename_all = "camelCase")] pub struct CommandLineTool { + #[serde(default = "CommandLineTool::default_cwl_version")] pub cwl_version: String, + #[serde(default = "CommandLineTool::default_class")] pub class: String, #[serde(skip_serializing_if = "Option::is_none")] pub doc: Option, + #[serde(default)] pub id: String, #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, + #[serde(default)] pub inputs: Vec, + #[serde(default)] pub outputs: Vec, + #[serde(default)] pub requirements: Vec, } +impl CommandLineTool { + fn default_cwl_version() -> String { + SUPPORTED_CWL_VERSIONS[0].to_string() + } + + fn default_class() -> String { + "CommandLineTool".to_string() + } +} + /// Represents an input parameter for a `CommandLineTool`. /// See: https://www.commonwl.org/v1.2/CommandLineTool.html#CommandInputParameter #[skip_serializing_none] diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs index 10cab7a..f3aa28c 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/document.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/document.rs @@ -1,4 +1,6 @@ -use crate::schema::{command_line_tool::CommandLineTool, workflow::Workflow}; +use crate::schema::{ + command_line_tool::CommandLineTool, requirements::SUPPORTED_CWL_VERSIONS, workflow::Workflow, +}; use anyhow::{bail, ensure, Error, Result}; use serde::{Deserialize, Serialize}; use serde_yaml::{self, Value}; @@ -8,8 +10,6 @@ use std::{ str::FromStr, }; -const SUPPORTED_VERSIONS: &[&str] = &["v1.2"]; - /// Represents a CWL Schema which can be either a CommandLineTool or a Workflow #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] @@ -40,7 +40,7 @@ impl CwlSchema { .and_then(Value::as_str) .ok_or_else(|| anyhow::anyhow!("Failed to determine CWL specification version."))?; ensure!( - SUPPORTED_VERSIONS.contains(&version), + SUPPORTED_CWL_VERSIONS.contains(&version), "Unsupported CWL version: {version}" ); @@ -158,4 +158,40 @@ mod tests { serde_yaml::to_value(&written_values).unwrap() ); } + + #[test] + fn test_clt_to_yaml_write_error() { + use std::io::{Error, ErrorKind, Write}; + + struct FailingWriter; + impl Write for FailingWriter { + fn write(&mut self, _: &[u8]) -> std::io::Result { + Err(Error::new(ErrorKind::Other, "Simulated write error")) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } + } + + let schema = CwlSchema::CommandLineTool(CommandLineTool::default()); + assert!(schema.to_yaml(FailingWriter).is_err()); + } + + #[test] + fn test_wf_to_yaml_write_error() { + use std::io::{Error, ErrorKind, Write}; + + struct FailingWriter; + impl Write for FailingWriter { + fn write(&mut self, _: &[u8]) -> std::io::Result { + Err(Error::new(ErrorKind::Other, "Simulated write error")) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } + } + + let schema = CwlSchema::Workflow(Workflow::default()); + assert!(schema.to_yaml(FailingWriter).is_err()); + } } diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs index 0319651..13ee9ce 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/requirements.rs @@ -1,6 +1,8 @@ use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; +pub const SUPPORTED_CWL_VERSIONS: [&str; 1] = ["v1.2"]; + const CPU_NUM_DEFAULT: u32 = 1; const RAM_SIZE_IN_MB_DEFAULT: u32 = 1024; const TMPDIR_MIN_IN_MB_DEFAULT: u32 = 1024; diff --git a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs index 413305f..26929fa 100644 --- a/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs +++ b/zefiro-core/zefiro-cwl-parser/src/schema/workflow.rs @@ -1,5 +1,5 @@ use crate::schema::command_line_tool::CommandLineTool; -use crate::schema::requirements::WorkflowRequirement; +use crate::schema::requirements::{WorkflowRequirement, SUPPORTED_CWL_VERSIONS}; use crate::schema::types::{Any, CwlSchemaType, Documentation, Scatter, Source}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -7,12 +7,15 @@ use serde_with::skip_serializing_none; /// This defines the schema of the CWL Workflow Description document. /// See: https://www.commonwl.org/v1.2/Workflow.html #[skip_serializing_none] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Default)] #[serde(rename_all = "camelCase")] pub struct Workflow { - pub class: String, + #[serde(default = "Workflow::default_cwl_version")] pub cwl_version: String, + #[serde(default = "Workflow::default_class")] + pub class: String, pub doc: Option, + #[serde(default)] pub id: String, pub label: Option, pub inputs: Vec, @@ -21,6 +24,16 @@ pub struct Workflow { pub requirements: Vec, } +impl Workflow { + fn default_cwl_version() -> String { + SUPPORTED_CWL_VERSIONS[0].to_string() + } + + fn default_class() -> String { + "Workflow".to_string() + } +} + /// Represents an input parameter for a `Workflow`. /// See: https://www.commonwl.org/v1.2/Workflow.html#WorkflowInputParameter #[skip_serializing_none] From c86db9bad98e30701d6ade96cced9a5183c2e44d Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sun, 5 Jan 2025 18:40:10 +0400 Subject: [PATCH 20/21] Add README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e9fb782 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +Code: [![codecov](https://codecov.io/gh/zefiroproj/zefiro/graph/badge.svg?token=5DgmM1KzuQ)](https://codecov.io/gh/zefiroproj/zefiro) + +# Zefiro - fast, scalable and simple engine to manage workflows \ No newline at end of file From 1d41817811b5ebd2dbfd53835f908e4cd8963b44 Mon Sep 17 00:00:00 2001 From: Nikita Syzrantsev <47356892+nsyzrantsev@users.noreply.github.com> Date: Sun, 5 Jan 2025 18:40:46 +0400 Subject: [PATCH 21/21] Update main README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e9fb782..89efc7f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -Code: [![codecov](https://codecov.io/gh/zefiroproj/zefiro/graph/badge.svg?token=5DgmM1KzuQ)](https://codecov.io/gh/zefiroproj/zefiro) +**Code**: [![codecov](https://codecov.io/gh/zefiroproj/zefiro/graph/badge.svg?token=5DgmM1KzuQ)](https://codecov.io/gh/zefiroproj/zefiro) # Zefiro - fast, scalable and simple engine to manage workflows \ No newline at end of file