Skip to content

Commit 6de37a3

Browse files
committed
AWS: Fix bug on PromotionalResources model
This commit fixes a bug in the `PromotionalResources` which did expected the attribute `promotional_media` to be an optional string, while it should be an optional list of resources. It also introduces the class `PromotionalMedia` to map the missing resource type. Refers to SPSTRAT-671 Signed-off-by: Jonathan Gangi <[email protected]>
1 parent 1e601c0 commit 6de37a3

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

cloudpub/models/aws.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,12 +638,26 @@ class PromoResourcesVideo(BaseResources):
638638
"""The promotional video title."""
639639

640640

641+
@define
642+
class PromotionalMedia(BaseResources):
643+
"""Represent a single element of promotional media from class :class:`~cloudpub.models.aws.PromotionalResources`.""" # noqa: E501
644+
645+
title: str = field(validator=instance_of(str), metadata={"alias": "Title"})
646+
"""The title of the promotional media resource."""
647+
648+
description: Optional[str] = field(
649+
validator=optional(instance_of(str)), metadata={"alias": "Description"}
650+
)
651+
"""The description of the promotional media resource."""
652+
653+
641654
@define
642655
class PromotionalResources(AttrsJSONDecodeMixin):
643656
"""Represent the "PromotionalResources" section of the :class:`~cloudpub.models.aws.ProductDetailResponse`.""" # noqa: E501
644657

645-
promotional_media: Optional[str] = field(
646-
validator=optional(instance_of(str)),
658+
promotional_media: Optional[List[PromotionalMedia]] = field(
659+
converter=lambda x: [PromotionalMedia.from_json(a) for a in x] if x else None,
660+
on_setattr=NO_OP,
647661
metadata={"alias": "PromotionalMedia", "hide_unset": True},
648662
)
649663
"""The product's promotional media."""

docs/cloud_providers/models/aws.rst.incl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ Resources internal elements
122122
.. autoclass:: cloudpub.models.aws.PromoResourcesVideo()
123123
:members:
124124

125+
.. autoclass:: cloudpub.models.aws.PromotionalMedia()
126+
:members:
127+
125128
.. autoclass:: cloudpub.models.aws.PositiveTargeting()
126129
:members:
127130

tests/aws/test_models.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import re
3+
from copy import deepcopy
34
from typing import Any, Dict
45

56
import pytest
@@ -16,6 +17,8 @@
1617
ProductVersionsBase,
1718
ProductVersionsCloudFormationSource,
1819
ProductVersionsVirtualizationSource,
20+
PromotionalMedia,
21+
PromotionalResources,
1922
SecurityGroup,
2023
Version,
2124
VersionMapping,
@@ -125,3 +128,64 @@ def test_describe_entity_response_parsed_details(
125128
def test_list_changeset_response_parsed(list_changeset_response: Dict[str, Any]) -> None:
126129
resp = ListChangeSetsResponse.from_json(list_changeset_response)
127130
assert len(resp.change_set_list) == 1
131+
132+
133+
@pytest.mark.parametrize(
134+
"promotional_media",
135+
[
136+
None,
137+
[],
138+
[
139+
{
140+
'Type': 'Image',
141+
'Url': 'https://foo.com/bar.png',
142+
'Title': 'Logo1',
143+
'Description': None,
144+
}
145+
],
146+
[
147+
{
148+
'Type': 'Image',
149+
'Url': 'https://foo.com/bar.png',
150+
'Title': 'Logo1',
151+
# Description field intentionally omitted to test absence
152+
}
153+
],
154+
[
155+
{
156+
'Type': 'Image',
157+
'Url': 'https://foo.com/bar.png',
158+
'Title': 'Logo1',
159+
'Description': 'This is the logo1',
160+
},
161+
{
162+
'Type': 'Video',
163+
'Url': 'https://foo.com/video.mp4',
164+
'Title': 'Video',
165+
'Description': 'This is the promotional video',
166+
},
167+
],
168+
],
169+
)
170+
def test_promotional_resources_promotional_media(
171+
promotional_media, promotional_resource: Dict[str, Any]
172+
) -> None:
173+
resource = deepcopy(promotional_resource)
174+
resource["PromotionalMedia"] = promotional_media
175+
176+
obj = PromotionalResources.from_json(resource)
177+
178+
assert obj
179+
if not promotional_media:
180+
assert obj.promotional_media is None
181+
else:
182+
assert obj.promotional_media == [PromotionalMedia.from_json(x) for x in promotional_media]
183+
184+
185+
def test_promotional_resources_promotional_media_absent(promotional_resource: Dict[str, Any]):
186+
resource = deepcopy(promotional_resource)
187+
del resource["PromotionalMedia"]
188+
189+
obj = PromotionalResources.from_json(resource)
190+
assert obj
191+
assert obj.promotional_media is None

0 commit comments

Comments
 (0)