-
Notifications
You must be signed in to change notification settings - Fork 7
Add templates_api for the paginated /api/templates endpoints #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
izikaj
wants to merge
5
commits into
main
Choose a base branch
from
templates-api
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+679
−0
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
742a149
Add templates_api for the paginated /api/templates endpoints
izikaj a7508e0
Drop the example package marker the sibling example dirs do not have
izikaj ece062e
Note that the /api/templates endpoints are experimental
izikaj 05c1d03
fix: name templates_api.templates in the deprecation warning
izikaj c039510
Hold the email templates deprecation and rename to paginated_templates
izikaj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import os | ||
| from typing import Optional | ||
|
|
||
| import mailtrap as mt | ||
| from mailtrap.models.common import DeletedObject | ||
| from mailtrap.models.paginated_templates import Template | ||
| from mailtrap.models.paginated_templates import TemplateListResponse | ||
|
|
||
| API_KEY = os.environ["MAILTRAP_API_KEY"] | ||
| ACCOUNT_ID = os.environ["MAILTRAP_ACCOUNT_ID"] | ||
|
|
||
| client = mt.MailtrapClient(token=API_KEY, account_id=ACCOUNT_ID) | ||
| templates_api = client.templates_api.templates | ||
|
|
||
|
|
||
| def list_templates() -> TemplateListResponse: | ||
| # `token` is the page number (page-token pagination); `per_page` caps at 100. | ||
| response = templates_api.get_list(mt.TemplateListParams(per_page=50, token=1)) | ||
| print(response.data) | ||
| print(response.pagination) | ||
| return response | ||
|
|
||
|
|
||
| def create_template( | ||
| name: str, | ||
| subject: str, | ||
| category: str, | ||
| body_html: Optional[str] = None, | ||
| body_text: Optional[str] = None, | ||
| ) -> Template: | ||
| params = mt.CreateTemplateParams( | ||
| name=name, | ||
| subject=subject, | ||
| category=category, | ||
| body_html=body_html, | ||
| body_text=body_text, | ||
| ) | ||
| return templates_api.create(params) | ||
|
|
||
|
|
||
| def get_template(template_id: int) -> Template: | ||
| return templates_api.get_by_id(template_id) | ||
|
|
||
|
|
||
| def update_template( | ||
| template_id: int, | ||
| name: Optional[str] = None, | ||
| subject: Optional[str] = None, | ||
| category: Optional[str] = None, | ||
| body_html: Optional[str] = None, | ||
| body_text: Optional[str] = None, | ||
| ) -> Template: | ||
| params = mt.UpdateTemplateParams( | ||
| name=name, | ||
| subject=subject, | ||
| category=category, | ||
| body_html=body_html, | ||
| body_text=body_text, | ||
| ) | ||
| return templates_api.update(template_id, params) | ||
|
|
||
|
|
||
| def delete_template(template_id: int) -> DeletedObject: | ||
| return templates_api.delete(template_id) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| list_templates() | ||
|
|
||
| created = create_template( | ||
| name="Welcome", | ||
| subject="Welcome aboard", | ||
| category="Onboarding", | ||
| body_html="<h1>Hello!</h1>", | ||
| ) | ||
| print(created) | ||
|
|
||
| print(get_template(created.id)) | ||
| print(update_template(created.id, subject="Welcome to Mailtrap")) | ||
| print(delete_template(created.id)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| from mailtrap.api.resources.paginated_templates import PaginatedTemplatesApi | ||
| from mailtrap.http import HttpClient | ||
|
|
||
|
|
||
| class TemplatesBaseApi: | ||
| def __init__(self, client: HttpClient, account_id: str) -> None: | ||
| self._account_id = account_id | ||
| self._client = client | ||
|
|
||
| @property | ||
| def templates(self) -> PaginatedTemplatesApi: | ||
| return PaginatedTemplatesApi(account_id=self._account_id, client=self._client) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| from typing import Optional | ||
|
|
||
| from mailtrap.http import HttpClient | ||
| from mailtrap.models.common import DeletedObject | ||
| from mailtrap.models.paginated_templates import CreateTemplateParams | ||
| from mailtrap.models.paginated_templates import Template | ||
| from mailtrap.models.paginated_templates import TemplateListParams | ||
| from mailtrap.models.paginated_templates import TemplateListResponse | ||
| from mailtrap.models.paginated_templates import TemplateResponse | ||
| from mailtrap.models.paginated_templates import UpdateTemplateParams | ||
|
|
||
|
|
||
| class PaginatedTemplatesApi: | ||
| """ | ||
| Templates API. The ``/api/templates`` endpoints are experimental: their | ||
| request and response shapes may change before general availability. | ||
| """ | ||
|
|
||
| def __init__(self, client: HttpClient, account_id: str) -> None: | ||
| self._account_id = account_id | ||
| self._client = client | ||
|
|
||
| def get_list( | ||
| self, params: Optional[TemplateListParams] = None | ||
| ) -> TemplateListResponse: | ||
| """ | ||
| List email templates in the account, one page at a time. Unlike the | ||
| ``email_templates_api`` list, it does not return every template: pass | ||
| ``pagination.next_token`` with the same ``per_page`` to get the next | ||
| page. Omit ``params`` for the first page with API defaults. | ||
| """ | ||
| query_params = params.api_query_params if params else None | ||
| response = self._client.get(self._api_path(), params=query_params or None) | ||
| return TemplateListResponse(**response) | ||
|
|
||
| def get_by_id(self, template_id: int) -> Template: | ||
| """Get an email template by ID.""" | ||
| response = self._client.get(self._api_path(template_id)) | ||
| return TemplateResponse(**response).data | ||
|
|
||
| def create(self, template_params: CreateTemplateParams) -> Template: | ||
| """Create a new email template.""" | ||
| response = self._client.post(self._api_path(), json=template_params.api_data) | ||
| return TemplateResponse(**response).data | ||
|
|
||
| def update(self, template_id: int, template_params: UpdateTemplateParams) -> Template: | ||
| """Update an email template. Only the supplied fields are changed.""" | ||
| response = self._client.patch( | ||
| self._api_path(template_id), json=template_params.api_data | ||
| ) | ||
| return TemplateResponse(**response).data | ||
|
|
||
| def delete(self, template_id: int) -> DeletedObject: | ||
| """Delete an email template.""" | ||
| self._client.delete(self._api_path(template_id)) | ||
| return DeletedObject(template_id) | ||
|
|
||
| def _api_path(self, template_id: Optional[int] = None) -> str: | ||
| path = f"/api/accounts/{self._account_id}/templates" | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| if template_id is not None: | ||
| return f"{path}/{template_id}" | ||
| return path | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| """Models for the account-scoped, paginated Templates API (``/api/templates``).""" | ||
|
|
||
| from typing import Optional | ||
|
|
||
| from pydantic import Field | ||
| from pydantic.dataclasses import dataclass | ||
|
|
||
| from mailtrap.models.common import Pagination | ||
| from mailtrap.models.common import RequestParams | ||
|
|
||
|
|
||
| @dataclass | ||
| class Template: | ||
| """A single email template.""" | ||
|
|
||
| id: int | ||
| uuid: Optional[str] = None | ||
| name: Optional[str] = None | ||
| category: Optional[str] = None | ||
| subject: Optional[str] = None | ||
| body_html: Optional[str] = None | ||
| body_text: Optional[str] = None | ||
| created_at: Optional[str] = None | ||
| updated_at: Optional[str] = None | ||
|
|
||
|
|
||
| @dataclass | ||
| class TemplateResponse: | ||
| """Envelope of a single-template response.""" | ||
|
|
||
| data: Template | ||
|
|
||
|
|
||
| @dataclass | ||
| class TemplateListResponse: | ||
| """Paginated response from listing templates.""" | ||
|
|
||
| data: list[Template] = Field(default_factory=list) | ||
| pagination: Optional[Pagination] = None | ||
|
|
||
|
|
||
| @dataclass | ||
| class TemplateListParams(RequestParams): | ||
| """ | ||
| Query params for listing templates. ``token`` is the page number and | ||
| ``per_page`` is capped at 100. | ||
| """ | ||
|
|
||
| per_page: Optional[int] = None | ||
| token: Optional[int] = None | ||
|
|
||
|
|
||
| @dataclass | ||
| class CreateTemplateParams(RequestParams): | ||
| """Attributes for creating a template (sent as a flat JSON body).""" | ||
|
|
||
| name: str | ||
| subject: str | ||
| category: str | ||
| body_html: Optional[str] = None | ||
| body_text: Optional[str] = None | ||
|
|
||
|
|
||
| @dataclass | ||
| class UpdateTemplateParams(RequestParams): | ||
| """ | ||
| Attributes for updating a template (sent as a flat JSON body). All fields | ||
| are optional, but at least one must be provided. | ||
| """ | ||
|
|
||
| name: Optional[str] = None | ||
| subject: Optional[str] = None | ||
| category: Optional[str] = None | ||
| body_html: Optional[str] = None | ||
| body_text: Optional[str] = None | ||
|
|
||
| def __post_init__(self) -> None: | ||
| if all( | ||
| value is None | ||
| for value in [ | ||
| self.name, | ||
| self.subject, | ||
| self.category, | ||
| self.body_html, | ||
| self.body_text, | ||
| ] | ||
| ): | ||
| raise ValueError("At least one field must be provided for update action") |
Empty file.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.