Skip to content

Commit

Permalink
Fix # char bug in cylc broadcast
Browse files Browse the repository at this point in the history
Everything after `#` in a setting was getting stripped out
  • Loading branch information
MetRonnie committed Jan 18, 2024
1 parent 522564c commit ea68bc8
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 26 deletions.
50 changes: 32 additions & 18 deletions cylc/flow/parsec/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import shlex
from collections import deque
from textwrap import dedent
from typing import List, Dict, Any, Tuple
from typing import List, Dict, Any, Tuple, Union

from metomi.isodatetime.data import Duration, TimePoint
from metomi.isodatetime.dumpers import TimePointDumper
Expand Down Expand Up @@ -373,7 +373,7 @@ def coerce_range(cls, value, keys):
return Range((int(min_), int(max_)))

@classmethod
def coerce_str(cls, value, keys):
def coerce_str(cls, value: Union[str, List[str]], keys: List[str]) -> str:
"""Coerce value to a string.
Examples:
Expand Down Expand Up @@ -512,16 +512,16 @@ def parse_int_range(cls, value):
return None

@classmethod
def strip_and_unquote(cls, keys, value):
def strip_and_unquote(cls, keys: List[str], value: str) -> str:
"""Remove leading and trailing spaces and unquote value.
Args:
keys (list):
keys:
Keys in nested dict that represents the raw configuration.
value (str):
value:
String value in raw configuration.
Return (str):
Return:
Processed value.
Examples:
Expand Down Expand Up @@ -1136,23 +1136,25 @@ def _coerce_type(cls, value):
return val


# BACK COMPAT: BroadcastConfigValidator
# The DB at 8.0.x stores Interval values as neither ISO8601 duration
# string or DurationFloat. This has been fixed at 8.1.0, and
# the following class acts as a bridge between fixed and broken.
# url:
# https://github.com/cylc/cylc-flow/pull/5138
# from:
# 8.0.x
# to:
# 8.1.x
# remove at:
# 8.x
class BroadcastConfigValidator(CylcConfigValidator):
"""Validate and Coerce DB loaded broadcast config to internal objects."""
def __init__(self):
CylcConfigValidator.__init__(self)

@classmethod
def coerce_str(cls, value: Union[str, List[str]], keys: List[str]) -> str:
"""Coerce value to a string.
Examples:
>>> BroadcastConfigValidator.coerce_str('abc#def', None)
'abc#def'
"""
# Prevent ParsecValidator from assuming '#' means comments;
# '#' has valid uses in shell script such as parameter substitution
if isinstance(value, str) and '#' in value:
value = f'"{value}"'
return ParsecValidator.coerce_str(value, keys)

@classmethod
def strip_and_unquote_list(cls, keys, value):
"""Remove leading and trailing spaces and unquote list value.
Expand All @@ -1177,6 +1179,18 @@ def strip_and_unquote_list(cls, keys, value):
value = value.lstrip('[').rstrip(']')
return ParsecValidator.strip_and_unquote_list(keys, value)

# BACK COMPAT: BroadcastConfigValidator.coerce_interval
# The DB at 8.0.x stores Interval values as neither ISO8601 duration
# string or DurationFloat. This has been fixed at 8.1.0, and
# the following class acts as a bridge between fixed and broken.
# url:
# https://github.com/cylc/cylc-flow/pull/5138
# from:
# 8.0.x
# to:
# 8.1.x
# remove at:
# 8.x
@classmethod
def coerce_interval(cls, value, keys):
"""Coerce an ISO 8601 interval into seconds.
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/broadcast/10-file-1/broadcast.cylc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
script="""
printenv CYLC_FOOBAR
# (This hash char should not cause the rest of the script to be stripped out)
if (($CYLC_TASK_TRY_NUMBER < 2 )); then
false
fi
Expand Down
20 changes: 12 additions & 8 deletions tests/unit/parsec/test_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,9 @@ def test_coerce_int_list():
validator.coerce_int_list(value, ['whatever'])


def test_coerce_str():
"""Test coerce_str."""
validator = ParsecValidator()
# The good
for value, result in [
@pytest.mark.parametrize(
'value, expected',
[
('', ''),
('Hello World!', 'Hello World!'),
('"Hello World!"', 'Hello World!'),
Expand All @@ -474,9 +472,15 @@ def test_coerce_str():
'Hello:\n foo\nGreet\n baz'),
('False', 'False'),
('None', 'None'),
(['a', 'b'], 'a\nb')
]:
assert validator.coerce_str(value, ['whatever']) == result
(['a', 'b'], 'a\nb'),
('abc#def', 'abc'),
]
)
def test_coerce_str(value: str, expected: str):
"""Test coerce_str."""
validator = ParsecValidator()
# The good
assert validator.coerce_str(value, ['whatever']) == expected


def test_coerce_str_list():
Expand Down

0 comments on commit ea68bc8

Please sign in to comment.