diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e4d10db..04d093f02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ CHANGELOG ========= ## HEAD (Unreleased) -_(none) + +- Python SDK: Avoid raising an error when an output has a type annotation of Any + and the value is a list or dict. + [#5238](https://github.com/pulumi/pulumi/pull/5238) ## 2.9.0 (2020-08-19) diff --git a/sdk/python/lib/pulumi/runtime/rpc.py b/sdk/python/lib/pulumi/runtime/rpc.py index 1e4b71e8e..033fb9ed3 100644 --- a/sdk/python/lib/pulumi/runtime/rpc.py +++ b/sdk/python/lib/pulumi/runtime/rpc.py @@ -399,6 +399,11 @@ def translate_output_properties(output: Any, # Unwrap optional types. typ = _types.unwrap_optional_type(typ) if typ else typ + # If the typ is Any, set it to None to treat it as if we don't have any type information, + # to avoid raising errors about unexpected types, since it could be any type. + if typ is Any: + typ = None + if isinstance(output, dict): # Function called to lookup a type for a given key. # The default always returns None. diff --git a/sdk/python/lib/test/test_translate_output_properties.py b/sdk/python/lib/test/test_translate_output_properties.py index 8d525ba98..2a7c1a6e0 100644 --- a/sdk/python/lib/test/test_translate_output_properties.py +++ b/sdk/python/lib/test/test_translate_output_properties.py @@ -13,7 +13,7 @@ # limitations under the License. import unittest -from typing import Dict, List, Optional +from typing import Any, Dict, List, Mapping, Optional from pulumi.runtime import rpc import pulumi @@ -326,6 +326,15 @@ class InvalidTypeDeclaredOptionalListOptionalStr(dict): ... +@pulumi.output_type +class OutputTypeWithAny(dict): + value_dict: Any + value_list: Any + value_dict_dict: Mapping[str, Any] + value_list_list: List[Any] + value_str: Any + + class TranslateOutputPropertiesTests(unittest.TestCase): def test_translate(self): output = { @@ -550,3 +559,19 @@ class TranslateOutputPropertiesTests(unittest.TestCase): for output in outputs: with self.assertRaises(AssertionError): rpc.translate_output_properties(output, translate_output_property, typ) + + def test_any(self): + output = { + "value_dict": {"hello": "world"}, + "value_list": ["hello"], + "value_dict_dict": {"value": {"hello": "world"}}, + "value_list_list": [["hello"]], + "value_str": "hello", + } + result = rpc.translate_output_properties(output, translate_output_property, OutputTypeWithAny) + self.assertIsInstance(result, OutputTypeWithAny) + self.assertEqual({"hello": "world"}, result.value_dict) + self.assertEqual(["hello"], result.value_list) + self.assertEqual({"value": {"hello": "world"}}, result.value_dict_dict) + self.assertEqual([["hello"]], result.value_list_list) + self.assertEqual("hello", result.value_str)