Skip to content

Commit

Permalink
[feat] Parse convertible mapping objects with json module
Browse files Browse the repository at this point in the history
The advantage is that we can automatically convert nested mappings, like for
example the `extra_resources` attribute, which can thus be set from the command
line.
  • Loading branch information
giordano committed Jun 19, 2023
1 parent eaad7e1 commit 95a9cfd
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 14 deletions.
33 changes: 20 additions & 13 deletions reframe/utility/typecheck.py
Expand Up @@ -95,6 +95,7 @@

import abc
import datetime
import json
import re


Expand Down Expand Up @@ -322,19 +323,25 @@ 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:
d = json.loads(s)
except json.JSONDecodeError:
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)
else:
return mappping_type(d)


class _StrType(_SequenceType):
Expand Down
9 changes: 8 additions & 1 deletion unittests/test_typecheck.py
Expand Up @@ -7,7 +7,6 @@

import reframe.utility.typecheck as typ


def assert_type_hierarchy(builtin_type, ctype):
assert isinstance(ctype, type)
assert issubclass(builtin_type, ctype)
Expand Down Expand Up @@ -208,6 +207,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}}'
assert (typ.Dict[str, typ.Dict[str, object]](s) ==
{
"gpu": {"num_gpus_per_node": 8},
"mpi": {"num_slots": 64},
})

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

Expand Down

0 comments on commit 95a9cfd

Please sign in to comment.