Skip to content

Commit

Permalink
Merge pull request #2876 from giordano/mg/convert-json
Browse files Browse the repository at this point in the history
[feat] Allow setting nested mapping types using the `-S` option
  • Loading branch information
vkarak committed Jul 3, 2023
2 parents 53ee447 + dbf0596 commit fb385e1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 13 deletions.
6 changes: 6 additions & 0 deletions docs/manpage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,9 @@ Options controlling ReFrame execution
- Sequence types: ``-S seqvar=1,2,3,4``
- Mapping types: ``-S mapvar=a:1,b:2,c:3``

Nested mapping types can also be converted using JSON syntax.
For example, the :attr:`~reframe.core.pipeline.RegressionTest.extra_resources` complex dictionary could be set with ``-S extra_resources='{"gpu": {"num_gpus_per_node":8}}'``.

Conversions to arbitrary objects are also supported.
See :class:`~reframe.utility.typecheck.ConvertibleType` for more details.

Expand Down Expand Up @@ -705,6 +708,9 @@ Options controlling ReFrame execution

Allow setting variables in fixtures.

.. versionchanged:: 4.4

Allow setting nested mapping types using JSON syntax.

.. option:: --skip-performance-check

Expand Down
31 changes: 18 additions & 13 deletions reframe/utility/typecheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@

import abc
import datetime
import json
import re


Expand Down Expand Up @@ -322,19 +323,23 @@ def __rfm_cast_str__(cls, s):
mappping_type = cls._type
key_type = cls._key_type
value_type = cls._value_type
seq = []
for key_datum in s.split(','):
try:
k, v = key_datum.split(':')
except ValueError:
# Re-raise as TypeError
raise TypeError(
f'cannot convert string {s!r} to {cls.__name__!r}'
) from None

seq.append((key_type(k), value_type(v)))

return mappping_type(seq)

try:
items = json.loads(s)
except json.JSONDecodeError:
items = []
for key_datum in s.split(','):
try:
k, v = key_datum.split(':')
except ValueError:
# Re-raise as TypeError
raise TypeError(
f'cannot convert string {s!r} to {cls.__name__!r}'
) from None

items.append((key_type(k), value_type(v)))

return mappping_type(items)


class _StrType(_SequenceType):
Expand Down
8 changes: 8 additions & 0 deletions unittests/test_typecheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ def test_mapping_type():
# Test conversions
assert typ.Dict[str, int]('a:1,b:2') == {'a': 1, 'b': 2}

# Conversion with JSON syntax, for nested dictionaries
s = '{"gpu":{"num_gpus_per_node": 8}, "mpi": {"num_slots": 64}}'
expected = {
'gpu': {'num_gpus_per_node': 8},
'mpi': {'num_slots': 64},
}
assert typ.Dict[str, typ.Dict[str, object]](s) == expected

with pytest.raises(TypeError):
typ.Dict[str, int]('a:1,b')

Expand Down

0 comments on commit fb385e1

Please sign in to comment.