diff --git a/src/webexpythonsdk/models/cards/__init__.py b/src/webexpythonsdk/models/cards/__init__.py index afdc0fc..3136650 100644 --- a/src/webexpythonsdk/models/cards/__init__.py +++ b/src/webexpythonsdk/models/cards/__init__.py @@ -1,4 +1,4 @@ -"""Webex Adaptive Cards data models. +"""Webex Adaptive Card - Init File. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -21,30 +21,64 @@ SOFTWARE. """ -from .adaptive_card_component import AdaptiveCardComponent -from .card import AdaptiveCard -from .components import ( - Choice, - Column, - Fact, +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent +) +from webexpythonsdk.models.cards.cards import ( + AdaptiveCard +) +from webexpythonsdk.models.cards.card_elements import ( + TextBlock, Image, Media, MediaSource, - TextBlock, + RichTextBlock, + TextRun, ) -from .container import ColumnSet, Container, FactSet, ImageSet -from .inputs import Choices, Date, Number, Text, Time, Toggle -from .options import ( - BlockElementHeight, - ChoiceInputStyle, - Colors, - ContainerStyle, +from webexpythonsdk.models.cards.containers import ( + ActionSet, + Container, + ColumnSet, + Column, + FactSet, + Fact, + ImageSet, +) +from webexpythonsdk.models.cards.actions import ( + OpenUrl, + Submit, + ShowCard, + ToggleVisibility, + TargetElement, +) +from webexpythonsdk.models.cards.inputs import ( + Text, + Number, + Date, + Time, + Toggle, + ChoiceSet, + Choice, +) +from webexpythonsdk.models.cards.types import ( + BackgroundImage, +) +from webexpythonsdk.models.cards.options import ( + AbstractOption, FontSize, + FontType, FontWeight, + Colors, + BlockElementHeight, + VerticalContentAlignment, HorizontalAlignment, + Spacing, ImageSize, ImageStyle, - Spacing, + ContainerStyle, TextInputStyle, - VerticalContentAlignment, + ChoiceInputStyle, + ActionStyle, + AssociatedInputs, + ImageFillMode, ) diff --git a/src/webexpythonsdk/models/cards/actions.py b/src/webexpythonsdk/models/cards/actions.py index 33d0936..9f1462c 100644 --- a/src/webexpythonsdk/models/cards/actions.py +++ b/src/webexpythonsdk/models/cards/actions.py @@ -1,4 +1,4 @@ -"""Webex Adaptive Card actions. +"""Webex Adaptive Card - Actions Model. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -21,52 +21,653 @@ SOFTWARE. """ -from .adaptive_card_component import AdaptiveCardComponent +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.cards as CARDS +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + check_type, + validate_input, + validate_dict_str, + validate_uri, +) class OpenUrl(AdaptiveCardComponent): - """Open URL Action.""" + """ + **Adaptive Card - Action.OpenUrl Element** + + When invoked, show the given url either by launching it in an external web + browser or showing within an embedded web browser. + """ type = "Action.OpenUrl" - def __init__(self, url, title=None, iconURL=None): + def __init__( + self, + url: object, + title: str = None, + iconUrl: object = None, + id: str = None, + style: OPTIONS.ActionStyle = None, + fallback: object = None, + requires: dict[str, str] = None, + ): + """ + Initialize a new Action.OpenUrl element. + + Args: + url (uri, Mandatory): The URL to open. Allowed value(s): + uri + title (str, Optional): Label for button or link that represents + this action. **_Defaults to None._** + iconUrl (uri, Optional): Optional icon to be shown on the action + in conjunction with the title. Supports data URI. **_Defaults + to None._** Allowed value(s): + uri + id (str, Optional): A unique identifier associated with this + Action. **_Defaults to None._** + style (ActionStyle, Optional): Controls the style of an Action, + which influences how the action is displayed, spoken, etc. + **_Defaults to None._** Allowed + value(s): + ActionStyle.DEFAULT, ActionStyle.POSITIVE, or + ActionStyle.DESTRUCTIVE + fallback (Action Element or str, Optional): Describes what to do + when an unknown element is encountered or the requires of this + or any children can't be met. **_Defaults to None._** Allowed + value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + validate_uri( + url, + ) + + check_type( + title, + str, + optional=True, + ) + + validate_uri( + iconUrl, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + validate_input( + style, + OPTIONS.ActionStyle, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + OpenUrl, + ShowCard, + Submit, + ToggleVisibility, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.url = url self.title = title - self.iconURL = iconURL + self.iconUrl = iconUrl + self.id = id + self.style = style + self.fallback = fallback + self.requires = requires super().__init__( - serializable_properties=[], - simple_properties=["url", "type", "title", "iconURL"], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "url", + "title", + "iconUrl", + "id", + "style", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "requires", + ], ) class Submit(AdaptiveCardComponent): - """Submit Action.""" + """ + **Adaptive Card - Action.Submit Element** + + Gathers input fields, merges with optional data field, and sends an event + to the client. It is up to the client to determine how this data is + processed. For example: With BotFramework bots, the client would send an + activity through the messaging medium to the bot. The inputs that are + gathered are those on the current card, and in the case of a show card + those on any parent cards. See + https://docs.microsoft.com/en-us/adaptive-cards/authoring-cards/input-validation + for more details. + """ type = "Action.Submit" - def __init__(self, data=None, title=None, iconURL=None): + def __init__( + self, + data: object = None, + associatedInputs: OPTIONS.AssociatedInputs = OPTIONS.AssociatedInputs.AUTO, + title: str = None, + iconUrl: object = None, + id: str = None, + style: OPTIONS.ActionStyle = None, + fallback: object = None, + requires: dict[str, str] = None, + ): + """ + Initialize a new Action.Submit element. + + Args: + data (str or object, Optional): Initial data that input fields + will be combined with. These are essentially "hidden" + properties. **_Defaults to None._** Allowed value(s): + str or object + associatedInputs (AssociatedInputs, Optional): Controls which + inputs are associated with the submit action. **_Defaults to + AssociatedInputs.AUTO_.** Allowed value(s): + AssociatedInputs.AUTO or AssociatedInputs.NONE + title (str, Optional): Label for button or link that represents + this action. **_Defaults to None._** + iconUrl (uri, Optional): Optional icon to be shown on the action + in conjunction with the title. Supports data URI. **_Defaults + to None._** Allowed value(s): + uri + id (str, Optional): A unique identifier associated with this + Action. **_Defaults to None._** + style (ActionStyle, Optional): Controls the style of an Action, + which influences how the action is displayed, spoken, etc. + **_Defaults to None._** Allowed value(s): + ActionStyle.DEFAULT, ActionStyle.POSITIVE, or + ActionStyle.DESTRUCTIVE + fallback (Action Element or str, Optional): Describes what to do + when an unknown element is encountered or the requires of this + or any children can't be met. **_Defaults to None._** Allowed + value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + data, + ( + str, + object, + ), + optional=True + ) + + validate_input( + associatedInputs, + OPTIONS.AssociatedInputs, + optional=True, + ) + + check_type( + title, + str, + optional=True, + ) + + validate_uri( + iconUrl, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + validate_input( + style, + OPTIONS.ActionStyle, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + OpenUrl, + ShowCard, + Submit, + ToggleVisibility, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.data = data + self.associatedInputs = associatedInputs self.title = title - self.iconURL = iconURL + self.iconUrl = iconUrl + self.id = id + self.style = style + self.fallback = fallback + self.requires = requires super().__init__( - serializable_properties=[], - simple_properties=["data", "title", "iconURL", "type"], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "data", + "associatedInputs", + "title", + "iconUrl", + "id", + "style", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "requires", + ], ) class ShowCard(AdaptiveCardComponent): - """Show Card Action.""" + """ + **Adaptive Card - Action.ShowCard Element** + + Defines an AdaptiveCard which is shown to the user when the button or link + is clicked. + """ type = "Action.ShowCard" - def __init__(self, card=None, title=None, iconURL=None): + def __init__( + self, + card: object = None, + title: str = None, + iconUrl: object = None, + id: str = None, + style: OPTIONS.ActionStyle = None, + fallback: object = None, + requires: dict[str, str] = None, + ): + """ + Initialize a new Action.ShowCard element. + + Args: + card (AdaptiveCard, Optional): The Adaptive Card to show. Inputs + in ShowCards will not be submitted if the submit button is + located on a parent card. See + https://docs.microsoft.com/en-us/adaptive-cards/authoring-cards/input-validation + for more details. **_Defaults to None._** Allowed value(s): + AdaptiveCard + title (str, Optional): Label for button or link that represents + this action. **_Defaults to None._** + iconUrl (uri, Optional): Optional icon to be shown on the action + in conjunction with the title. Supports data URI. **_Defaults + to None._** Allowed value(s): + uri + id (str, Optional): A unique identifier associated with this + Action. **_Defaults to None._** + style (ActionStyle, Optional): Controls the style of an Action, + which influences how the action is displayed, spoken, etc. + **_Defaults to None._** Allowed + value(s): + ActionStyle.DEFAULT, ActionStyle.POSITIVE, or + ActionStyle.DESTRUCTIVE + fallback (Action Element or str, Optional): Describes what to do + when an unknown element is encountered or the requires of this + or any children can't be met. **_Defaults to None._** Allowed + value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + card, + CARDS.AdaptiveCard, + optional=True, + ) + + check_type( + title, + str, + optional=True, + ) + + validate_uri( + iconUrl, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + validate_input( + style, + OPTIONS.ActionStyle, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + OpenUrl, + ShowCard, + Submit, + ToggleVisibility, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.card = card self.title = title - self.iconURL = iconURL + self.iconUrl = iconUrl + self.id = id + self.style = style + self.fallback = fallback + self.requires = requires + + super().__init__( + serializable_properties=[ + "card", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "title", + "iconUrl", + "id", + "style", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "requires", + ], + ) + + +class ToggleVisibility(AdaptiveCardComponent): + """ + **Adaptive Card - Action.ToggleVisibility Element** + + An action that toggles the visibility of associated card elements. + """ + + type = "Action.ToggleVisibility" + + def __init__( + self, + targetElements: list[object], + title: str = None, + iconUrl: object = None, + id: str = None, + style: OPTIONS.ActionStyle = None, + fallback: object = None, + requires: dict[str, str] = None, + ): + """ + Initialize a new Action.ToggleVisibility element. + + Args: + targetElements (list of TargetElement(s) or str, Mandatory): The + array of TargetElements. It is not recommended to include + Input elements with validation under Action.Toggle due to + confusion that can arise from invalid inputs that are not + currently visible. See + https://docs.microsoft.com/en-us/adaptive-cards/authoring-cards/input-validation + for more information. Allowed value(s): + TargetElement or str + title (str, Optional): Label for button or link that represents + this action. **_Defaults to None._** + iconUrl (uri, Optional): Optional icon to be shown on the action + in conjunction with the title. Supports data URI. **_Defaults + to None._** Allowed value(s): + uri + id (str, Optional): A unique identifier associated with this + Action. **_Defaults to None._** + style (ActionStyle, Optional): Controls the style of an Action, + which influences how the action is displayed, spoken, etc. + **_Defaults to None._** Allowed value(s): + ActionStyle.DEFAULT, ActionStyle.POSITIVE, or + ActionStyle.DESTRUCTIVE + fallback (Action Element or str, Optional): Describes what to do + when an unknown element is encountered or the requires of this + or any children can't be met. **_Defaults to None._** Allowed + value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + targetElements, + ( + TargetElement, + str, + ), + is_list=True, + ) + + check_type( + title, + str, + optional=True, + ) + + validate_uri( + iconUrl, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + validate_input( + style, + OPTIONS.ActionStyle, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + OpenUrl, + ShowCard, + Submit, + ToggleVisibility, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.targetElements = targetElements + self.title = title + self.iconUrl = iconUrl + self.id = id + self.style = style + self.fallback = fallback + self.requires = requires super().__init__( - serializable_properties=["card"], - simple_properties=["title", "type", "iconURL"], + serializable_properties=[ + "targetElements", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "title", + "iconUrl", + "id", + "style", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "requires", + ], + ) + + +class TargetElement(AdaptiveCardComponent): + """ + **Adaptive Card - TargetElement Element** + + Represents an entry for Action.ToggleVisibility's targetElements property. + """ + + def __init__( + self, + elementId: str, + isVisible: bool = None, + ): + """ + Initialize a new TargetElement element for the + Action.ToggleVisibility element's targetElements argument. + + Args: + elementId (str, Mandatory): Element ID of element to toggle. + isVisible (uri, Optional): If true, always show target element. If + false, always hide target element. If not supplied, toggle + target element's visibility. **_Defaults to None._** + """ + # Check types + check_type( + elementId, + str, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + # Set properties + self.elementId = elementId + self.isVisible = isVisible + + super().__init__( + serializable_properties=[], + simple_properties=[ + "elementId", + "isVisible", + ], ) diff --git a/src/webexpythonsdk/models/cards/adaptive_card_component.py b/src/webexpythonsdk/models/cards/adaptive_card_component.py index d17852f..ab00beb 100644 --- a/src/webexpythonsdk/models/cards/adaptive_card_component.py +++ b/src/webexpythonsdk/models/cards/adaptive_card_component.py @@ -1,4 +1,4 @@ -"""Webex Adaptive Card Component base class. +"""Webex Adaptive Card - Component Base Class Model. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -21,14 +21,15 @@ SOFTWARE. """ -import json import enum +import json class AdaptiveCardComponent: - """Base class for all Adaptive Card components. + """ + Base class for all Adaptive Card elements. - Each component should inherit from this class and specify which of its + Each element should inherit from this class and specify which of its properties fall into the following two categories: * Simple properties are basic types (int, float, str, etc.). @@ -39,7 +40,8 @@ class AdaptiveCardComponent: """ def __init__(self, serializable_properties, simple_properties): - """Initialize a serializable object. + """ + Initialize a serializable object. Args: serializable_properties(list): List of all serializable properties @@ -49,13 +51,14 @@ def __init__(self, serializable_properties, simple_properties): self.simple_properties = simple_properties def to_dict(self): - """Serialize the component into a Python dictionary. + """ + Serialize the element into a Python dictionary. The to_dict() method recursively serializes the object's data into a Python dictionary. Returns: - dict: Dictionary representation of this component. + dict: Dictionary representation of this element. """ serialized_data = {} @@ -69,14 +72,15 @@ def to_dict(self): serialized_data[property_name] = property_value - # Recursively serialize sub-components + # Recursively serialize sub-elements for property_name in self.serializable_properties: property_value = getattr(self, property_name, None) if property_value is not None: if isinstance(property_value, list): serialized_data[property_name] = [ - item.to_dict() for item in property_value + item.to_dict() if hasattr(item, "to_dict") else item + for item in property_value ] else: serialized_data[property_name] = property_value.to_dict() @@ -84,7 +88,8 @@ def to_dict(self): return serialized_data def to_json(self, **kwargs): - """Serialize the component into JSON text. + """ + Serialize the element into JSON text. Any keyword arguments provided are passed through the Python JSON encoder. diff --git a/src/webexpythonsdk/models/cards/card.py b/src/webexpythonsdk/models/cards/card.py deleted file mode 100644 index b2b5901..0000000 --- a/src/webexpythonsdk/models/cards/card.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Webex Adaptive Card data model. - -Copyright (c) 2016-2024 Cisco and/or its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -from .actions import OpenUrl, ShowCard, Submit -from .adaptive_card_component import AdaptiveCardComponent -from .utils import check_type - - -class AdaptiveCard(AdaptiveCardComponent): - """Adaptive Card data model. - - Note: Webex currently supports version 1.1 of adaptive cards and thus - only features from that release are supported in this abstraction. - """ - - type = "AdaptiveCard" - schema = "http://adaptivecards.io/schemas/adaptive-card.json" - version = "1.1" - - def __init__( - self, - body=None, - actions=None, - selectAction=None, - fallbackText=None, - lang=None, - ): - """Initialize a new Adaptive Card object. - - Args: - body(list): The list of components and containers making up the - body of this adaptive card. - actions(list): The list of actions this adaptive card should - contain - selectAction(action): The action that should be invoked when this - adaptive card is selected. Can be any action other then - 'ShowCard' - fallbackText(str): The text that should be displayed on clients - that can't render adaptive cards - lang(str): The 2-letter ISO-639-1 language used in the card. This - is used for localization of date/time functions - - """ - # Check types - check_type( - actions, - (ShowCard, Submit, OpenUrl), - optional=True, - is_list=True, - ) - check_type(selectAction, (Submit, OpenUrl), optional=True) - check_type(fallbackText, str, optional=True) - check_type(lang, str, optional=True) - - # Set properties - self.body = body - self.actions = actions - self.selectAction = selectAction - self.fallbackText = fallbackText - self.lang = lang - - super().__init__( - serializable_properties=["body", "actions", "selectAction"], - simple_properties=["version", "fallbackText", "lang", "type"], - ) - - def to_dict(self): - # We need to overwrite the to_dict method to add the $schema - # property that can't be specified the normal way due to the - # `$` in the property name. - serialized_data = super().to_dict() - serialized_data["$schema"] = self.schema - return serialized_data diff --git a/src/webexpythonsdk/models/cards/card_elements.py b/src/webexpythonsdk/models/cards/card_elements.py new file mode 100644 index 0000000..6507e93 --- /dev/null +++ b/src/webexpythonsdk/models/cards/card_elements.py @@ -0,0 +1,1137 @@ +"""Webex Adaptive Card - Card Elements Model. + +Copyright (c) 2016-2024 Cisco and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.actions as ACTIONS +import webexpythonsdk.models.cards.containers as CONTAINERS +import webexpythonsdk.models.cards.inputs as INPUTS +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + check_type, + validate_input, + validate_dict_str, + validate_uri, +) + + +class TextBlock(AdaptiveCardComponent): + """ + **Adaptive Card - TextBlock Element** + + Displays text, allowing control over font sizes, weight, and color. + """ + + type = "TextBlock" + + def __init__( + self, + text: str, + color: OPTIONS.Colors = None, + fontType: OPTIONS.FontType = None, + horizontalAlignment: OPTIONS.HorizontalAlignment = None, + isSubtle: bool = None, + maxLines: int = None, + size: OPTIONS.FontSize = None, + weight: OPTIONS.FontWeight = None, + wrap: bool = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new TextBlock element. + + Args: + text (str, Mandatory): Text to display. + color (Colors, Optional): Control the color of TextBlock element. + **_Defaults to None._** Allowed value(s): + Colors.DEFAULT, Colors.DARK, Colors.LIGHT, Colors.ACCENT, + Colors.GOOD, Colors.WARNING, or Colors.ATTENTION. + fontType (FontType, Optional): Type of font to use for rendering. + **_Defaults to None._** Allowed value(s): + FontType.DEFAULT or FontType.MONOSPACE. + horizontalAlignment (HorizontalAlignment, Optional): Controls the + horizontal text alignment. When not specified, the value of + horizontalAlignment is inherited from the parent container. If + no parent container has horizontalAlignment set, it defaults + to Left. Allowed value(s): + HorizontalAlignment.LEFT, HorizontalAlignment.CENTER, or + HorizontalAlignment.RIGHT. + isSubtle (bool, Optional): If true, displays text slightly toned + down to appear less prominent. **_Defaults to None._** + maxLines (int, Optional): Specifies the maximum number of lines to + display. **_Defaults to None._** + size (FontSize, Optional): Controls size of text. **_Defaults to + None._** Allowed value(s): + FontSize.DEFAULT, FontSize.SMALL, FontSize.MEDIUM, + FontSize.LARGE, or FontSize.EXTRA_LARGE. + weight (FontWeight, Optional): Controls the weight of TextBlock + elements. **_Defaults to None._** Allowed value(s): + FontWeight.DEFAULT, FontWeight.LIGHTER, or FontWeight.BOLDER. + wrap (bool, Optional): If true, allow text to wrap. Otherwise, + text is clipped. **_Defaults to None._** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + text, + str, + ) + + validate_input( + color, + OPTIONS.Colors, + optional=True, + ) + + validate_input( + fontType, + OPTIONS.FontType, + optional=True, + ) + + validate_input( + horizontalAlignment, + OPTIONS.HorizontalAlignment, + optional=True, + ) + + check_type( + isSubtle, + bool, + optional=True, + ) + + check_type( + maxLines, + int, + optional=True, + ) + + validate_input( + size, + OPTIONS.FontSize, + optional=True, + ) + + validate_input( + weight, + OPTIONS.FontWeight, + optional=True, + ) + + check_type( + wrap, + bool, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + Image, + CONTAINERS.ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + Media, + RichTextBlock, + TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.text = text + self.color = color + self.fontType = fontType + self.horizontalAlignment = horizontalAlignment + self.isSubtle = isSubtle + self.maxLines = maxLines + self.size = size + self.weight = weight + self.wrap = wrap + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "text", + "color", + "fontType", + "horizontalAlignment", + "isSubtle", + "maxLines", + "size", + "weight", + "wrap", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class Image(AdaptiveCardComponent): + """ + **Adaptive Card - Image Element** + + Displays an image. Acceptable formats are PNG, JPEG, and GIF. + """ + + type = "Image" + + def __init__( + self, + url: object, + altText: str = None, + backgroundColor: str = None, + height: object = OPTIONS.BlockElementHeight.AUTO, + horizontalAlignment: OPTIONS.HorizontalAlignment = None, + selectAction: object = None, + size: OPTIONS.ImageSize = None, + style: OPTIONS.ImageStyle = None, + width: str = None, + fallback: object = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new Image element. + + Args: + url (str, Mandatory): The URL to the image. Supports data URI. + Allowed value(s): + uri + altText (str, Optional): Alternate text describing the image. + **_Defaults to None._** + backgroundColor (str, Optional): Applies a background to a + transparent image. This property will respect the image style. + **_Defaults to None._** + height (str or BlockElementHeight, Optional): The desired height + of the image. If specified as a pixel value, ending in 'px', + E.g., 50px, the image will distort to fit that exact height. + This overrides the size property. **_Defaults to + BlockElementHeight.AUTO_** Allowed value(s): + str, BlockElementHeight.AUTO, or BlockElementHeight.STRETCH + horizontalAlignment (HorizontalAlignment, Optional): Controls how + this element is horizontally positioned within its parent. + When not specified, the value of horizontalAlignment is + inherited from the parent container. If no parent container + has horizontalAlignment set, it defaults to Left. Allowed + value(s): + HorizontalAlignment.LEFT, HorizontalAlignment.CENTER, or + HorizontalAlignment.RIGHT. + selectAction (Action Element, Optional): An Action that will be + invoked when the Image is tapped or selected. Action.ShowCard + is not supported. **_Defaults to None._** Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + size (ImageSize, Optional): Controls how this Image is displayed. + **_Defaults to None._** Allowed value(s): + ImageSize.AUTO, ImageSize.STRETCH, ImageSize.SMALL, + ImageSize.MEDIUM, or ImageSize.LARGE. + style (ImageStyle, Optional): Controls the approximate size of the + image. The physical dimensions will vary per host. **_Defaults + to None._** Allowed value(s): + ImageStyle.DEFAULT or ImageStyle.PERSON + width (str, Optional): The desired on-screen width of the image, + ending in 'px'. E.g., 50px. This overrides the size property. + **_Defaults to None._** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + validate_uri( + url, + ) + + check_type( + altText, + str, + optional=True, + ) + + check_type( + backgroundColor, + str, + optional=True, + ) + + check_type( + height, + ( + str, + OPTIONS.BlockElementHeight, + ), + optional=True, + ) + + validate_input( + horizontalAlignment, + OPTIONS.HorizontalAlignment, + optional=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + validate_input( + size, + OPTIONS.ImageSize, + optional=True, + ) + + validate_input( + style, + OPTIONS.ImageStyle, + optional=True, + ) + + check_type( + width, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + Image, + CONTAINERS.ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + Media, + RichTextBlock, + TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.url = url + self.altText = altText + self.backgroundColor = backgroundColor + self.height = height + self.horizontalAlignment = horizontalAlignment + self.selectAction = selectAction + self.size = size + self.style = style + self.width = width + self.fallback = fallback + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "selectAction", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "url", + "altText", + "backgroundColor", + "height", + "horizontalAlignment", + "size", + "style", + "width", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class Media(AdaptiveCardComponent): + """ + **Adaptive Card - Media Element** + + Displays a media player for audio or video content. + """ + + type = "Media" + + def __init__( + self, + sources: list[object], + poster: object = None, + altText: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new Media element. + + Args: + sources (list of MediaSource Element(s), Mandatory): Array of + media sources to attempt to play. Allowed value(s): + MediaSource + poster (uri, Optional): URL of an image to display before playing. + Supports data URI. If poster is omitted, the Media element + will either use a default poster (controlled by the host + application) or will attempt to automatically pull the poster + from the target video service when the source URL points to a + video from a Web provider such as YouTube. **_Defaults to + None._** Allowed value(s): + uri + altText (str, Optional): Alternate text describing the audio or + video. **_Defaults to None._** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + sources, + MediaSource, + is_list=True, + ) + + validate_uri( + poster, + optional=True, + ) + + check_type( + altText, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + Image, + CONTAINERS.ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + Media, + RichTextBlock, + TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.sources = sources + self.poster = poster + self.altText = altText + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "sources", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "poster", + "altText", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class MediaSource(AdaptiveCardComponent): + """ + **Adaptive Card - MediaSource Element** + + Defines a source for a Media element. + """ + + def __init__( + self, + url: object, + mimeType: str = None, + ): + """ + Initialize a new MediaSource element. + + Args: + url (uri, Mandatory): URL to media. Supports data URI. Allowed + value(s): + uri + mimeType (str, Optional): Mime type of associated media + (e.g. "video/mp4"). For YouTube and other Web video URLs, + mimeType can be omitted. + """ + # Check types + validate_uri( + url, + ) + + check_type( + mimeType, + str, + ) + + # Set properties + self.url = url + self.mimeType = mimeType + + super().__init__( + serializable_properties=[], + simple_properties=[ + "url", + "mimeType", + ], + ) + + +class RichTextBlock(AdaptiveCardComponent): + """ + **Adaptive Card - RichTextBlock Element** + + Defines an array of inlines, allowing for inline text formatting. + """ + + type = "RichTextBlock" + + def __init__( + self, + inlines: list[object], + horizontalAlignment: OPTIONS.HorizontalAlignment = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new RichTextBlock element. + + Args: + inlines (list of TextRun Card Element(s) or str, Mandatory): The + array of inlines. Allowed value(s): + TextRun, str + horizontalAlignment (HorizontalAlignment, Optional): Controls the + horizontal text alignment. When not specified, the value of + horizontalAlignment is inherited from the parent container. If + no parent container has horizontalAlignment set, it defaults + to Left. Allowed value(s): HorizontalAlignment.LEFT, + HorizontalAlignment.CENTER, or HorizontalAlignment.RIGHT + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + inlines, + ( + TextRun, + str, + ), + is_list=True, + ) + + validate_input( + horizontalAlignment, + OPTIONS.HorizontalAlignment, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + Image, + CONTAINERS.ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + Media, + RichTextBlock, + TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.inlines = inlines + self.horizontalAlignment = horizontalAlignment + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "inlines", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "horizontalAlignment", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class TextRun(AdaptiveCardComponent): + """ + **Adaptive Card - TextRun Element** + + Defines a single run of formatted text. A TextRun with no properties set + can be represented in the json as string containing the text as a shorthand + for the json object. These two representations are equivalent. + """ + + type = "TextRun" + + def __init__( + self, + text: str, + color: OPTIONS.Colors = None, + fontType: OPTIONS.FontType = None, + highlight: bool = None, + isSubtle: bool = None, + italic: bool = None, + selectAction: object = None, + size: OPTIONS.FontSize = None, + strikethrough: bool = None, + underline: bool = None, + weight: OPTIONS.FontWeight = None, + ): + """ + Initialize a new TextRun element. + + Args: + text (str, Mandatory): Text to display. Markdown is not supported. + color (Colors, Optional): Controls the color of the text. + **_Defaults to None._** Allowed value(s): + Colors.DEFAULT, Colors.DARK, Colors.LIGHT, Colors.ACCENT, + Colors.GOOD, Colors.WARNING, or Colors.ATTENTION + fontType (FontType, Optional): The type of font to use. + **_Defaults to None._** Allowed value(s): + FontType.DEFAULT or FontType.MONOSPACE + highlight (bool, Optional): If true, displays the text highlighted. + **_Defaults to None._** + isSubtle (bool, Optional): If true, displays text slightly toned + down to appear less prominent. **_Defaults to None._** + italic (bool, Optional): If true, displays the text using italic + font. **_Defaults to None._** + selectAction (Action Element, Optional): Action to invoke when + this text run is clicked. Visually changes the text run into a + hyperlink. Action.ShowCard is not supported. **_Defaults to + None._** Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + size (FontSize, Optional): Controls size of text. **_Defaults to + None._** Allowed value(s): + FontSize.DEFAULT, FontSize.SMALL, FontSize.MEDIUM, + FontSize.LARGE, or FontSize.EXTRA_LARGE + strikethrough (bool, Optional): If true, displays the text with + strikethrough. **_Defaults to None._** + underline (bool, Optional): If true, displays the text with an + underline. **_Defaults to None._** + weight (FontWeight, Optional): Controls the weight of the text. + **_Defaults to None._** Allowed value(s): + FontWeight.DEFAULT, FontWeight.LIGHTER, or FontWeight.BOLDER + """ + # Check types + check_type( + text, + str, + ) + + validate_input( + color, + OPTIONS.Colors, + optional=True, + ) + + validate_input( + fontType, + OPTIONS.FontType, + optional=True, + ) + + check_type( + highlight, + bool, + optional=True, + ) + + check_type( + isSubtle, + bool, + optional=True, + ) + + check_type( + italic, + bool, + optional=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + validate_input( + size, + OPTIONS.FontSize, + optional=True, + ) + + check_type( + strikethrough, + bool, + optional=True, + ) + + check_type( + underline, + bool, + optional=True, + ) + + validate_input( + weight, + OPTIONS.FontWeight, + optional=True, + ) + + # Set properties + self.text = text + self.color = color + self.fontType = fontType + self.highlight = highlight + self.isSubtle = isSubtle + self.italic = italic + self.selectAction = selectAction + self.size = size + self.strikethrough = strikethrough + self.underline = underline + self.weight = weight + + super().__init__( + serializable_properties=[ + "selectAction", + ], + simple_properties=[ + "type", + "text", + "color", + "fontType", + "highlight", + "isSubtle", + "italic", + "size", + "strikethrough", + "underline", + "weight", + ], + ) diff --git a/src/webexpythonsdk/models/cards/cards.py b/src/webexpythonsdk/models/cards/cards.py new file mode 100644 index 0000000..5e44d85 --- /dev/null +++ b/src/webexpythonsdk/models/cards/cards.py @@ -0,0 +1,247 @@ +"""Webex Adaptive Card - Cards Model. + +Copyright (c) 2016-2024 Cisco and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.card_elements as CARD_ELEMENTS +import webexpythonsdk.models.cards.containers as CONTAINERS +import webexpythonsdk.models.cards.actions as ACTIONS +import webexpythonsdk.models.cards.inputs as INPUTS +import webexpythonsdk.models.cards.types as TYPES +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + check_type, + validate_input, + validate_uri, +) + + +class AdaptiveCard(AdaptiveCardComponent): + """ + **Adaptive Card - Adaptive Card Element** + + An Adaptive Card, containing a free-form body of card elements, and an + optional set of actions. + + **_Note:_** Webex currently supports version 1.3 of adaptive cards and + thus only features from that release are supported in this abstraction. + """ + + type = "AdaptiveCard" + schema = "http://adaptivecards.io/schemas/adaptive-card.json" + version = "1.3" + + def __init__( + self, + body: list[object] = None, + actions: list[object] = None, + selectAction: object = None, + fallbackText: str = None, + backgroundImage: object = None, + minHeight: str = None, + speak: str = None, + lang: str = None, + verticalContentAlignment: OPTIONS.VerticalContentAlignment = None, + ): + """ + Initialize a new Adaptive Card element. + + Args: + body (list of Card Element(s), Optional): The card elements to + show in the primary card region. **_Defaults to None._** + Allowed value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock + actions (list of Actions Element(s), Optional): The Actions to + show in the card's action bar. **_Defaults to None._** Allowed + value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility + selectAction (Actions Element, Optional): An Action that will be + invoked when the card is tapped or selected. Action.ShowCard + is not supported. **_Defaults to None._** Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + fallbackText (str, Optional): Text shown when the client doesn't + support the version specified (may contain markdown). + **_Defaults to None._** + backgroundImage (BackgroundImage or uri, Optional): Specifies the + background image of the card. **_Defaults to None._** Allowed + value(s): + BackgroundImage or uri + minHeight (str, Optional): Specifies the minimum height of the + card. **_Defaults to None._** + speak (str, Optional): Specifies what should be spoken for this + entire card. This is simple text or SSML fragment. **_Defaults + to None._** + lang (str, Optional): The 2-letter ISO-639-1 language used in the + card. Used to localize any date/time functions. **_Defaults to + None._** + verticalContentAlignment (VerticalContentAlignment, Optional): + Defines how the content should be aligned vertically within + the container. Only relevant for fixed-height cards, or cards + with a minHeight specified. **_Defaults to None._** Allowed + value(s): + VerticalContentAlignment.TOP, VerticalContentAlignment.CENTER, + or VerticalContentAlignment.BOTTOM + + """ + # Check types + check_type( + body, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + is_list=True, + ) + + check_type( + actions, + ( + ACTIONS.OpenUrl, + ACTIONS.ShowCard, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + is_list=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + check_type( + fallbackText, + str, + optional=True, + ) + + # Check if backgroundImage is of TYPES.BackgroundImage type + if hasattr(backgroundImage, "to_dict"): + check_type( + backgroundImage, + TYPES.BackgroundImage, + optional=True, + ) + # If not, check if it is an URI and reachable + else: + validate_uri( + uri=backgroundImage, + optional=True, + ) + + check_type( + minHeight, + str, + optional=True, + ) + + check_type( + speak, + str, + optional=True, + ) + + check_type( + lang, + str, + optional=True, + ) + + check_type( + verticalContentAlignment, + str, + optional=True, + ) + + validate_input( + verticalContentAlignment, + OPTIONS.VerticalContentAlignment, + optional=True, + ) + + # Set properties + self.body = body + self.actions = actions + self.selectAction = selectAction + self.fallbackText = fallbackText + self.backgroundImage = backgroundImage + self.minHeight = minHeight + self.speak = speak + self.lang = lang + self.verticalContentAlignment = verticalContentAlignment + + super().__init__( + serializable_properties=[ + "body", + "actions", + "selectAction", + *( + ["backgroundImage"] if hasattr(backgroundImage, "to_dict") + else [] + ), + ], + simple_properties=[ + "type", + "version", + "fallbackText", + *( + [] if hasattr(backgroundImage, "to_dict") + else ["backgroundImage"] + ), + "minHeight", + "speak", + "lang", + "verticalContentAlignment", + ], + ) + + def to_dict(self): + # We need to overwrite the to_dict method to add the $schema + # property that can't be specified the normal way due to the + # `$` in the property name. + serialized_data = super().to_dict() + serialized_data["$schema"] = self.schema + return serialized_data diff --git a/src/webexpythonsdk/models/cards/components.py b/src/webexpythonsdk/models/cards/components.py deleted file mode 100644 index 300208c..0000000 --- a/src/webexpythonsdk/models/cards/components.py +++ /dev/null @@ -1,323 +0,0 @@ -"""Webex Adaptive Card components. - -Copyright (c) 2016-2024 Cisco and/or its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -from .actions import OpenUrl, Submit -from .adaptive_card_component import AdaptiveCardComponent -from .options import ( - BlockElementHeight, - ImageSize, - ImageStyle, - Spacing, - HorizontalAlignment, -) -from .utils import check_type - - -class MediaSource(AdaptiveCardComponent): - """Adaptive Card Media Source.""" - - def __init__(self, mimeType, url): - """Initialize a new Media Source component. - - Args: - mimeType(str): Mime type of the associated media(i.e. 'video/mp4') - url(str): URL of the media. - """ - # Check types - check_type(mimeType, str) - check_type(url, str) - - self.mimeType = mimeType - self.url = url - - super().__init__( - serializable_properties=[], - simple_properties=["mimeType", "url"], - ) - - -class Media(AdaptiveCardComponent): - """Adaptive Card Media component.""" - - type = "Media" - - def __init__( - self, - sources, - poster=None, - altText=None, - height=None, - separator=None, - spacing=None, - id=None, - ): - """Initialize a new Media component. - - Args: - sources(list): A list of media sources to be played - poster(str): The url to the image that is displayed before playing - altText(str): Alternative text for this component - height(BlockElementHeight): The height of this block element - separator(bool): Draw a separating line when set to true - spacing(Spacing): Specify the spacing of this component - id(str): The id of this component - """ - # Check types - check_type(sources, MediaSource, is_list=True) - check_type(poster, str, optional=True) - check_type(altText, str, optional=True) - check_type(height, BlockElementHeight, optional=True) - check_type(separator, bool, optional=True) - check_type(spacing, Spacing, optional=True) - check_type(id, str, optional=True) - - self.sources = sources - self.poster = poster - self.altText = altText - self.height = height - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=["sources"], - simple_properties=[ - "type", - "poster", - "altText", - "height", - "separator", - "spacing", - "id", - ], - ) - - -class Image(AdaptiveCardComponent): - """Adaptive Card Image component.""" - - type = "Image" - - def __init__( - self, - url, - altText=None, - backgroundColor=None, - height=None, - horizontalAlignment=None, - selectAction=None, - size=None, - style=None, - width=None, - separator=None, - spacing=None, - id=None, - ): - """Initialize a new image component. - - Args: - url(str): The URL to the image - altText(str): Alternative text describing the image - backgroundColor(str): Background color for transparent images. - height(str, BlockElementHeight): Height of the image either as a - pixel value(i.e. '50px') or as an instance of - BlockElementHeight - horizontalAlignmnet(HorizontalAlignment): Controls how the - component is positioned within its parent. - selectAction(OpenUrl, Submit): Option that is carried out when the - card is selected. - size(ImageSize): Controls the approximate size of the image. - style(ImageStyle): The display style of this image. - width(str): Width of the image as a pixel value (i.e. '50px') - separator(bool): Draw a separating line when set to true - spacing(Spacing): Specify the spacing of this component - id(str): The id of this component - """ - check_type(url, str) - check_type(altText, str, optional=True) - check_type(backgroundColor, str, optional=True) - check_type(height, (str, BlockElementHeight), optional=True) - check_type( - horizontalAlignment, (str, HorizontalAlignment), optional=True - ) - check_type(selectAction, (OpenUrl, Submit), optional=True) - check_type(size, ImageSize, optional=True) - check_type(style, ImageStyle, optional=True) - check_type(width, str, optional=True) - check_type(separator, bool, optional=True) - check_type(spacing, Spacing, optional=True) - check_type(id, str, optional=True) - - self.url = url - self.altText = altText - self.backgroundColor = backgroundColor - self.height = height - self.horizontalAlignment = horizontalAlignment - self.selectAction = selectAction - self.size = size - self.style = style - self.width = width - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=[], - simple_properties=[ - "type", - "url", - "altText", - "backgroundColor", - "height", - "horizontalAlignment", - "selectAction", - "size", - "style", - "width", - "separator", - "spacing", - "id", - ], - ) - - -class TextBlock(AdaptiveCardComponent): - """Adaptive Card Text Block component.""" - - type = "TextBlock" - - def __init__( - self, - text, - color=None, - horizontalAlignment=None, - isSubtle=None, - maxLines=None, - size=None, - weight=None, - wrap=None, - separator=None, - spacing=None, - id=None, - ): - """Initialize a new TextBlock component.""" - # TODO: Document arguments - self.text = text - self.color = color - self.horizontalAlignment = horizontalAlignment - self.isSubtle = isSubtle - self.maxLines = maxLines - self.size = size - self.weight = weight - self.wrap = wrap - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=[], - simple_properties=[ - "type", - "text", - "color", - "horizontalAlignment", - "isSubtle", - "maxLines", - "size", - "weight", - "wrap", - "spacing", - "id", - "separator", - ], - ) - - -class Column(AdaptiveCardComponent): - """Adaptive Card Column component.""" - - type = "Column" - - def __init__( - self, - items=None, - separator=None, - spacing=None, - selectAction=None, - style=None, - verticalContentAlignment=None, - width=None, - id=None, - ): - """Initialize a new Column component.""" - # TODO: Document arguments - self.items = items - self.separator = separator - self.spacing = spacing - self.selectAction = selectAction - self.style = style - self.verticalContentAlignment = verticalContentAlignment - self.width = width - self.id = id - - super().__init__( - serializable_properties=["items"], - simple_properties=[ - "type", - "separator", - "spacing", - "selectAction", - "style", - "verticalContentAlignment", - "width", - "id", - ], - ) - - -class Fact(AdaptiveCardComponent): - """Adaptive Card Fact component.""" - - def __init__(self, title, value): - """Initialize a new Fact component.""" - # TODO: Document arguments - self.title = title - self.value = value - - super().__init__( - serializable_properties=[], - simple_properties=["title", "value"], - ) - - -class Choice(AdaptiveCardComponent): - def __init__(self, title, value): - """Initialize a new Choice component.""" - # TODO: Document arguments - self.title = title - self.value = value - - super().__init__( - serializable_properties=[], - simple_properties=["title", "value"], - ) diff --git a/src/webexpythonsdk/models/cards/container.py b/src/webexpythonsdk/models/cards/container.py deleted file mode 100644 index b6d6972..0000000 --- a/src/webexpythonsdk/models/cards/container.py +++ /dev/null @@ -1,158 +0,0 @@ -"""Webex Adaptive Card container data models. - -Copyright (c) 2016-2024 Cisco and/or its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -from .adaptive_card_component import AdaptiveCardComponent - - -class Container(AdaptiveCardComponent): - """Adaptive Card Container component.""" - - type = "Container" - - def __init__( - self, - items, - selectAction=None, - style=None, - verticalContentAlignment=None, - height=None, - separator=None, - spacing=None, - id=None, - ): - self.items = items - self.selectAction = selectAction - self.style = style - self.verticalContentAlignment = verticalContentAlignment - self.height = height - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=["items"], - simple_properties=[ - "selectAction", - "style", - "verticalContentAlignment", - "height", - "separator", - "spacing", - "id", - "type", - ], - ) - - -class ColumnSet(AdaptiveCardComponent): - """Adaptive Card Column Set component.""" - - type = "ColumnSet" - - def __init__( - self, - columns=None, - selectAction=None, - height=None, - separator=None, - spacing=None, - id=None, - ): - self.columns = columns - self.selectAction = selectAction - self.height = height - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=["columns"], - simple_properties=[ - "selectAction", - "height", - "separator", - "spacing", - "id", - "type", - ], - ) - - -class FactSet(AdaptiveCardComponent): - """Adaptive Card Fact Set component.""" - - type = "FactSet" - - def __init__( - self, facts, height=None, separator=None, spacing=None, id=None - ): - self.facts = facts - self.height = height - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=["facts"], - simple_properties=[ - "type", - "height", - "separator", - "id", - "spacing", - ], - ) - - -class ImageSet(AdaptiveCardComponent): - """Adaptive Card Image Set component.""" - - type = "ImageSet" - - def __init__( - self, - images, - imageSize=None, - height=None, - separator=None, - spacing=None, - id=None, - ): - self.images = images - self.imageSize = imageSize - self.height = height - self.separator = separator - self.spacing = spacing - self.id = id - - super().__init__( - serializable_properties=["images"], - simple_properties=[ - "imageSize", - "height", - "separator", - "spacing", - "id", - "type", - ], - ) diff --git a/src/webexpythonsdk/models/cards/containers.py b/src/webexpythonsdk/models/cards/containers.py new file mode 100644 index 0000000..f5e5294 --- /dev/null +++ b/src/webexpythonsdk/models/cards/containers.py @@ -0,0 +1,1377 @@ +"""Webex Adaptive Card - Containers Model. + +Copyright (c) 2016-2024 Cisco and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.actions as ACTIONS +import webexpythonsdk.models.cards.card_elements as CARD_ELEMENTS +import webexpythonsdk.models.cards.inputs as INPUTS +import webexpythonsdk.models.cards.types as TYPES +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + check_type, + validate_input, + validate_dict_str, + validate_uri, +) + + +class ActionSet(AdaptiveCardComponent): + """ + **Adaptive Card - ActionSet Element** + + Displays a set of actions. + """ + + type = "ActionSet" + + def __init__( + self, + actions: list[object], + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new ActionSet element. + + Args: + actions (list of Action Element(s), Mandatory): The array of + Action elements to show. Allowed value(s): + OpenUrl, ShowCard, Submit, ToggleVisibility + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + actions, + ( + ACTIONS.OpenUrl, + ACTIONS.ShowCard, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + is_list=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.actions = actions + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "actions", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class Container(AdaptiveCardComponent): + """ + **Adaptive Card - Container Element** + + Containers group items together. + """ + + type = "Container" + + def __init__( + self, + items: list[object], + selectAction: object = None, + style: OPTIONS.ContainerStyle = None, + verticalContentAlignment: OPTIONS.VerticalContentAlignment = None, + bleed: bool = None, + backgroundImage: object = None, + minHeight: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new Container element. + + Args: + items (list of Card Element(s), Mandatory): The card elements to + render inside the Container. Allowed value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock + selectAction (Action Element, Optional): An Action that will be + invoked when the Container is tapped or selected. + Action.ShowCard is not supported. **_Defaults to None._** + Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + style (ContainerStyle, Optional): Style hint for Container. + **_Defaults to None._**Allowed value(s): + ContainerStyle.DEFAULT, ContainerStyle.EMPHASIS, + ContainerStyle.GOOD, ContainerStyle.ATTENTION, + ContainerStyle.WARNING, or ContainerStyle.ACCENT + verticalContentAlignment (VerticalContentAlignment, Optional): + Defines how the content should be aligned vertically within + the container. When not specified, the value of + verticalContentAlignment is inherited from the parent + container. If no parent container has verticalContentAlignment + set, it defaults to Top. Allowed value(s): + VerticalContentAlignment.TOP, VerticalContentAlignment.CENTER, + or VerticalContentAlignment.BOTTOM + bleed (bool, Optional): Determines whether the element should + bleed through its parent's padding. **_Defaults to None._** + backgroundImage (BackgroundImage or uri, Optional): Specifies the + background image. Acceptable formats are PNG, JPEG, and GIF. + **_Defaults to None._** Allowed value(s): + BackgroundImage or uri + minHeight (str, Optional): Specifies the minimum height of the + container in pixels, like "80px". **_Defaults to None._** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + items, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + is_list=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + validate_input( + style, + OPTIONS.ContainerStyle, + optional=True, + ) + + validate_input( + verticalContentAlignment, + OPTIONS.VerticalContentAlignment, + optional=True, + ) + + check_type( + bleed, + bool, + optional=True, + ) + + # Check if backgroundImage is of TYPES.BackgroundImage type + if hasattr(backgroundImage, "to_dict"): + check_type( + backgroundImage, + TYPES.BackgroundImage, + optional=True, + ) + # If not, check if it is an URI and reachable + else: + validate_uri( + backgroundImage, + optional=True, + ) + + check_type( + minHeight, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.items = items + self.selectAction = selectAction + self.style = style + self.verticalContentAlignment = verticalContentAlignment + self.bleed = bleed + self.backgroundImage = backgroundImage + self.minHeight = minHeight + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "items", + "selectAction", + *( + ["backgroundImage"] if hasattr(backgroundImage, "to_dict") + else [] + ), + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "style", + "verticalContentAlignment", + "bleed", + *( + [] if hasattr(backgroundImage, "to_dict") + else ["backgroundImage"] + ), + "minHeight", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class ColumnSet(AdaptiveCardComponent): + """ + **Adaptive Card - ColumnSet Element** + + ColumnSet divides a region into Columns, allowing elements to sit + side-by-side. + """ + + type = "ColumnSet" + + def __init__( + self, + columns: list[object] = None, + selectAction: object = None, + style: OPTIONS.ContainerStyle = None, + bleed: bool = None, + minHeight: str = None, + horizontalAlignment: OPTIONS.HorizontalAlignment = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight=None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new ColumnSet element. + + Args: + columns (list of Column Element(s), Optional): The array of + Columns to divide the region into. **_Defaults to None._** + Allowed value(s): + Column + selectAction (Action Element, Optional): An Action that will be + invoked when the ColumnSet is tapped or selected. + Action.ShowCard is not supported. **_Defaults to None._** + Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + style (ContainerStyle, Optional): Style hint for ColumnSet. + **_Defaults to None._**Allowed value(s): + ContainerStyle.DEFAULT, ContainerStyle.EMPHASIS, + ContainerStyle.GOOD, ContainerStyle.ATTENTION, + ContainerStyle.WARNING, or ContainerStyle.ACCENT + bleed (bool, Optional): Determines whether the element should + bleed through its parent's padding. **_Defaults to None._** + minHeight (str, Optional): Specifies the minimum height of the + column set in pixels, like "80px". **_Defaults to None._** + horizontalAlignment (HorizontalAlignment, Optional): Controls the + horizontal alignment of the ColumnSet. When not specified, the + value of horizontalAlignment is inherited from the parent + container. If no parent container has horizontalAlignment set, + it defaults to Left. Allowed value(s): + HorizontalAlignment.LEFT, HorizontalAlignment.CENTER, or + HorizontalAlignment.RIGHT + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + columns, + Column, + optional=True, + is_list=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + validate_input( + style, + OPTIONS.ContainerStyle, + optional=True, + ) + + check_type( + bleed, + bool, + optional=True, + ) + + check_type( + minHeight, + str, + optional=True, + ) + + validate_input( + horizontalAlignment, + OPTIONS.HorizontalAlignment, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.columns = columns + self.selectAction = selectAction + self.style = style + self.bleed = bleed + self.minHeight = minHeight + self.horizontalAlignment = horizontalAlignment + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "columns", + "selectAction", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "style", + "bleed", + "minHeight", + "horizontalAlignment", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) + + +class Column(AdaptiveCardComponent): + """ + **Adaptive Card - Column Element** + + Defines a container that is part of a ColumnSet. + """ + + type = "Column" + + def __init__( + self, + items: list[object] = None, + backgroundImage: object = None, + bleed: bool = None, + fallback: object = None, + minHeight: str = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + selectAction: object = None, + style: OPTIONS.ContainerStyle = None, + verticalContentAlignment: OPTIONS.VerticalContentAlignment = None, + width: object = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new Column element. + + Args: + items (list of Column Element(s), Optional): The card elements to + render inside the Column. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock + backgroundImage (BackgroundImage or uri, Optional): Specifies the + background image. Acceptable formats are PNG, JPEG, and GIF. + **_Defaults to None._** Allowed value(s): + BackgroundImage or uri + bleed (bool, Optional): Determines whether the element should + bleed through its parent's padding. **_Defaults to None._** + fallback (Column Element or str, Optional): Describes what to do + when an unknown element is encountered or the requires of this + or any children can't be met. **_Defaults to None._** Allowed + value(s): + Column or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + minHeight (str, Optional): Specifies the minimum height of the + container in pixels, like "80px". **_Defaults to None._** + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + selectAction (Action Element, Optional): An Action that will be + invoked when the Column is tapped or selected. Action.ShowCard + is not supported. **_Defaults to None._** Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + style (ContainerStyle, Optional): Style hint for Column. + **_Defaults to None._**Allowed value(s): + ContainerStyle.DEFAULT, ContainerStyle.EMPHASIS, + ContainerStyle.GOOD, ContainerStyle.ATTENTION, + ContainerStyle.WARNING, or ContainerStyle.ACCENT + verticalContentAlignment (VerticalContentAlignment, Optional): + Defines how the content should be aligned vertically within + the column. When not specified, the value of + verticalContentAlignment is inherited from the parent + container. If no parent container has verticalContentAlignment + set, it defaults to Top. **_Defaults to None._** Allowed + value(s): + VerticalContentAlignment.TOP, VerticalContentAlignment.CENTER, + or VerticalContentAlignment.BOTTOM + width (str or int, Optional): "auto", "stretch", a number + representing relative width of the column in the column group, + or in version 1.1 and higher, a specific pixel width, like + "50px". **_Defaults to None._** Allowed value(s): + str ("auto" or "stretch") or int + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + items, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + is_list=True, + ) + + # Check if backgroundImage is of TYPES.BackgroundImage type + if hasattr(backgroundImage, "to_dict"): + check_type( + backgroundImage, + TYPES.BackgroundImage, + optional=True, + ) + # If not, check if it is an URI and reachable + else: + validate_uri( + backgroundImage, + optional=True, + ) + + check_type( + bleed, + bool, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + Column, + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + check_type( + minHeight, + str, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + selectAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + validate_input( + style, + OPTIONS.ContainerStyle, + optional=True, + ) + + validate_input( + verticalContentAlignment, + OPTIONS.VerticalContentAlignment, + optional=True, + ) + + check_type( + width, + ( + str, + int, + ), + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.items = items + self.backgroundImage = backgroundImage + self.bleed = bleed + self.fallback = fallback + self.minHeight = minHeight + self.separator = separator + self.spacing = spacing + self.selectAction = selectAction + self.style = style + self.verticalContentAlignment = verticalContentAlignment + self.width = width + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "items", + *( + ["backgroundImage"] if hasattr(backgroundImage, "to_dict") + else [] + ), + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + "selectAction", + ], + simple_properties=[ + "type", + *( + [] if hasattr(backgroundImage, "to_dict") + else ["backgroundImage"] + ), + "bleed", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "minHeight", + "separator", + "spacing", + "style", + "verticalContentAlignment", + "width", + "id", + "isVisible", + "requires", + ], + ) + + +class FactSet(AdaptiveCardComponent): + """ + **Adaptive Card - FactSet Element** + + The FactSet element displays a series of facts (i.e., name/value pairs) in + a tabular form. + """ + + type = "FactSet" + + def __init__( + self, + facts: list[object], + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new FactSet element. + + Args: + facts (list of Fact Element(s), Mandatory): The array of Fact's. + Allowed value(s): + Fact + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + facts, + Fact, + is_list=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.facts = facts + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "facts", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "id", + "spacing", + "isVisible", + "requires", + ], + ) + + +class Fact(AdaptiveCardComponent): + """ + **Adaptive Card - Fact Element** + + Describes a Fact in a FactSet as a key/value pair. + """ + + def __init__( + self, + title: str, + value: str, + ): + """ + Initialize a new Fact element for the FactSet element. + + Args: + title (str, Mandatory): The title of the fact. + value (str, Mandatory): The value of the fact. + """ + # Check types + check_type( + title, + str, + ) + + check_type( + value, + str, + ) + + # Set properties + self.title = title + self.value = value + + super().__init__( + serializable_properties=[], + simple_properties=[ + "title", + "value", + ], + ) + + +class ImageSet(AdaptiveCardComponent): + """ + **Adaptive Card - ImageSet Element** + + The ImageSet displays a collection of Images similar to a gallery. + Acceptable formats are PNG, JPEG, and GIF. + """ + + type = "ImageSet" + + def __init__( + self, + images: list[object], + imageSize: OPTIONS.ImageSize = OPTIONS.ImageSize.MEDIUM, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + id: str = None, + isVisible: bool = True, + requires: dict[str, str] = None, + ): + """ + Initialize a new ImageSet element. + + Args: + images (list of Image Element(s), Mandatory): The array of Image + elements to show. Allowed value(s): + Image + imageSize (ImageSize, Optional): Controls the approximate size of + each image. The physical dimensions will vary per host. Auto + and stretch are not supported for ImageSet. The size will + default to medium if those values are set. **_Defaults to + ImageSize.MEDIUM._** Allowed value(s): + ImageSize.AUTO, ImageSize.STRETCH, ImageSize.SMALL, + ImageSize.MEDIUM, or ImageSize.LARGE + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + id (str, Optional): A unique identifier associated with the item. + **_Defaults to None._** + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + images, + CARD_ELEMENTS.Image, + is_list=True, + ) + + validate_input( + imageSize, + OPTIONS.ImageSize, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + ActionSet, + ColumnSet, + Container, + FactSet, + CARD_ELEMENTS.Image, + ImageSet, + INPUTS.ChoiceSet, + INPUTS.Date, + INPUTS.Number, + INPUTS.Text, + INPUTS.Time, + INPUTS.Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + id, + str, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties + self.images = images + self.imageSize = imageSize + self.fallback = fallback + self.height = height + self.separator = separator + self.spacing = spacing + self.id = id + self.isVisible = isVisible + self.requires = requires + + super().__init__( + serializable_properties=[ + "images", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ + "type", + "imageSize", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), + "height", + "separator", + "spacing", + "id", + "isVisible", + "requires", + ], + ) diff --git a/src/webexpythonsdk/models/cards/inputs.py b/src/webexpythonsdk/models/cards/inputs.py index 4939923..72a2c79 100644 --- a/src/webexpythonsdk/models/cards/inputs.py +++ b/src/webexpythonsdk/models/cards/inputs.py @@ -1,4 +1,4 @@ -"""Webex Access-Tokens API wrapper. +"""Webex Adaptive Card - Inputs Model. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -21,80 +21,495 @@ SOFTWARE. """ -from .adaptive_card_component import AdaptiveCardComponent +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.actions as ACTIONS +import webexpythonsdk.models.cards.card_elements as CARD_ELEMENTS +import webexpythonsdk.models.cards.containers as CONTAINERS +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + check_type, + validate_input, + validate_dict_str, +) class Text(AdaptiveCardComponent): - """Adaptive Card Text component.""" + """ + **Adaptive Card - Input.Text Element** + + Lets a user enter text. + """ type = "Input.Text" def __init__( self, - id, - isMultiline=None, - maxLength=None, - placeholder=None, - style=None, - value=None, - height=None, - separator=None, - spacing=None, + id: str, + isMultiline: bool = None, + maxLength: int = None, + placeholder: str = None, + regex: str = None, + style: OPTIONS.TextInputStyle = None, + inlineAction: object = None, + value: str = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): + """ + Initialize a new Input.Text element. + + Args: + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + isMultiline (bool, Optional): If true, allow multiple lines of + input. **_Defaults to None_.** + maxLength (int, Optional): Hint of maximum length characters to + collect (may be ignored by some clients). **_Defaults to + None_.** + placeholder (str, Optional): Description of the input desired. + Displayed when no text has been input. **_Defaults to None_.** + regex (str, Optional): Regular expression indicating the required + format of this text input. **_Defaults to None_.** + style (TextInputStyle, to None_.** Allowed value(s): + TextInputStyle.TEXT, TextInputStyle.TEL, TextInputStyle.URL, or + TextInputStyle.EMAIL + inlineAction (Action Element, Optional): The inline action for the + input. Typically displayed to the right of the input. It is + strongly recommended to provide an icon on the action (which + will be displayed instead of the title of the action). + **_Defaults to None_.** Allowed value(s): + OpenUrl, Submit, or ToggleVisibility + value (str, Optional): The initial value for this field. + **_Defaults to None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + id, + str, + ) + + check_type( + isMultiline, + bool, + optional=True, + ) + + check_type( + maxLength, + int, + optional=True, + ) + + check_type( + placeholder, + str, + optional=True, + ) + + check_type( + regex, + str, + optional=True, + ) + + validate_input( + style, + OPTIONS.TextInputStyle, + optional=True, + ) + + check_type( + inlineAction, + ( + ACTIONS.OpenUrl, + ACTIONS.Submit, + ACTIONS.ToggleVisibility, + ), + optional=True, + ) + + check_type( + value, + str, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.id = id self.isMultiline = isMultiline self.maxLength = maxLength self.placeholder = placeholder + self.regex = regex self.style = style + self.inlineAction = inlineAction self.value = value + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=[], + serializable_properties=[ + "inlineAction", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], simple_properties=[ - "id", "type", + "id", "isMultiline", "maxLength", "placeholder", + "regex", "style", "value", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", ], ) class Number(AdaptiveCardComponent): - """Adaptive Card Number component.""" + """ + **Adaptive Card - Input.Number Element** + + Allows a user to enter a number. + """ type = "Input.Number" def __init__( self, - id, - max=None, - min=None, - placeholder=None, - value=None, - height=None, - separator=None, - spacing=None, + id: str, + max: int = None, + min: int = None, + placeholder: str = None, + value: int = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): + """ + Initialize a new Input.Number element. + + Args: + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + max (int, Optional): Hint of maximum value (may be ignored by some + clients). **_Defaults to None_.** + min (int, Optional): Hint of minimum value (may be ignored by some + clients). **_Defaults to None_.** + placeholder (str, Optional): Description of the input desired. + Displayed when no text has been input. **_Defaults to None_.** + value (int, Optional): Initial value for this field. **_Defaults to + None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + id, + str, + ) + + check_type( + max, + int, + optional=True, + ) + + check_type( + min, + int, + optional=True, + ) + + check_type( + placeholder, + str, + optional=True, + ) + + check_type( + value, + int, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.id = id self.max = max self.min = min self.placeholder = placeholder self.value = value + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=[], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], simple_properties=[ "type", "id", @@ -102,40 +517,226 @@ def __init__( "min", "placeholder", "value", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", ], ) class Date(AdaptiveCardComponent): - """Adaptive Card Date component.""" + """ + **Adaptive Card - Input.Date Element** + + Lets a user choose a date. + """ type = "Input.Date" def __init__( self, - id, - max=None, - min=None, - placeholder=None, - value=None, - height=None, - separator=None, - spacing=None, + id: str, + max: str = None, + min: str = None, + placeholder: str = None, + value: str = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): + """ + Initialize a new Input.Date element. + + Args: + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + max (str, Optional): Hint of maximum value expressed in YYYY-MM-DD + (may be ignored by some clients). **_Defaults to None_.** + min (str, Optional): Hint of minimum value expressed in YYYY-MM-DD + (may be ignored by some clients). **_Defaults to None_.** + placeholder (str, Optional): Description of the input desired. + Displayed when no text has been input. **_Defaults to None_.** + value (str, Optional): The initial value for this field expressed + in YYYY-MM-DD. **_Defaults to None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + id, + str, + ) + + check_type( + max, + str, + optional=True, + ) + + check_type( + min, + str, + optional=True, + ) + + check_type( + placeholder, + str, + optional=True, + ) + + check_type( + value, + str, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.id = id self.max = max self.min = min self.placeholder = placeholder self.value = value + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=[], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], simple_properties=[ "type", "id", @@ -143,40 +744,226 @@ def __init__( "min", "placeholder", "value", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", ], ) class Time(AdaptiveCardComponent): - """Adaptive Card Time component.""" + """ + **Adaptive Card - Input.Time Element** + + Lets a user select a time. + """ type = "Input.Time" def __init__( self, - id, - max=None, - min=None, - placeholder=None, - value=None, - height=None, - separator=None, - spacing=None, + id: str, + max: str = None, + min: str = None, + placeholder: str = None, + value: str = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): + """ + Initialize a new Input.Time element. + + Args: + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + max (str, Optional): Hint of maximum value expressed in HH:MM (may + be ignored by some clients). **_Defaults to None_.** + min (str, Optional): Hint of minimum value expressed in HH:MM (may + be ignored by some clients). **_Defaults to None_.** + placeholder (str, Optional): Description of the input desired. + Displayed when no text has been input. **_Defaults to None_.** + value (str, Optional): The initial value for this field expressed + in HH:MM. **_Defaults to None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + id, + str, + ) + + check_type( + max, + str, + optional=True, + ) + + check_type( + min, + str, + optional=True, + ) + + check_type( + placeholder, + str, + optional=True, + ) + + check_type( + value, + str, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.id = id self.max = max self.min = min self.placeholder = placeholder self.value = value + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=[], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], simple_properties=[ "id", "type", @@ -184,40 +971,235 @@ def __init__( "min", "placeholder", "value", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", ], ) class Toggle(AdaptiveCardComponent): - """Adaptive Card Toggle component.""" + """ + **Adaptive Card - Input.Toggle Element** + + Lets a user choose between two options. + """ type = "Input.Toggle" def __init__( self, - title, - id, - value=None, - valueOff=None, - valueOn=None, - height=None, - separator=None, - spacing=None, + title: str, + id: str, + value: str = "false", + valueOff: str = "false", + valueOn: str = "true", + wrap: bool = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): + """ + Initialize a new Input.Toggle element. + + Args: + title (str, Mandatory): Title for the toggle. + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + value (str, Optional): The initial selected value. If you want the + toggle to be initially on, set this to the value of valueOn's + value. **_Defaults to false_.** + valueOff (str, Optional): The value when toggle is off. + **_Defaults to false_.** + valueOn (str, Optional): The value when toggle is on. **_Defaults + to true_.** + wrap (bool, Optional): If true, allow text to wrap. Otherwise, + text is clipped. **_Defaults to None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + title, + str, + ) + + check_type( + id, + str, + ) + + check_type( + value, + str, + optional=True, + ) + + check_type( + valueOff, + str, + optional=True, + ) + + check_type( + valueOn, + str, + optional=True, + ) + + check_type( + wrap, + bool, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.title = title self.id = id self.value = value self.valueOff = valueOff self.valueOn = valueOn + self.wrap = wrap + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=[], + serializable_properties=[ + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], simple_properties=[ "type", "id", @@ -225,49 +1207,318 @@ def __init__( "value", "valueOff", "valueOn", + "wrap", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", ], ) -class Choices(AdaptiveCardComponent): - """Adaptive Card Choice Set component.""" +class ChoiceSet(AdaptiveCardComponent): + """ + **Adaptive Card - Input.ChoiceSet Element** + + Allows a user to input a Choice. + """ type = "Input.ChoiceSet" def __init__( self, - choices, - id, - isMultiSelect=None, - style=None, - value=None, - height=None, - separator=None, - spacing=None, + id: str, + choices: list[object] = None, + isMultiSelect: bool = None, + style: OPTIONS.ChoiceInputStyle = None, + value: str = None, + placeholder: str = None, + wrap: bool = None, + errorMessage: str = None, + isRequired: bool = None, + label: str = None, + fallback: object = None, + height: OPTIONS.BlockElementHeight = None, + separator: bool = None, + spacing: OPTIONS.Spacing = None, + isVisible: bool = True, + requires: dict[str, str] = None, ): - self.choices = choices + """ + Initialize a new Input.ChoiceSet element. + + Args: + id (str, Mandatory): Unique identifier for the value. Used to + identify collected input when the Submit action is performed. + choices (list of Choice Element(s), Optional): Choice options. + **_Defaults to None_** Allowed value(s): + Choice + isMtuliSelect (bool, Optional): Allow multiple choices to be + selected. **_Defaults to None._** + style (ChoiceInputStyle, Optional): Style hint for choiceset input. + **_Defaults to None_** Allowed value(s): + ChoiceInputStyle.COMPACT or ChoiceInputStyle.EXPANDED + value (str, Optional): The initial choice (or set of choices) that + should be selected. For multi-select, specify a + comma-separated string of values. **_Defaults to None_.** + placeholder (str, Optional): Description of the input desired. + Only visible when no selection has been made, the style is + compact and isMultiSelect is false. **_Defaults to None_.** + wrap (bool, Optional): If true, allow text to wrap. Otherwise, + text is clipped. **_Defaults to None_.** + errorMessage (str, Optional): Error message to display when + entered input is invalid. **_Defaults to None_.** + isRequired (bool, Optional): Whether or not this input is required. + **_Defaults to None_.** + label (str, Optional): Label for this input. **_Defaults to + None_.** + fallback (Element or str, Optional): Describes what to do when an + unknown element is encountered or the requires of this or any + children can't be met. **_Defaults to None._** Allowed + value(s): + ActionSet, ColumnSet, Container, FactSet, Image, ImageSet, + ChoiceSet, Date, Number, Text, Time, Toggle, Media, + RichTextBlock, TextBlock, or "drop". + Note: "drop" causes this element to be dropped immediately + when unknown elements are encountered. The unknown element + doesn't bubble up any higher. + height (BlockElementHeight, Optional): Specifies the height of the + element. **_Defaults to None._** Allowed value(s): + BlockElementHeight.AUTO or BlockElementHeight.STRETCH + separator (bool, Optional): When true, draw a separating line at + the top of the element. **_Defaults to None._** + spacing (Spacing, Optional): Controls the amount of spacing + between this element and the preceding element. **_Defaults to + None._** Allowed value(s): + Spacing.DEFAULT, Spacing.NONE, Spacing.SMALL, Spacing.MEDIUM, + Spacing.LARGE, Spacing.EXTRA_LARGE, or Spacing.PADDING. + isVisible (bool, Optional): If false, this item will be removed + from the visual tree. **_Defaults to True._** + requires (Dictionary(string), Optional): A series of key/value + pairs indicating features that the item requires with + corresponding minimum version. When a feature is missing or of + insufficient version, fallback is triggered. In the Dictionary, + both key(s) and value(s) should be of str datatype. **_Defaults + to None._** + """ + # Check types + check_type( + id, + str, + ) + + check_type( + choices, + Choice, + optional=True, + is_list=True, + ) + + check_type( + isMultiSelect, + bool, + optional=True, + ) + + validate_input( + style, + OPTIONS.ChoiceInputStyle, + optional=True, + ) + + check_type( + value, + str, + optional=True, + ) + + check_type( + placeholder, + str, + optional=True, + ) + + check_type( + wrap, + bool, + optional=True, + ) + + check_type( + errorMessage, + str, + optional=True, + ) + + check_type( + isRequired, + bool, + optional=True, + ) + + check_type( + label, + str, + optional=True, + ) + + if hasattr(fallback, "to_dict"): + check_type( + fallback, + ( + CONTAINERS.ActionSet, + CONTAINERS.ColumnSet, + CONTAINERS.Container, + CONTAINERS.FactSet, + CARD_ELEMENTS.Image, + CONTAINERS.ImageSet, + ChoiceSet, + Date, + Number, + Text, + Time, + Toggle, + CARD_ELEMENTS.Media, + CARD_ELEMENTS.RichTextBlock, + CARD_ELEMENTS.TextBlock, + ), + optional=True, + ) + else: + validate_input( + fallback, + "drop", + optional=True, + ) + + validate_input( + height, + OPTIONS.BlockElementHeight, + optional=True, + ) + + check_type( + separator, + bool, + optional=True, + ) + + validate_input( + spacing, + OPTIONS.Spacing, + optional=True, + ) + + check_type( + isVisible, + bool, + optional=True, + ) + + validate_dict_str( + requires, + str, + str, + optional=True, + ) + + # Set properties self.id = id + self.choices = choices self.isMultiSelect = isMultiSelect self.style = style self.value = value + self.placeholder = placeholder + self.wrap = wrap + self.errorMessage = errorMessage + self.isRequired = isRequired + self.label = label + self.fallback = fallback self.height = height self.separator = separator self.spacing = spacing + self.isVisible = isVisible + self.requires = requires super().__init__( - serializable_properties=["choices"], - simple_properties=[ + serializable_properties=[ "choices", - "id", + *( + ["fallback"] if hasattr(fallback, "to_dict") else [] + ), + ], + simple_properties=[ "type", + "id", "isMultiSelect", "style", "value", + "placeholder", + "wrap", + "errorMessage", + "isRequired", + "label", + *( + [] if hasattr(fallback, "to_dict") else ["fallback"] + ), "height", "separator", "spacing", + "isVisible", + "requires", + ], + ) + + +class Choice(AdaptiveCardComponent): + """ + **Adaptive Card Choice Component** + + Describes a choice for use in a ChoiceSet. + """ + + def __init__( + self, + title: str, + value: str, + ): + """ + Initialize a new Input.Choice element for the Input.ChoiceSet + element. + + Args: + title (str, Mandatory): Text to display. + value (str, Mandatory): The raw value for the choice. + NOTE: do not use a , in the value, since a ChoiceSet with + isMultiSelect set to true returns a comma-delimited string of + choice values. + """ + # Check types + check_type( + title, + str, + ) + + check_type( + value, + str, + ) + + # Set properties + self.title = title + self.value = value + + super().__init__( + serializable_properties=[], + simple_properties=[ + "title", + "value", ], ) diff --git a/src/webexpythonsdk/models/cards/options.py b/src/webexpythonsdk/models/cards/options.py index db691e8..69ab343 100644 --- a/src/webexpythonsdk/models/cards/options.py +++ b/src/webexpythonsdk/models/cards/options.py @@ -1,4 +1,4 @@ -"""Webex Adaptive Card options. +"""Webex Adaptive Card - Options Model. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -25,11 +25,20 @@ class AbstractOption(Enum): + """ + Abstract base class for options represented as strings. + """ + def __str__(self): + """Return the string representation of the enum value.""" return str(self.value) class FontSize(AbstractOption): + """ + Enumeration for different font sizes. + """ + DEFAULT = "default" SMALL = "small" MEDIUM = "medium" @@ -37,13 +46,30 @@ class FontSize(AbstractOption): EXTRA_LARGE = "extraLarge" +class FontType(AbstractOption): + """ + Enumeration for different font types. + """ + + DEFAULT = "default" + MONOSPACE = "monospace" + + class FontWeight(AbstractOption): + """ + Enumeration for different font weights. + """ + DEFAULT = "default" LIGHTER = "lighter" BOLDER = "bolder" class Colors(AbstractOption): + """ + Enumeration for different color options. + """ + DEFAULT = "default" DARK = "dark" LIGHT = "light" @@ -54,23 +80,39 @@ class Colors(AbstractOption): class BlockElementHeight(AbstractOption): + """ + Enumeration for different block element height options. + """ + AUTO = "auto" - STRETCH = "auto" + STRETCH = "stretch" class VerticalContentAlignment(AbstractOption): + """ + Enumeration for vertical content alignment options. + """ + TOP = "top" CENTER = "center" BOTTOM = "bottom" class HorizontalAlignment(AbstractOption): + """ + Enumeration for different horizontal alignment options. + """ + LEFT = "left" CENTER = "center" RIGHT = "right" class Spacing(AbstractOption): + """ + Enumeration for different spacing options. + """ + DEFAULT = "default" NONE = "none" SMALL = "small" @@ -81,6 +123,10 @@ class Spacing(AbstractOption): class ImageSize(AbstractOption): + """ + Enumeration for different image sizes. + """ + AUTO = "auto" STRETCH = "stretch" SMALL = "small" @@ -89,16 +135,32 @@ class ImageSize(AbstractOption): class ImageStyle(AbstractOption): + """ + Enumeration for different image styles. + """ + DEFAULT = "default" PERSON = "person" class ContainerStyle(AbstractOption): + """ + Enumeration for different container styles. + """ + DEFAULT = "default" EMPHASIS = "emphasis" + GOOD = "good" + ATTENTION = "attention" + WARNING = "warning" + ACCENT = "accent" class TextInputStyle(AbstractOption): + """ + Enumeration for different text input styles. + """ + TEXT = "text" TEL = "tel" URL = "url" @@ -106,5 +168,39 @@ class TextInputStyle(AbstractOption): class ChoiceInputStyle(AbstractOption): + """ + Enumeration for different choice input styles. + """ + COMPACT = "compact" EXPANDED = "expanded" + + +class ActionStyle(AbstractOption): + """ + Enumeration for different action stlyes. + """ + + DEFAULT = "default" + POSITIVE = "positive" + DESTRUCTIVE = "destructive" + + +class AssociatedInputs(AbstractOption): + """ + Enumeration for different associated input options. + """ + + AUTO = "auto" + NONE = "none" + + +class ImageFillMode(AbstractOption): + """ + Enumeration for different image fill modes. + """ + + COVER = "cover" + REPEAT_HORIZONTALLY = "repeatHorizontally" + REPEAT_VERTICALLY = "repeatVertically" + REPEAT = "repeat" diff --git a/src/webexpythonsdk/models/cards/types.py b/src/webexpythonsdk/models/cards/types.py new file mode 100644 index 0000000..8b775c2 --- /dev/null +++ b/src/webexpythonsdk/models/cards/types.py @@ -0,0 +1,108 @@ +"""Webex Adaptive Card - Types Model. + +Copyright (c) 2016-2024 Cisco and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from webexpythonsdk.models.cards.adaptive_card_component import ( + AdaptiveCardComponent, +) +import webexpythonsdk.models.cards.options as OPTIONS +from webexpythonsdk.models.cards.utils import ( + validate_input, + validate_uri, +) + + +class BackgroundImage(AdaptiveCardComponent): + """ + **Adaptive Card - Background Image Element** + + Specifies a background image. Acceptable formats are PNG, JPEG, and GIF. + """ + + def __init__( + self, + url: object, + fillMode: OPTIONS.ImageFillMode = None, + horizontalAlignment: OPTIONS.HorizontalAlignment = None, + verticalAlignment: OPTIONS.VerticalContentAlignment = None, + ): + """ + Initialize a new BackgroundImage element. + + Args: + url (uri, Mandatory): The URL (or data url) of the image. + Acceptable formats are PNG, JPEG, and GIF. Allowed value(s): + uri + fillMode (ImageFillMode, Optional): Describes how the image should + fill the area. **_Defaults to None._** Allowed value(s): + ImageFillMode.COVER, ImageFillMode.REPEAT_HORIZONTALLY, + ImageFillMode.REPEAT_VERTICALLY, or ImageFillMode.REPEAT + horizontalAlignment (HorizontalAlignment, Optional): Describes how + the image should be aligned if it must be cropped or if using + repeat fill mode. **_Defaults to None._** Allowed value(s): + HorizontalAlignment.LEFT, HorizontalAlignment.CENTER, or + HorizontalAlignment.RIGHT + verticalAlignment (VerticalContentAlignment, Optional): Describes + how the image should be aligned if it must be cropped or if + using repeat fill mode. **_Defaults to None._** Allowed + value(s): + VerticalContentAlignment.TOP, VerticalContentAlignment.CENTER, + or VerticalContentAlignment.BOTTOM + """ + # Check types + validate_uri( + url, + ) + + validate_input( + fillMode, + OPTIONS.ImageFillMode, + optional=True, + ) + + validate_input( + horizontalAlignment, + OPTIONS.HorizontalAlignment, + optional=True, + ) + + validate_input( + verticalAlignment, + OPTIONS.VerticalContentAlignment, + optional=True, + ) + + # Set properties + self.url = url + self.fillMode = fillMode + self.horizontalAlignment = horizontalAlignment + self.verticalAlignment = verticalAlignment + + super().__init__( + serializable_properties=[], + simple_properties=[ + "url", + "fillMode", + "horizontalAlignment", + "verticalAlignment", + ], + ) diff --git a/src/webexpythonsdk/models/cards/utils.py b/src/webexpythonsdk/models/cards/utils.py index 52c463a..2b850fc 100644 --- a/src/webexpythonsdk/models/cards/utils.py +++ b/src/webexpythonsdk/models/cards/utils.py @@ -1,4 +1,4 @@ -"""Webex Access-Tokens API wrapper. +"""Webex Adaptive Card - Utilities Model. Copyright (c) 2016-2024 Cisco and/or its affiliates. @@ -21,14 +21,19 @@ SOFTWARE. """ +from enum import Enum +from typing import Any, Type +from urllib.parse import urlparse -def set_if_not_none(property_name, property, export): - if property is not None: - export[property_name] = property.to_dict() - -def check_type(obj, acceptable_types, optional=False, is_list=False): - """Object is an instance of one of the acceptable types or None. +def check_type( + obj: object, + acceptable_types: Any, + optional: bool = False, + is_list: bool = False, + ): + """ + Object is an instance of one of the acceptable types or None. Args: obj: The object to be inspected. @@ -52,15 +57,10 @@ def check_type(obj, acceptable_types, optional=False, is_list=False): if not isinstance(obj, list): error_message = ( "We were expecting to receive a list of objects of the " - "following types: {types}{none}; instead we received {o} " - "which is a {o_type}.".format( - types=", ".join( - [repr(t.__name__) for t in acceptable_types] - ), - none="or None" if optional else "", - o=obj, - o_type=repr(type(obj).__name__), - ) + "following types: " + f"{', '.join([repr(t.__name__) for t in acceptable_types])}" + f"{' or \'None\'' if optional else ''}; instead we received " + f"{obj} which is a {repr(type(obj).__name__)}." ) raise TypeError(error_message) @@ -68,15 +68,10 @@ def check_type(obj, acceptable_types, optional=False, is_list=False): if not isinstance(o, acceptable_types): error_message = ( "We were expecting to receive an object of one of the " - "following types: {types}{none}; but instead we received " - "{o} which is a {o_type}.".format( - types=", ".join( - [repr(t.__name__) for t in acceptable_types] - ), - none="or None" if optional else "", - o=o, - o_type=repr(type(o).__name__), - ) + "following types: " + f"{', '.join(repr(t.__name__) for t in acceptable_types)}" + f"{' or \'None\'' if optional else ''}; instead we " + f"received {o} which is a {repr(type(o).__name__)}." ) raise TypeError(error_message) return @@ -86,12 +81,156 @@ def check_type(obj, acceptable_types, optional=False, is_list=False): else: error_message = ( "We were expecting to receive an instance of one of the following " - "types: {types}{none}; but instead we received {o} which is a " - "{o_type}.".format( - types=", ".join([repr(t.__name__) for t in acceptable_types]), - none="or 'None'" if optional else "", - o=obj, - o_type=repr(type(obj).__name__), - ) + f"types: {', '.join(repr(t.__name__) for t in acceptable_types)}" + f"{' or \'None\'' if optional else ''}; but instead we received " + f"{obj} which is a {repr(type(obj).__name__)}." ) + raise TypeError(error_message) + + +def validate_input( + input_value: Any, + allowed_values: Any, + optional: bool = False, + ): + """ + Validate if the input value is in the tuple of allowed values. + + Args: + input_value: The value to be validated. + allowed_values (str | tuple | Enum): A string, a tuple of allowed + values, or an Enum subclass. + optional (bool): Whether or not the object may be None. + + Raises: + ValueError: If the value is not in the allowed values. + TypeError: If allowed_values is neither a string, a tuple, nor an Enum + subclass. + """ + # Return if the argument is optional and if the input is None + if optional and input_value is None: + return + + # If allowed_values is an Enum subclass, get its members' values as a tuple + if isinstance(allowed_values, type) and issubclass(allowed_values, Enum): + expected_values = tuple( + f"{item.__class__.__name__}.{item.name}" for item in allowed_values + ) + allowed_values = tuple( + item.value for item in allowed_values + ) + + # Convert a single string to a tuple of one string + if isinstance(allowed_values, str): + allowed_values = (allowed_values,) + expected_values = allowed_values + + # Ensure allowed_values is a tuple + if not isinstance(allowed_values, tuple): + raise TypeError( + "allowed_values must be a string, a tuple, or an Enum subclass." + ) + + # Determine the value to check based on its type + value_to_check = ( + input_value.value if isinstance(input_value, Enum) else input_value + ) + + # Check if the value is in the tuple of allowed values + if value_to_check not in allowed_values: + raise ValueError( + f"Invalid value: '{input_value}'. " + f"Must be one of {expected_values}." + ) + + return + + +def validate_dict_str( + input_value: Any, + key_type: Type, + value_type: Type, + optional: bool = False, + ): + """ + Validate that the input is a dictionary and that all keys and values in the + dictionary are of the specified types. + + Args: + input_value (Any): The input to validate. + key_type (Type): The expected type for the dictionary keys. + value_type (Type): The expected type for the dictionary values. + optional(bool): Whether or not the object may be None. + + Raises: + TypeError: If the input is not a dictionary or any key or value in the + dictionary does not match the specified types, with details about + the non-conforming elements. + """ + if optional and input_value is None: + return + + if not isinstance(input_value, dict): + raise TypeError(f"'{input_value}' is not of type 'dict'") + + errors = [] + + for key, value in input_value.items(): + if not isinstance(key, key_type): + errors.append( + f"Key '{key}' of type '{type(key).__name__}' " + f"is not of type '{key_type.__name__}'." + ) + if not isinstance(value, value_type): + errors.append( + f"Value '{value}' of type '{type(value).__name__}' " + f"is not of type '{value_type.__name__}'." + ) + + if errors: + raise TypeError("\n".join(errors)) + + return + + +class URIException(Exception): + """ + Custom exception for invalid URIs. + """ + + +def validate_uri( + uri: Any, + optional=False, + ): + """ + Validate the given URI and raise an exception if it is invalid. + + Args: + uri (str): The URI to validate. + optional(bool): Whether or not the object may be None. + + Raises: + TypeError: If the input is not a string. + URIException: If the URI is invalid. + """ + if optional and uri is None: + return + + if not isinstance(uri, str): + raise TypeError(f"'{uri}' is not of type 'str'") + + # First validate using urlparse + parsed_uri = urlparse(uri) + + # Check if the URI has a scheme + if not parsed_uri.scheme: + raise URIException("Invalid URI: Missing scheme") + + # Check if the URI has a heir-part location + if not parsed_uri.netloc: + raise URIException("Invalid URI: Missing heir part location") + + # Return if every check is passed + return