cd9fae599d
Python SDK changes to support strongly-typed input/output "dataclasses".
242 lines
8.4 KiB
Python
242 lines
8.4 KiB
Python
# Copyright 2016-2020, Pulumi Corporation.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import unittest
|
|
from typing import Optional
|
|
|
|
import pulumi
|
|
import pulumi._types as _types
|
|
|
|
|
|
CAMEL_TO_SNAKE_CASE_TABLE = {
|
|
"firstValue": "first_value",
|
|
"secondValue": "second_value",
|
|
}
|
|
|
|
@pulumi.output_type
|
|
class MyOutputType:
|
|
first_value: str = pulumi.property("firstValue")
|
|
second_value: Optional[float] = pulumi.property("secondValue", default=None)
|
|
|
|
@pulumi.output_type
|
|
class MyOutputTypeDict(dict):
|
|
first_value: str = pulumi.property("firstValue")
|
|
second_value: Optional[float] = pulumi.property("secondValue", default=None)
|
|
|
|
@pulumi.output_type
|
|
class MyOutputTypeTranslated:
|
|
first_value: str = pulumi.property("firstValue")
|
|
second_value: Optional[float] = pulumi.property("secondValue", default=None)
|
|
|
|
def _translate_property(self, prop):
|
|
return CAMEL_TO_SNAKE_CASE_TABLE.get(prop) or prop
|
|
|
|
@pulumi.output_type
|
|
class MyOutputTypeDictTranslated(dict):
|
|
first_value: str = pulumi.property("firstValue")
|
|
second_value: Optional[float] = pulumi.property("secondValue", default=None)
|
|
|
|
def _translate_property(self, prop):
|
|
return CAMEL_TO_SNAKE_CASE_TABLE.get(prop) or prop
|
|
|
|
|
|
@pulumi.output_type
|
|
class MyDeclaredPropertiesOutputType:
|
|
def __init__(self, first_value: str, second_value: Optional[float] = None):
|
|
pulumi.set(self, "first_value", first_value)
|
|
if second_value is not None:
|
|
pulumi.set(self, "second_value", second_value)
|
|
|
|
# Property with empty body.
|
|
@property
|
|
@pulumi.getter(name="firstValue")
|
|
def first_value(self) -> str:
|
|
"""First value docstring."""
|
|
...
|
|
|
|
# Property with implementation.
|
|
@property
|
|
@pulumi.getter(name="secondValue")
|
|
def second_value(self) -> Optional[float]:
|
|
"""Second value docstring."""
|
|
return pulumi.get(self, "second_value")
|
|
|
|
@pulumi.output_type
|
|
class MyDeclaredPropertiesOutputTypeDict(dict):
|
|
def __init__(self, first_value: str, second_value: Optional[float] = None):
|
|
pulumi.set(self, "first_value", first_value)
|
|
if second_value is not None:
|
|
pulumi.set(self, "second_value", second_value)
|
|
|
|
# Property with empty body.
|
|
@property
|
|
@pulumi.getter(name="firstValue")
|
|
def first_value(self) -> str:
|
|
"""First value docstring."""
|
|
...
|
|
|
|
# Property with implementation.
|
|
@property
|
|
@pulumi.getter(name="secondValue")
|
|
def second_value(self) -> Optional[float]:
|
|
"""Second value docstring."""
|
|
return pulumi.get(self, "second_value")
|
|
|
|
@pulumi.output_type
|
|
class MyDeclaredPropertiesOutputTypeTranslated:
|
|
def __init__(self, first_value: str, second_value: Optional[float] = None):
|
|
pulumi.set(self, "first_value", first_value)
|
|
if second_value is not None:
|
|
pulumi.set(self, "second_value", second_value)
|
|
|
|
# Property with empty body.
|
|
@property
|
|
@pulumi.getter(name="firstValue")
|
|
def first_value(self) -> str:
|
|
"""First value docstring."""
|
|
...
|
|
|
|
# Property with implementation.
|
|
@property
|
|
@pulumi.getter(name="secondValue")
|
|
def second_value(self) -> Optional[float]:
|
|
"""Second value docstring."""
|
|
return pulumi.get(self, "second_value")
|
|
|
|
def _translate_property(self, prop):
|
|
return CAMEL_TO_SNAKE_CASE_TABLE.get(prop) or prop
|
|
|
|
@pulumi.output_type
|
|
class MyDeclaredPropertiesOutputTypeDictTranslated(dict):
|
|
def __init__(self, first_value: str, second_value: Optional[float] = None):
|
|
pulumi.set(self, "first_value", first_value)
|
|
if second_value is not None:
|
|
pulumi.set(self, "second_value", second_value)
|
|
|
|
# Property with empty body.
|
|
@property
|
|
@pulumi.getter(name="firstValue")
|
|
def first_value(self) -> str:
|
|
"""First value docstring."""
|
|
...
|
|
|
|
# Property with implementation.
|
|
@property
|
|
@pulumi.getter(name="secondValue")
|
|
def second_value(self) -> Optional[float]:
|
|
"""Second value docstring."""
|
|
return pulumi.get(self, "second_value")
|
|
|
|
def _translate_property(self, prop):
|
|
return CAMEL_TO_SNAKE_CASE_TABLE.get(prop) or prop
|
|
|
|
|
|
class InputTypeTests(unittest.TestCase):
|
|
def test_decorator_raises(self):
|
|
with self.assertRaises(AssertionError) as cm:
|
|
@pulumi.output_type
|
|
@pulumi.input_type
|
|
class Foo:
|
|
pass
|
|
|
|
with self.assertRaises(AssertionError) as cm:
|
|
@pulumi.output_type
|
|
@pulumi.input_type
|
|
class Bar:
|
|
pass
|
|
|
|
def test_is_output_type(self):
|
|
types = [
|
|
MyOutputType,
|
|
MyOutputTypeDict,
|
|
MyOutputTypeTranslated,
|
|
MyOutputTypeDictTranslated,
|
|
MyDeclaredPropertiesOutputType,
|
|
MyDeclaredPropertiesOutputTypeDict,
|
|
MyDeclaredPropertiesOutputTypeTranslated,
|
|
MyDeclaredPropertiesOutputTypeDictTranslated,
|
|
]
|
|
for typ in types:
|
|
self.assertTrue(_types.is_output_type(typ))
|
|
self.assertEqual(True, typ._pulumi_output_type)
|
|
self.assertTrue(hasattr(typ, "__init__"))
|
|
|
|
def test_output_type_types(self):
|
|
self.assertEqual({
|
|
"firstValue": str,
|
|
"secondValue": float,
|
|
}, _types.output_type_types(MyOutputType))
|
|
|
|
def test_output_type(self):
|
|
types = [
|
|
(MyOutputType, False),
|
|
(MyOutputTypeDict, False),
|
|
(MyOutputTypeTranslated, False),
|
|
(MyOutputTypeDictTranslated, False),
|
|
(MyDeclaredPropertiesOutputType, True),
|
|
(MyDeclaredPropertiesOutputTypeDict, True),
|
|
(MyDeclaredPropertiesOutputTypeTranslated, True),
|
|
(MyDeclaredPropertiesOutputTypeDictTranslated, True),
|
|
]
|
|
for typ, has_doc in types:
|
|
self.assertTrue(hasattr(typ, "__init__"))
|
|
t = _types.output_type_from_dict(typ, {"firstValue": "hello", "secondValue": 42})
|
|
self.assertEqual("hello", t.first_value)
|
|
self.assertEqual(42, t.second_value)
|
|
|
|
if isinstance(t, dict):
|
|
self.assertEqual("hello", t["first_value"])
|
|
self.assertEqual(42, t["second_value"])
|
|
|
|
first = typ.first_value
|
|
self.assertIsInstance(first, property)
|
|
self.assertTrue(callable(first.fget))
|
|
self.assertEqual("first_value", first.fget.__name__)
|
|
self.assertEqual({"return": str}, first.fget.__annotations__)
|
|
if has_doc:
|
|
self.assertEqual("First value docstring.", first.fget.__doc__)
|
|
self.assertEqual("firstValue", first.fget._pulumi_name)
|
|
|
|
second = typ.second_value
|
|
self.assertIsInstance(second, property)
|
|
self.assertTrue(callable(second.fget))
|
|
self.assertEqual("second_value", second.fget.__name__)
|
|
self.assertEqual({"return": Optional[float]}, second.fget.__annotations__)
|
|
if has_doc:
|
|
self.assertEqual("Second value docstring.", second.fget.__doc__)
|
|
self.assertEqual("secondValue", second.fget._pulumi_name)
|
|
|
|
self.assertTrue(hasattr(t, "__eq__"))
|
|
self.assertTrue(t.__eq__(t))
|
|
self.assertTrue(t == t)
|
|
self.assertFalse(t != t)
|
|
self.assertFalse(t == "not equal")
|
|
|
|
t2 = _types.output_type_from_dict(typ, {"firstValue": "hello", "secondValue": 42})
|
|
self.assertTrue(t.__eq__(t2))
|
|
self.assertTrue(t == t2)
|
|
self.assertFalse(t != t2)
|
|
|
|
if isinstance(t2, dict):
|
|
self.assertEqual("hello", t2["first_value"])
|
|
self.assertEqual(42, t2["second_value"])
|
|
|
|
t3 = _types.output_type_from_dict(typ, {"firstValue": "foo", "secondValue": 1})
|
|
self.assertFalse(t.__eq__(t3))
|
|
self.assertFalse(t == t3)
|
|
self.assertTrue(t != t3)
|
|
|
|
if isinstance(t3, dict):
|
|
self.assertEqual("foo", t3["first_value"])
|
|
self.assertEqual(1, t3["second_value"])
|