From 7d0d819558aace9e5e19970db9f17ce530251618 Mon Sep 17 00:00:00 2001 From: talyz Date: Wed, 15 Nov 2023 18:07:23 +0100 Subject: [PATCH] ImmutableValidatedObject: Support nested Mapping types --- nixops/util.py | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/nixops/util.py b/nixops/util.py index e5f6ef966..83c6201b0 100644 --- a/nixops/util.py +++ b/nixops/util.py @@ -17,8 +17,9 @@ import re import typing import typeguard # type: ignore -import inspect import shlex +import collections.abc +from inspect import isclass from typing import ( Callable, List, @@ -149,21 +150,33 @@ def _transform_value(key: Any, value: Any) -> Any: if not ann: return value - if inspect.isclass(ann) and issubclass(ann, ImmutableValidatedObject): + if isclass(ann) and issubclass(ann, ImmutableValidatedObject): value = ann(**value) - # Support Sequence[ImmutableValidatedObject] - if isinstance(value, tuple) and not isinstance(ann, str): - new_value = [] - for v in value: - for subann in ann.__args__: # type: ignore - if inspect.isclass(subann) and issubclass( - subann, ImmutableValidatedObject - ): - new_value.append(subann(**v)) - else: - new_value.append(v) - value = tuple(new_value) + # Support containers of ImmutableValidatedObjects + match typing.get_origin(ann): + + case collections.abc.Sequence: + new_value: Any = [] + for v in value: + for subann in typing.get_args(ann): + if isclass(subann) and issubclass( + subann, ImmutableValidatedObject + ): + new_value.append(subann(**v)) + else: + new_value.append(v) + value = tuple(new_value) + + case collections.abc.Mapping: + _, value_ann = typing.get_args(ann) + if isclass(value_ann) and issubclass( + value_ann, ImmutableValidatedObject + ): + new_value = {} + for k, v in value.items(): + new_value[k] = value_ann(**v) + value = new_value typeguard.check_type(value, ann)