diff --git a/CHANGELOG.md b/CHANGELOG.md index a674a8e..89a8b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,17 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -### Changed - -### Deprecated - -### Removed +## [0.22.2] - 2026-10-01 ### Fixed -### Security +- `default` value for _string format_ is a `string` and not an `object`. ## [0.22.1] - 2026-09-27 @@ -138,7 +132,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed the STAC Item public schema URL. - Fixed a Python `cgi` import issue, pdoc installation, import organization, f-string syntax, documentation links, and CI/package workflow issues. -[unreleased]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.22.0...HEAD +[Unreleased]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.22.2...HEAD +[0.22.2]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.22.1...v0.22.2 +[0.22.1]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.22.0...v0.22.1 [0.22.0]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.21.0...v0.22.0 [0.21.0]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.20.0...v0.21.0 [0.20.0]: https://github.com/transpiler-mate/cwl2ogc/compare/v0.19.0...v0.20.0 diff --git a/src/cwl2ogc/__about__.py b/src/cwl2ogc/__about__.py index f34cac3..137b3cf 100644 --- a/src/cwl2ogc/__about__.py +++ b/src/cwl2ogc/__about__.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.22.1" +__version__ = "0.22.2" diff --git a/src/cwl2ogc/__init__.py b/src/cwl2ogc/__init__.py index 6e9fe66..36c1b77 100644 --- a/src/cwl2ogc/__init__.py +++ b/src/cwl2ogc/__init__.py @@ -305,7 +305,15 @@ def _on_input(self, input: Any) -> Mapping[str, Any]: schema = dict(self._convert_input_type(input)) default_value = getattr(input, "default", None) if default_value: - schema["default"] = default_value + if ( + "format" in schema + and schema["format"] in __STRING_FORMATS__.values() + and isinstance(default_value, dict) + and "value" in default_value + ): + schema["default"] = default_value["value"] + else: + schema["default"] = default_value return schema def _convert_input_type(self, parameter: object) -> Mapping[str, Any]: diff --git a/tests/test_conversion.py b/tests/test_conversion.py index bb3643c..a8f5ec2 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -17,7 +17,7 @@ from pathlib import Path import pytest -from cwl_utils.parser import Process, load_document_by_yaml +from cwl_utils.parser import LoadingOptions, Process, load_document_by_yaml from cwl_utils.parser.cwl_v1_2 import SchemaDefRequirement, Workflow, WorkflowInputParameter from ruamel.yaml import YAML @@ -157,3 +157,100 @@ def test_custom_type_without_requirements_does_not_crash( assert "aoi" in schema["properties"] assert schema["$defs"]["aoi"] == {} + + +@pytest.mark.parametrize( + ("type_name", "expected_format"), + [ + ("Date", "date"), + ("DateTime", "date-time"), + ("Duration", "duration"), + ("Email", "email"), + ("Hostname", "hostname"), + ("IDNEmail", "idn-email"), + ("IDNHostname", "idn-hostname"), + ("IPv4", "ipv4"), + ("IPv6", "ipv6"), + ("IRI", "iri"), + ("IRIReference", "iri-reference"), + ("JsonPointer", "json-pointer"), + ("Password", "password"), + ("RelativeJsonPointer", "relative-json-pointer"), + ("UUID", "uuid"), + ("URI", "uri"), + ("URIReference", "uri-reference"), + ("URITemplate", "uri-template"), + ("Time", "time"), + ], +) +@pytest.mark.parametrize("default_value", ["default-value", ""]) +def test_string_format_record_default_is_unwrapped( + type_name: str, expected_format: str, default_value: str +) -> None: + type_uri = f"https://raw.githubusercontent.com/eoap/schemas/main/string_format.yaml#{type_name}" + # Inline the referenced record definition to keep parsing independent of network access. + document = load_document_by_yaml( + yaml={ + "cwlVersion": "v1.2", + "class": "Workflow", + "id": "file:///tmp/string-format-default.cwl#main", + "requirements": { + "SchemaDefRequirement": { + "types": [ + { + "name": type_uri, + "type": "record", + "fields": [{"name": "value", "type": "string"}], + } + ] + } + }, + "inputs": {"formatted": {"type": type_uri, "default": {"value": default_value}}}, + "outputs": [], + "steps": [], + }, + uri="file:///tmp/string-format-default.cwl", + loadingOptions=LoadingOptions(no_link_check=True), + ) + assert isinstance(document, Process) + converter = BaseCWLtypes2OGCConverter(document) + expected_schema = {"type": "string", "format": expected_format, "default": default_value} + + assert converter.get_inputs()["formatted"]["schema"] == expected_schema + assert converter.get_inputs_json_schema()["$defs"]["formatted"] == expected_schema + assert document.inputs[0].default == {"value": default_value} + + +def test_ordinary_record_default_remains_an_object() -> None: + document = load_document_by_yaml( + yaml={ + "cwlVersion": "v1.2", + "class": "Workflow", + "id": "file:///tmp/ordinary-record-default.cwl#main", + "inputs": { + "record": { + "type": { + "type": "record", + "name": "OrdinaryRecord", + "fields": [{"name": "value", "type": "string"}], + }, + "default": {"value": "default-value"}, + } + }, + "outputs": [], + "steps": [], + }, + uri="file:///tmp/ordinary-record-default.cwl", + loadingOptions=LoadingOptions(no_link_check=True), + ) + assert isinstance(document, Process) + converter = BaseCWLtypes2OGCConverter(document) + expected_schema = { + "type": "object", + "properties": {"value": {"type": "string"}}, + "required": ["value"], + "default": {"value": "default-value"}, + } + + assert converter.get_inputs()["record"]["schema"] == expected_schema + assert converter.get_inputs_json_schema()["$defs"]["record"] == expected_schema