Skip to content

Commit 59f1675

Browse files
authored
Test & fix bug with internal update of metadata messing up versions (#1551)
1 parent 910616d commit 59f1675

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

cwltool/load_tool.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import re
77
import urllib
88
import uuid
9+
import copy
910
from typing import (
1011
Any,
1112
Dict,
@@ -391,6 +392,11 @@ def resolve_and_validate_document(
391392
if loadingContext.metadata:
392393
metadata = loadingContext.metadata
393394

395+
# Make a shallow copy. If we do a version update later, metadata
396+
# will be updated, we don't want to write through and change the
397+
# original object.
398+
metadata = copy.copy(metadata)
399+
394400
if not isinstance(metadata, CommentedMap):
395401
raise ValidationException(
396402
"metadata must be a CommentedMap, was %s" % type(metadata)

tests/test_load_tool.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
from pathlib import Path
22

33
import pytest
4+
import logging
45

56
from cwltool.context import LoadingContext, RuntimeContext
67
from cwltool.errors import WorkflowException
78
from cwltool.load_tool import load_tool
89
from cwltool.process import use_custom_schema, use_standard_schema
910
from cwltool.update import INTERNAL_VERSION
1011
from cwltool.utils import CWLObjectType
12+
from cwltool.loghandler import _logger, configure_logging
1113

1214
from .util import get_data
1315

16+
configure_logging(_logger.handlers[-1], False, True, True, True)
17+
_logger.setLevel(logging.DEBUG)
18+
1419

1520
def test_check_version() -> None:
1621
"""
@@ -96,5 +101,31 @@ def test_load_graph_fragment_from_packed() -> None:
96101
assert tool.tool["requirements"] == [
97102
{"class": "LoadListingRequirement", "loadListing": "no_listing"}
98103
]
104+
105+
# This tests an additional, related bug, in which the updater
106+
# updates only one fragment of the document, but would update
107+
# the metadata dict in-place. This had the effect of marking
108+
# the original document as updated. On a subsequent load, it
109+
# would get the original un-updated document, which mistakenly
110+
# had the version modified in place, and validate it with the
111+
# newer schema instead of the original one.
112+
#
113+
# The specific case where this failed was
114+
# cwltool:LoadListingRequirement which is only recognized for
115+
# v1.0 documents, newer documents are supposed to be
116+
# auto-updated to the spec LoadListingRequirement, so it is
117+
# dropped from the schema. However if we try to validate a
118+
# v1.0 document with a v1.2 schema, it will throw an error the
119+
# cwltool:LoadListingRequirement extension.
120+
#
121+
# This was solved by making a shallow copy of the metadata
122+
# dict to ensure that the updater did not modify the original
123+
# document.
124+
uri2 = (
125+
Path(get_data("tests/wf/packed-with-loadlisting.cwl")).as_uri()
126+
+ "#16169-step.cwl"
127+
)
128+
tool2 = load_tool(uri2, loadingContext)
129+
99130
finally:
100131
use_standard_schema("v1.0")

0 commit comments

Comments
 (0)