[sdk/python] Cast numbers intended to be integers to int (#5419)

We recently made a change to the Python codegen to emit `int` type annotations, instead of `float`, for properties that are typed as `schema.IntType`.

But the number values that come back from protobuf structs are always floats (like JSON), so we need to cast the values intended to be integers to `int`.
This commit is contained in:
Justin Van Patten 2020-09-20 04:09:53 +00:00 committed by GitHub
parent a2a64e55d0
commit 5794a3f482
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View file

@ -9,6 +9,9 @@ CHANGELOG
- Add `pulumi console` command which opens the currently selected stack in the Pulumi console.
[#5368](https://github.com/pulumi/pulumi/pull/5368)
- Python SDK: Cast numbers intended to be integers to `int`.
[#5419](https://github.com/pulumi/pulumi/pull/5419)
## 2.10.1 (2020-09-16)
- feat(autoapi): add GetPermalink for operation result

View file

@ -391,15 +391,21 @@ def translate_output_properties(output: Any,
Recursively rewrite keys of objects returned by the engine to conform with a naming
convention specified by `output_transformer`.
Additionally, if output is a `dict` and `typ` is an output type, instantiate the output type,
passing the dict as an argument to the output type's __init__() method.
Additionally, perform any type conversions as necessary, based on the optional `typ` parameter.
If output is a `dict`, every key is translated using `translate_output_property` while every value is transformed
by recursing.
If output is a `list`, every value is recursively transformed.
If output is a primitive (i.e. not a dict or list), the value is returned without modification.
If output is a `dict` and `typ` is an output type, instantiate the output type,
passing the values in the dict to the output type's __init__() method.
If output is a `float` and `typ` is `int`, the value is cast to `int`.
Otherwise, if output is a primitive (i.e. not a dict or list), the value is returned without modification.
:param Optional[type] typ: The output's target type.
"""
# If it's a secret, unwrap the value so the output is in alignment with the expected type.
@ -466,6 +472,9 @@ def translate_output_properties(output: Any,
raise AssertionError(f"Unexpected type. Expected 'list' got '{typ}'")
return [translate_output_properties(v, output_transformer, element_type) for v in output]
if isinstance(output, float) and typ is int:
return int(output)
return output

View file

@ -874,3 +874,34 @@ class TranslateOutputPropertiesTests(unittest.TestCase):
self.assertEqual([["hello"]], result.value_list_list)
self.assertEqual([["hello"]], result.value_list_sequence)
self.assertEqual("hello", result.value_str)
def test_int(self):
@pulumi.output_type
class OutputTypeWithInt(dict):
value_dict: Dict[str, int]
value_mapping: Mapping[str, int]
value_list: List[int]
value_sequence: Sequence[int]
value_int: int
output = {
"value_dict": {"hello": 42.0},
"value_mapping": {"world": 100.0},
"value_list": [42.0],
"value_sequence": [100.0],
"value_int": 50.0,
}
result = rpc.translate_output_properties(output, translate_output_property, OutputTypeWithInt)
self.assertIsInstance(result, OutputTypeWithInt)
self.assertEqual({"hello": 42}, result.value_dict)
self.assertIsInstance(result.value_dict["hello"], int)
self.assertEqual({"world": 100}, result.value_mapping)
self.assertIsInstance(result.value_mapping["world"], int)
self.assertEqual([42], result.value_list)
self.assertIsInstance(result.value_list[0], int)
self.assertEqual([100], result.value_sequence)
self.assertIsInstance(result.value_sequence[0], int)
self.assertEqual(50, result.value_int)
self.assertIsInstance(result.value_int, int)