From 77f7d79f6b8c6c1e733b306cc01f29db4b299d2a Mon Sep 17 00:00:00 2001 From: DX-Bandwidth Date: Tue, 20 May 2025 14:06:11 +0000 Subject: [PATCH 1/2] Generate SDK with OpenAPI Generator Version --- .openapi-generator/FILES | 2 + README.md | 1 + bandwidth.yml | 36 +++-- bandwidth/__init__.py | 1 + bandwidth/models/__init__.py | 1 + bandwidth/models/blocked_webhook.py | 123 ++++++++++++++++++ bandwidth/models/tfv_submission_info.py | 6 +- bandwidth/models/verification_request.py | 6 +- .../models/verification_update_request.py | 6 +- docs/BlockedWebhook.md | 34 +++++ 10 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 bandwidth/models/blocked_webhook.py create mode 100644 docs/BlockedWebhook.md diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index f013b950..ff6de818 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -23,6 +23,7 @@ bandwidth/models/account_statistics.py bandwidth/models/additional_denial_reason.py bandwidth/models/address.py bandwidth/models/answer_callback.py +bandwidth/models/blocked_webhook.py bandwidth/models/bridge_complete_callback.py bandwidth/models/bridge_target_complete_callback.py bandwidth/models/call_direction_enum.py @@ -169,6 +170,7 @@ docs/AccountStatistics.md docs/AdditionalDenialReason.md docs/Address.md docs/AnswerCallback.md +docs/BlockedWebhook.md docs/BridgeCompleteCallback.md docs/BridgeTargetCompleteCallback.md docs/CallDirectionEnum.md diff --git a/README.md b/README.md index 2cd27437..5d623508 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ Class | Method | HTTP request | Description - [AdditionalDenialReason](docs/AdditionalDenialReason.md) - [Address](docs/Address.md) - [AnswerCallback](docs/AnswerCallback.md) + - [BlockedWebhook](docs/BlockedWebhook.md) - [BridgeCompleteCallback](docs/BridgeCompleteCallback.md) - [BridgeTargetCompleteCallback](docs/BridgeTargetCompleteCallback.md) - [CallDirectionEnum](docs/CallDirectionEnum.md) diff --git a/bandwidth.yml b/bandwidth.yml index e180a94b..89d94888 100644 --- a/bandwidth.yml +++ b/bandwidth.yml @@ -5253,17 +5253,17 @@ components: description: >- The Toll-Free Verification request privacy policy URL. (Not Available Until 5/28/2025) - example: http://your-company.com/privacyPolicyUrl.pdf + example: http://your-company.com/privacyPolicy type: string termsAndConditionsUrl: description: >- The Toll-Free Verification request terms and conditions policy URL. (Not Available Until 5/28/2025) - example: http://your-company.com/termsAndConditionsUrl.pdf + example: http://your-company.com/termsAndConditions type: string - businessDBA: + businessDba: description: The company 'Doing Business As'. (Not Available Until 5/28/2025) - example: SecondCompany Name + example: Another Company Name Inc. type: string additionalDenialReason: properties: @@ -5349,8 +5349,8 @@ components: $ref: '#/components/schemas/privacyPolicyUrl' termsAndConditionsUrl: $ref: '#/components/schemas/termsAndConditionsUrl' - businessDBA: - $ref: '#/components/schemas/businessDBA' + businessDba: + $ref: '#/components/schemas/businessDba' verificationUpdateRequest: type: object required: @@ -5388,8 +5388,8 @@ components: $ref: '#/components/schemas/privacyPolicyUrl' termsAndConditionsUrl: $ref: '#/components/schemas/termsAndConditionsUrl' - businessDBA: - $ref: '#/components/schemas/businessDBA' + businessDba: + $ref: '#/components/schemas/businessDba' tfvBasicAuthentication: type: object properties: @@ -5483,6 +5483,21 @@ components: $ref: '#/components/schemas/tfvCallbackStatusEnum' internalTicketNumber: $ref: '#/components/schemas/internalTicketNumberForWebhook' + blockedWebhook: + type: object + properties: + accountId: + $ref: '#/components/schemas/accountId1' + phoneNumber: + $ref: '#/components/schemas/tfPhoneNumber' + status: + $ref: '#/components/schemas/tfvCallbackStatusEnum' + internalTicketNumber: + $ref: '#/components/schemas/internalTicketNumberForWebhook' + blocked: + $ref: '#/components/schemas/blocked' + blockedReason: + $ref: '#/components/schemas/blockedReason' tfvSubmissionWrapper: type: object properties: @@ -5849,8 +5864,8 @@ components: $ref: '#/components/schemas/privacyPolicyUrl' termsAndConditionsUrl: $ref: '#/components/schemas/termsAndConditionsUrl' - businessDBA: - $ref: '#/components/schemas/businessDBA' + businessDba: + $ref: '#/components/schemas/businessDba' tfvStatusEnum: type: string enum: @@ -7468,6 +7483,7 @@ components: - $ref: '#/components/schemas/verificationWebhook' - $ref: '#/components/schemas/verificationDenialWebhook' - $ref: '#/components/schemas/failureWebhook' + - $ref: '#/components/schemas/blockedWebhook' webhookSubscriptionRequest: description: >- Information about a webhook that Bandwidth should send upon the diff --git a/bandwidth/__init__.py b/bandwidth/__init__.py index 3cfa826e..104043fb 100644 --- a/bandwidth/__init__.py +++ b/bandwidth/__init__.py @@ -46,6 +46,7 @@ from bandwidth.models.additional_denial_reason import AdditionalDenialReason from bandwidth.models.address import Address from bandwidth.models.answer_callback import AnswerCallback +from bandwidth.models.blocked_webhook import BlockedWebhook from bandwidth.models.bridge_complete_callback import BridgeCompleteCallback from bandwidth.models.bridge_target_complete_callback import BridgeTargetCompleteCallback from bandwidth.models.call_direction_enum import CallDirectionEnum diff --git a/bandwidth/models/__init__.py b/bandwidth/models/__init__.py index ef4ea3a1..4d66be19 100644 --- a/bandwidth/models/__init__.py +++ b/bandwidth/models/__init__.py @@ -19,6 +19,7 @@ from bandwidth.models.additional_denial_reason import AdditionalDenialReason from bandwidth.models.address import Address from bandwidth.models.answer_callback import AnswerCallback +from bandwidth.models.blocked_webhook import BlockedWebhook from bandwidth.models.bridge_complete_callback import BridgeCompleteCallback from bandwidth.models.bridge_target_complete_callback import BridgeTargetCompleteCallback from bandwidth.models.call_direction_enum import CallDirectionEnum diff --git a/bandwidth/models/blocked_webhook.py b/bandwidth/models/blocked_webhook.py new file mode 100644 index 00000000..d5d1473b --- /dev/null +++ b/bandwidth/models/blocked_webhook.py @@ -0,0 +1,123 @@ +# coding: utf-8 + +""" + Bandwidth + + Bandwidth's Communication APIs + + The version of the OpenAPI document: 1.0.0 + Contact: letstalk@bandwidth.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from bandwidth.models.tfv_callback_status_enum import TfvCallbackStatusEnum +from typing import Optional, Set +from typing_extensions import Self + +class BlockedWebhook(BaseModel): + """ + BlockedWebhook + """ # noqa: E501 + account_id: Optional[StrictStr] = Field(default=None, description="User's account ID.", alias="accountId") + phone_number: Optional[Annotated[str, Field(min_length=12, strict=True, max_length=12)]] = Field(default=None, description="Toll-free telephone number in E.164 format.", alias="phoneNumber") + status: Optional[TfvCallbackStatusEnum] = None + internal_ticket_number: Optional[StrictStr] = Field(default=None, description="Unique identifier (UUID) generated by Bandwidth to assist in tracking the verification status of a toll-free number.", alias="internalTicketNumber") + blocked: Optional[StrictBool] = Field(default=None, description="Whether a Toll-Free Verification is blocked. This attribute will only be defined when the number is blocked. (Not Available Until 5/28/2025)") + blocked_reason: Optional[StrictStr] = Field(default=None, description="The reason why the Toll-Free Verification is blocked. This attribute will only be defined when the number is blocked. (Not Available Until 5/28/2025)", alias="blockedReason") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["accountId", "phoneNumber", "status", "internalTicketNumber", "blocked", "blockedReason"] + + @field_validator('phone_number') + def phone_number_validate_regular_expression(cls, value): + """Validates the regular expression""" + if value is None: + return value + + if not re.match(r"^\+1(800|833|844|855|866|877|888)[2-9]\d{6}$", value): + raise ValueError(r"must validate the regular expression /^\+1(800|833|844|855|866|877|888)[2-9]\d{6}$/") + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BlockedWebhook from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BlockedWebhook from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "accountId": obj.get("accountId"), + "phoneNumber": obj.get("phoneNumber"), + "status": obj.get("status"), + "internalTicketNumber": obj.get("internalTicketNumber"), + "blocked": obj.get("blocked"), + "blockedReason": obj.get("blockedReason") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/bandwidth/models/tfv_submission_info.py b/bandwidth/models/tfv_submission_info.py index 03c475bb..876893b2 100644 --- a/bandwidth/models/tfv_submission_info.py +++ b/bandwidth/models/tfv_submission_info.py @@ -42,9 +42,9 @@ class TfvSubmissionInfo(BaseModel): isv_reseller: Optional[Annotated[str, Field(min_length=0, strict=True, max_length=500)]] = Field(default=None, description="ISV name.", alias="isvReseller") privacy_policy_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request privacy policy URL. (Not Available Until 5/28/2025)", alias="privacyPolicyUrl") terms_and_conditions_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request terms and conditions policy URL. (Not Available Until 5/28/2025)", alias="termsAndConditionsUrl") - business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDBA") + business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDba") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDBA"] + __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDba"] model_config = ConfigDict( populate_by_name=True, @@ -134,7 +134,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "isvReseller": obj.get("isvReseller"), "privacyPolicyUrl": obj.get("privacyPolicyUrl"), "termsAndConditionsUrl": obj.get("termsAndConditionsUrl"), - "businessDBA": obj.get("businessDBA") + "businessDba": obj.get("businessDba") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/bandwidth/models/verification_request.py b/bandwidth/models/verification_request.py index 28598544..03e6951c 100644 --- a/bandwidth/models/verification_request.py +++ b/bandwidth/models/verification_request.py @@ -43,9 +43,9 @@ class VerificationRequest(BaseModel): isv_reseller: Optional[Annotated[str, Field(min_length=0, strict=True, max_length=500)]] = Field(default=None, description="ISV name.", alias="isvReseller") privacy_policy_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request privacy policy URL. (Not Available Until 5/28/2025)", alias="privacyPolicyUrl") terms_and_conditions_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request terms and conditions policy URL. (Not Available Until 5/28/2025)", alias="termsAndConditionsUrl") - business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDBA") + business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDba") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "phoneNumbers", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDBA"] + __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "phoneNumbers", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDba"] model_config = ConfigDict( populate_by_name=True, @@ -136,7 +136,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "isvReseller": obj.get("isvReseller"), "privacyPolicyUrl": obj.get("privacyPolicyUrl"), "termsAndConditionsUrl": obj.get("termsAndConditionsUrl"), - "businessDBA": obj.get("businessDBA") + "businessDba": obj.get("businessDba") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/bandwidth/models/verification_update_request.py b/bandwidth/models/verification_update_request.py index 5ecc84c4..fddb0501 100644 --- a/bandwidth/models/verification_update_request.py +++ b/bandwidth/models/verification_update_request.py @@ -42,9 +42,9 @@ class VerificationUpdateRequest(BaseModel): isv_reseller: Optional[Annotated[str, Field(min_length=0, strict=True, max_length=500)]] = Field(default=None, description="ISV name.", alias="isvReseller") privacy_policy_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request privacy policy URL. (Not Available Until 5/28/2025)", alias="privacyPolicyUrl") terms_and_conditions_url: Optional[StrictStr] = Field(default=None, description="The Toll-Free Verification request terms and conditions policy URL. (Not Available Until 5/28/2025)", alias="termsAndConditionsUrl") - business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDBA") + business_dba: Optional[StrictStr] = Field(default=None, description="The company 'Doing Business As'. (Not Available Until 5/28/2025)", alias="businessDba") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDBA"] + __properties: ClassVar[List[str]] = ["businessAddress", "businessContact", "messageVolume", "useCase", "useCaseSummary", "productionMessageContent", "optInWorkflow", "additionalInformation", "isvReseller", "privacyPolicyUrl", "termsAndConditionsUrl", "businessDba"] model_config = ConfigDict( populate_by_name=True, @@ -134,7 +134,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "isvReseller": obj.get("isvReseller"), "privacyPolicyUrl": obj.get("privacyPolicyUrl"), "termsAndConditionsUrl": obj.get("termsAndConditionsUrl"), - "businessDBA": obj.get("businessDBA") + "businessDba": obj.get("businessDba") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/docs/BlockedWebhook.md b/docs/BlockedWebhook.md new file mode 100644 index 00000000..38243edd --- /dev/null +++ b/docs/BlockedWebhook.md @@ -0,0 +1,34 @@ +# BlockedWebhook + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**account_id** | **str** | User's account ID. | [optional] +**phone_number** | **str** | Toll-free telephone number in E.164 format. | [optional] +**status** | [**TfvCallbackStatusEnum**](TfvCallbackStatusEnum.md) | | [optional] +**internal_ticket_number** | **str** | Unique identifier (UUID) generated by Bandwidth to assist in tracking the verification status of a toll-free number. | [optional] +**blocked** | **bool** | Whether a Toll-Free Verification is blocked. This attribute will only be defined when the number is blocked. (Not Available Until 5/28/2025) | [optional] +**blocked_reason** | **str** | The reason why the Toll-Free Verification is blocked. This attribute will only be defined when the number is blocked. (Not Available Until 5/28/2025) | [optional] + +## Example + +```python +from bandwidth.models.blocked_webhook import BlockedWebhook + +# TODO update the JSON string below +json = "{}" +# create an instance of BlockedWebhook from a JSON string +blocked_webhook_instance = BlockedWebhook.from_json(json) +# print the JSON string representation of the object +print(BlockedWebhook.to_json()) + +# convert the object into a dict +blocked_webhook_dict = blocked_webhook_instance.to_dict() +# create an instance of BlockedWebhook from a dict +blocked_webhook_from_dict = BlockedWebhook.from_dict(blocked_webhook_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + From 45f1e3db57cf1b03d1c73c67c249e5e32e290f45 Mon Sep 17 00:00:00 2001 From: ckoegel Date: Tue, 20 May 2025 14:17:56 -0400 Subject: [PATCH 2/2] blocked webhook tests --- test/unit/models/test_blocked_webhook.py | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/unit/models/test_blocked_webhook.py diff --git a/test/unit/models/test_blocked_webhook.py b/test/unit/models/test_blocked_webhook.py new file mode 100644 index 00000000..6685f921 --- /dev/null +++ b/test/unit/models/test_blocked_webhook.py @@ -0,0 +1,62 @@ +# coding: utf-8 + +""" + Bandwidth + + Bandwidth's Communication APIs + + The version of the OpenAPI document: 1.0.0 + Contact: letstalk@bandwidth.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from bandwidth.models.blocked_webhook import BlockedWebhook + +class TestBlockedWebhook(unittest.TestCase): + """BlockedWebhook unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> BlockedWebhook: + """Test BlockedWebhook + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + + model = BlockedWebhook() + if include_optional: + return BlockedWebhook( + account_id = '1234567', + phone_number = '+18005555555', + status = 'VERIFIED', + internal_ticket_number = 'acde070d-8c4c-4f0d-9d8a-162843c10333', + blocked = True, + blocked_reason = 'Toll-free number was used to send spam messages' + ) + else: + return BlockedWebhook( + ) + + def testBlockedWebhook(self): + """Test BlockedWebhook""" + instance = self.make_instance(True) + assert instance is not None + assert isinstance(instance, BlockedWebhook) + assert instance.account_id == '1234567' + assert instance.phone_number == '+18005555555' + assert instance.status == 'VERIFIED' + assert instance.internal_ticket_number == 'acde070d-8c4c-4f0d-9d8a-162843c10333' + assert instance.blocked == True + assert instance.blocked_reason == 'Toll-free number was used to send spam messages' + +if __name__ == '__main__': + unittest.main()