[python/sdk] - Correctly handle outputs with properties named "values" (#6264)

Co-authored-by: Justin Van Patten <jvp@justinvp.com>
This commit is contained in:
Komal 2021-02-05 17:16:13 -07:00 committed by GitHub
parent 3a3b96de72
commit f374b8a953
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 3 deletions

View file

@ -6,6 +6,9 @@ CHANGELOG
- [sdk/python] Gracefully handle monitor shutdown in the python runtime without exiting the process.
[#6249](https://github.com/pulumi/pulumi/pull/6249)
- [sdk/python] Fix a bug in `contains_unknowns` where outputs with a property named "values" failed with a TypeError.
[#6264](https://github.com/pulumi/pulumi/pull/6264)
## 2.20.0 (2021-02-03)
- [sdk/python] Fix `Output.from_input` to unwrap nested output values in input types (args classes), which addresses

View file

@ -33,7 +33,7 @@ from .. import _types
if TYPE_CHECKING:
from ..output import Inputs, Input, Output
from ..resource import Resource, CustomResource, ProviderResource
from ..resource import Resource, ProviderResource
from ..asset import FileAsset, RemoteAsset, StringAsset, FileArchive, RemoteArchive, AssetArchive
UNKNOWN = "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
@ -567,7 +567,7 @@ def contains_unknowns(val: Any) -> bool:
if not any([x is val for x in stack]):
stack.append(val)
if isinstance(val, dict):
return any([impl(x, stack) for x in val.values()])
return any([impl(val[k], stack) for k in val])
if isinstance(val, list):
return any([impl(x, stack) for x in val])
return False

View file

@ -36,18 +36,22 @@ class FakeCustomResource(CustomResource):
self.__dict__["urn"] = Output.from_input(urn)
self.__dict__["id"] = Output.from_input("id")
class FakeComponentResource(ComponentResource):
def __init__(self, urn):
self.__dict__["urn"] = Output.from_input(urn)
class MyCustomResource(CustomResource):
def __init__(self, name: str, typ: Optional[str] = None, opts: Optional[ResourceOptions] = None):
super(MyCustomResource, self).__init__(typ if typ is not None else "test:index:resource", name, None, opts)
class MyComponentResource(ComponentResource):
def __init__(self, name: str, typ: Optional[str] = None, opts: Optional[ResourceOptions] = None):
super(MyComponentResource, self).__init__(typ if typ is not None else "test:index:component", name, None, opts)
class MyResourceModule(ResourceModule):
def version(self):
return None
@ -60,6 +64,7 @@ class MyResourceModule(ResourceModule):
else:
raise Exception(f"unknown resource type {typ}")
class MyMocks(Mocks):
def call(self, token, args, provider):
raise Exception(f"unknown function {token}")
@ -72,8 +77,24 @@ class MyMocks(Mocks):
else:
raise Exception(f"unknown resource type {typ}")
@pulumi.output_type
class MyOutputTypeDict(dict):
def __init__(self, values: list):
pulumi.set(self, "values", values)
# Property with empty body.
@property
@pulumi.getter
def values(self) -> str:
"""Values docstring."""
...
def pulumi_test(coro):
wrapped = pulumi.runtime.test(coro)
def wrapper(*args, **kwargs):
settings.configure(settings.Settings())
rpc._RESOURCE_PACKAGES.clear()
@ -84,6 +105,7 @@ def pulumi_test(coro):
return wrapper
class NextSerializationTests(unittest.TestCase):
@pulumi_test
async def test_list(self):
@ -899,6 +921,12 @@ class NextSerializationTests(unittest.TestCase):
self.assertTrue(await r.is_secret())
self.assertEqual(await r.future(), "inner")
@pulumi_test
async def test_dangerous_prop_output(self):
out = self.create_output(MyOutputTypeDict(values=["foo", "bar"]), is_known=True)
self.assertTrue(await out.is_known())
@pulumi_test
async def test_apply_unknown_output(self):
out = self.create_output("foo", is_known=True)
@ -1167,4 +1195,3 @@ class EnumSerializationTests(unittest.TestCase):
one = FloatEnum.ZERO_POINT_ONE
prop = await rpc.serialize_property(one, [])
self.assertEqual(FloatEnum.ZERO_POINT_ONE, prop)