Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/devo_global_comms_python/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

from . import __version__
from .auth import APIKeyAuth
from .exceptions import DevoAPIException, DevoAuthenticationException, DevoException, DevoMissingAPIKeyException
from .resources.contacts import ContactsResource
Expand Down Expand Up @@ -143,7 +144,7 @@ def request(

# Prepare headers
request_headers = {
"User-Agent": f"devo-python/{self.__class__.__module__.split('.')[0]}",
"User-Agent": f"devo-python-sdk/{__version__}",
"Accept": "application/json",
}
if headers:
Expand Down
4 changes: 2 additions & 2 deletions src/devo_global_comms_python/models/sms.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def __init__(self, data: List[Dict] = None, **kwargs):
"""Custom constructor to handle direct array response."""
if data is not None and isinstance(data, list):
# Convert list of dicts to list of AvailableNumber objects
numbers = [AvailableNumber.parse_obj(item) for item in data]
numbers = [AvailableNumber.model_validate(item) for item in data]
super().__init__(numbers=numbers, **kwargs)
else:
super().__init__(**kwargs)
Expand All @@ -222,7 +222,7 @@ def __init__(self, data: List[Dict] = None, **kwargs):
@classmethod
def parse_from_list(cls, data: List[Dict]) -> "AvailableNumbersResponse":
"""Parse from direct array response."""
numbers = [AvailableNumber.parse_obj(item) for item in data]
numbers = [AvailableNumber.model_validate(item) for item in data]
return cls(numbers=numbers)


Expand Down
14 changes: 7 additions & 7 deletions src/devo_global_comms_python/resources/contacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def list(

from ..models.contacts import GetContactsSerializer

return GetContactsSerializer.parse_obj(response.json())
return GetContactsSerializer.model_validate(response.json())

def create(self, contact_data: "CreateContactDto") -> "ContactSerializer":
"""
Expand All @@ -113,7 +113,7 @@ def create(self, contact_data: "CreateContactDto") -> "ContactSerializer":

from ..models.contacts import ContactSerializer

return ContactSerializer.parse_obj(response.json())
return ContactSerializer.model_validate(response.json())

def update(self, contact_id: str, contact_data: "UpdateContactDto") -> "ContactSerializer":
"""
Expand All @@ -132,7 +132,7 @@ def update(self, contact_id: str, contact_data: "UpdateContactDto") -> "ContactS

from ..models.contacts import ContactSerializer

return ContactSerializer.parse_obj(response.json())
return ContactSerializer.model_validate(response.json())

def delete_bulk(self, delete_data: "DeleteContactsDto", approve: Optional[str] = None) -> "ContactSerializer":
"""
Expand All @@ -153,7 +153,7 @@ def delete_bulk(self, delete_data: "DeleteContactsDto", approve: Optional[str] =

from ..models.contacts import ContactSerializer

return ContactSerializer.parse_obj(response.json())
return ContactSerializer.model_validate(response.json())

# Contact Group Management

Expand Down Expand Up @@ -198,7 +198,7 @@ def import_from_csv(

from ..models.contacts import CreateContactsFromCsvRespDto

return CreateContactsFromCsvRespDto.parse_obj(response.json())
return CreateContactsFromCsvRespDto.model_validate(response.json())

# Custom Fields Management

Expand Down Expand Up @@ -232,7 +232,7 @@ def list_custom_fields(

from ..models.contacts import GetCustomFieldsSerializer

return GetCustomFieldsSerializer.parse_obj(response.json())
return GetCustomFieldsSerializer.model_validate(response.json())

def create_custom_field(self, field_data: "CreateCustomFieldDto") -> "CustomFieldSerializer":
"""
Expand All @@ -248,7 +248,7 @@ def create_custom_field(self, field_data: "CreateCustomFieldDto") -> "CustomFiel

from ..models.contacts import CustomFieldSerializer

return CustomFieldSerializer.parse_obj(response.json())
return CustomFieldSerializer.model_validate(response.json())

def update_custom_field(self, field_id: str, field_data: "UpdateCustomFieldDto") -> None:
"""
Expand Down
152 changes: 2 additions & 150 deletions src/devo_global_comms_python/resources/email.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from typing import TYPE_CHECKING

from ..utils import validate_email, validate_required_string
from .base import BaseResource

if TYPE_CHECKING:
from ..models.email import EmailMessage, EmailSendResponse
from ..models.email import EmailSendResponse


class EmailResource(BaseResource):
Expand Down Expand Up @@ -60,151 +60,3 @@ def send_email(
from ..models.email import EmailSendResponse

return EmailSendResponse.model_validate(response.json())

def send(
self,
to: str,
subject: str,
body: str,
from_: Optional[str] = None,
html_body: Optional[str] = None,
cc: Optional[List[str]] = None,
bcc: Optional[List[str]] = None,
attachments: Optional[List[Dict[str, Any]]] = None,
reply_to: Optional[str] = None,
callback_url: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
) -> "EmailMessage":
"""
Send an email message.

Args:
to: The recipient's email address
subject: The email subject
body: The plain text email body
from_: The sender's email address (optional, uses account default)
html_body: The HTML email body (optional)
cc: List of CC email addresses (optional)
bcc: List of BCC email addresses (optional)
attachments: List of attachment objects (optional)
reply_to: Reply-to email address (optional)
callback_url: Webhook URL for delivery status (optional)
metadata: Custom metadata dictionary (optional)

Returns:
EmailMessage: The sent message details
"""
# Validate inputs
to = validate_email(to)
subject = validate_required_string(subject, "subject")
body = validate_required_string(body, "body")

if from_:
from_ = validate_email(from_)
if reply_to:
reply_to = validate_email(reply_to)
if cc:
cc = [validate_email(email) for email in cc]
if bcc:
bcc = [validate_email(email) for email in bcc]

# Prepare request data
data = {
"to": to,
"subject": subject,
"body": body,
}

if from_:
data["from"] = from_
if html_body:
data["html_body"] = html_body
if cc:
data["cc"] = cc
if bcc:
data["bcc"] = bcc
if attachments:
data["attachments"] = attachments
if reply_to:
data["reply_to"] = reply_to
if callback_url:
data["callback_url"] = callback_url
if metadata:
data["metadata"] = metadata

# Send request
response = self.client.post("email/messages", json=data)

from ..models.email import EmailMessage

return EmailMessage.parse_obj(response.json())

def get(self, message_id: str) -> "EmailMessage":
"""
Retrieve an email message by ID.

Args:
message_id: The message ID

Returns:
EmailMessage: The message details
"""
message_id = validate_required_string(message_id, "message_id")

response = self.client.get(f"email/messages/{message_id}")

from ..models.email import EmailMessage

return EmailMessage.parse_obj(response.json())

def list(
self,
to: Optional[str] = None,
from_: Optional[str] = None,
subject: Optional[str] = None,
date_sent_after: Optional[str] = None,
date_sent_before: Optional[str] = None,
status: Optional[str] = None,
limit: int = 50,
offset: int = 0,
) -> List["EmailMessage"]:
"""
List email messages with optional filtering.

Args:
to: Filter by recipient email address
from_: Filter by sender email address
subject: Filter by subject (partial match)
date_sent_after: Filter messages sent after this date
date_sent_before: Filter messages sent before this date
status: Filter by message status
limit: Maximum number of messages to return (default: 50)
offset: Number of messages to skip (default: 0)

Returns:
List[EmailMessage]: List of messages
"""
params = {
"limit": limit,
"offset": offset,
}

if to:
params["to"] = validate_email(to)
if from_:
params["from"] = validate_email(from_)
if subject:
params["subject"] = subject
if date_sent_after:
params["date_sent_after"] = date_sent_after
if date_sent_before:
params["date_sent_before"] = date_sent_before
if status:
params["status"] = status

response = self.client.get("email/messages", params=params)
data = response.json()

from ..models.email import EmailMessage

return [EmailMessage.parse_obj(item) for item in data.get("messages", [])]
6 changes: 3 additions & 3 deletions src/devo_global_comms_python/resources/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def get(self, message_id: str) -> "Message":

from ..models.messages import Message

return Message.parse_obj(response.json())
return Message.model_validate(response.json())

def list(
self,
Expand Down Expand Up @@ -142,7 +142,7 @@ def list(

from ..models.messages import Message

return [Message.parse_obj(item) for item in data.get("messages", [])]
return [Message.model_validate(item) for item in data.get("messages", [])]

def get_delivery_status(self, message_id: str) -> Dict[str, Any]:
"""
Expand Down Expand Up @@ -173,4 +173,4 @@ def resend(self, message_id: str) -> "Message":

from ..models.messages import Message

return Message.parse_obj(response.json())
return Message.model_validate(response.json())
14 changes: 7 additions & 7 deletions src/devo_global_comms_python/resources/rcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def create_account(self, account_data: Dict[str, Any]) -> "RcsAccountSerializer"

from ..models.rcs import RcsAccountSerializer

return RcsAccountSerializer.parse_obj(response.json())
return RcsAccountSerializer.model_validate(response.json())

def get_accounts(
self,
Expand Down Expand Up @@ -65,7 +65,7 @@ def verify_account(self, verification_data: Dict[str, Any]) -> "SuccessSerialize

from ..models.rcs import SuccessSerializer

return SuccessSerializer.parse_obj(response.json())
return SuccessSerializer.model_validate(response.json())

def update_account(self, account_id: str, account_data: Dict[str, Any]) -> Dict[str, Any]:
"""Update RCS Account."""
Expand All @@ -86,7 +86,7 @@ def send_message(self, message_data: Dict[str, Any]) -> "RcsSendMessageSerialize

from ..models.rcs import RcsSendMessageSerializer

return RcsSendMessageSerializer.parse_obj(response.json())
return RcsSendMessageSerializer.model_validate(response.json())

def list_messages(
self,
Expand All @@ -113,7 +113,7 @@ def list_messages(

from ..models.rcs import RcsSendMessageSerializer

return [RcsSendMessageSerializer.parse_obj(message) for message in response.json()]
return [RcsSendMessageSerializer.model_validate(message) for message in response.json()]

# Template Management Endpoints
def create_template(self, template_data: Dict[str, Any]) -> Dict[str, Any]:
Expand Down Expand Up @@ -238,7 +238,7 @@ def send_text(

from ..models.rcs import RCSMessage

return RCSMessage.parse_obj(response.json())
return RCSMessage.model_validate(response.json())

def send_rich_card(
self,
Expand Down Expand Up @@ -277,7 +277,7 @@ def send_rich_card(

from ..models.rcs import RCSMessage

return RCSMessage.parse_obj(response.json())
return RCSMessage.model_validate(response.json())

def get(self, message_id: str) -> "RCSMessage":
"""Retrieve an RCS message by ID."""
Expand All @@ -286,4 +286,4 @@ def get(self, message_id: str) -> "RCSMessage":

from ..models.rcs import RCSMessage

return RCSMessage.parse_obj(response.json())
return RCSMessage.model_validate(response.json())
Loading
Loading