-
Notifications
You must be signed in to change notification settings - Fork 8
Fix issue #41: Add ContactExportsApi, related models, tests and examples #49
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
Conversation
WalkthroughAdds contact exports: new models, a ContactExportsApi client with create/get_by_id, exposes it on ContactsBaseApi, re-exports model types, includes an example script, and adds unit tests for models and API behaviors. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer
participant Client as Mailtrap Client
participant Contacts as ContactsBaseApi
participant Exports as ContactExportsApi
participant HTTP as HttpClient
participant API as Mailtrap REST API
rect rgb(240,248,255)
note left of Dev: Create contact export
Dev->>Client: instantiate(client, account_id)
Dev->>Contacts: client.contacts
Contacts->>Contacts: .contact_exports (property)
Contacts-->>Dev: ContactExportsApi
Dev->>Exports: create(CreateContactExportParams)
Exports->>HTTP: POST /api/accounts/{id}/contacts/exports\nbody: params.api_data
HTTP->>API: request
API-->>HTTP: 201 {export_detail}
HTTP-->>Exports: response
Exports-->>Dev: ContactExportDetail
end
rect rgb(245,255,245)
note left of Dev: Get export by ID
Dev->>Exports: get_by_id(export_id)
Exports->>HTTP: GET /api/accounts/{id}/contacts/exports/{export_id}
HTTP->>API: request
API-->>HTTP: 200 {export_detail}
HTTP-->>Exports: response
Exports-->>Dev: ContactExportDetail
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
examples/contacts/contact_exports.py
(1 hunks)mailtrap/__init__.py
(1 hunks)mailtrap/api/contacts.py
(2 hunks)mailtrap/api/resources/contact_exports.py
(1 hunks)mailtrap/models/contacts.py
(2 hunks)tests/unit/api/contacts/test_contact_exports.py
(1 hunks)tests/unit/models/test_contacts.py
(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-29T21:15:03.708Z
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#38
File: mailtrap/api/resources/contact_imports.py:13-18
Timestamp: 2025-08-29T21:15:03.708Z
Learning: In mailtrap/models/contacts.py, ImportContactParams.api_data is defined as a property, not a method, so it can be accessed without parentheses like contact.api_data.
Applied to files:
mailtrap/api/contacts.py
📚 Learning: 2025-08-22T13:51:31.437Z
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#35
File: examples/contacts/contact_fields.py:11-11
Timestamp: 2025-08-22T13:51:31.437Z
Learning: In mailtrap/api/contacts.py, ContactsBaseApi.contact_fields is defined as a property, not a method, so it can be accessed without parentheses like client.contacts_api.contact_fields.
Applied to files:
mailtrap/api/contacts.py
🧬 Code graph analysis (7)
mailtrap/api/contacts.py (2)
mailtrap/api/resources/contact_exports.py (1)
ContactExportsApi
(8-32)tests/unit/api/contacts/test_contact_exports.py (1)
client
(23-24)
examples/contacts/contact_exports.py (3)
mailtrap/api/contacts.py (2)
contacts
(31-32)contact_exports
(15-16)mailtrap/models/contacts.py (3)
ContactImport
(109-114)CreateContactExportParams
(135-136)ContactExportFilter
(128-131)mailtrap/api/resources/contact_exports.py (2)
create
(13-21)get_by_id
(23-26)
tests/unit/models/test_contacts.py (2)
mailtrap/models/contacts.py (2)
ContactExportFilter
(128-131)CreateContactExportParams
(135-136)mailtrap/models/common.py (1)
api_data
(15-19)
mailtrap/models/contacts.py (1)
mailtrap/models/common.py (1)
RequestParams
(13-19)
tests/unit/api/contacts/test_contact_exports.py (5)
mailtrap/api/contacts.py (2)
contact_exports
(15-16)contacts
(31-32)mailtrap/api/resources/contact_exports.py (3)
ContactExportsApi
(8-32)create
(13-21)get_by_id
(23-26)mailtrap/exceptions.py (1)
APIError
(10-15)mailtrap/http.py (2)
HttpClient
(14-106)post
(32-34)mailtrap/models/contacts.py (3)
ContactExportDetail
(140-145)ContactExportFilter
(128-131)CreateContactExportParams
(135-136)
mailtrap/api/resources/contact_exports.py (3)
mailtrap/http.py (2)
HttpClient
(14-106)post
(32-34)mailtrap/models/contacts.py (2)
ContactExportDetail
(140-145)CreateContactExportParams
(135-136)tests/unit/api/contacts/test_contact_exports.py (1)
client
(23-24)
mailtrap/__init__.py (2)
mailtrap/api/contacts.py (1)
contacts
(31-32)mailtrap/models/contacts.py (3)
ContactExportFilter
(128-131)ContactListParams
(37-38)CreateContactExportParams
(135-136)
🪛 Ruff (0.13.3)
examples/contacts/contact_exports.py
4-4: Possible hardcoded password assigned to: "API_TOKEN"
(S105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test python3.9 on windows-latest
🔇 Additional comments (9)
mailtrap/__init__.py (1)
9-11
: LGTM!The new exports follow the established pattern and correctly expose the new contact export models for external use.
mailtrap/api/contacts.py (2)
1-1
: LGTM!Import correctly placed at the top with other resource imports.
14-16
: LGTM!The
contact_exports
property follows the same pattern as other properties in this class and correctly instantiates theContactExportsApi
with the required parameters.tests/unit/models/test_contacts.py (2)
3-5
: LGTM!Imports are correctly placed with other model imports.
154-200
: LGTM!The test coverage is comprehensive and follows the established patterns:
- Tests api_data generation for ContactExportFilter
- Tests single, multiple, and empty filter scenarios for CreateContactExportParams
- All assertions are clear and verify the expected behavior
mailtrap/models/contacts.py (2)
1-1
: LGTM!The datetime import is necessary for the ContactExportDetail model's timestamp fields.
127-145
: LGTM!The new dataclasses are well-structured:
ContactExportFilter
andCreateContactExportParams
correctly extendRequestParams
for API request serialization via theapi_data
propertyContactExportDetail
uses Pydantic's dataclass, which will automatically parse ISO datetime strings from API responses- Field types are appropriate for the domain
tests/unit/api/contacts/test_contact_exports.py (1)
1-244
: LGTM!Excellent test coverage for the ContactExportsApi:
- Comprehensive error handling tests (401, 403, 404, 422 status codes)
- Success path validation for both create and get_by_id operations
- Verification of correct URL construction with different export IDs
- Proper use of fixtures and parameterized tests
- Clear assertions on response types, fields, and HTTP request details
The test suite follows established patterns and will catch regressions effectively.
mailtrap/api/resources/contact_exports.py (1)
8-32
: LGTM!The
ContactExportsApi
implementation is clean and follows the established patterns in the codebase:
- Constructor correctly stores dependencies
create
andget_by_id
methods properly use the HTTP client and return strongly-typed results_api_path
helper correctly constructs the endpoint path with optional export_id- Consistent with other resource API classes (ContactFieldsApi, ContactListsApi, etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
examples/contacts/contact_exports.py (2)
1-2
: Consider using consistent import style for clarity.The direct import of
ContactExportDetail
on line 2 is inconsistent with the module-prefixed style (mt.CreateContactExportParams
,mt.ContactExportFilter
) used throughout the rest of the example. In example files, consistently using the module prefix helps readers understand where types originate.Apply this diff to use consistent module-prefixed imports:
import mailtrap as mt -from mailtrap.models.contacts import ContactExportDetail API_TOKEN = "YOUR_API_TOKEN"
Then update the return type annotations to use
mt.ContactExportDetail
:def create_export_contacts( contact_exports_params: mt.CreateContactExportParams, -) -> ContactExportDetail: +) -> mt.ContactExportDetail: return contact_exports_api.create(contact_exports_params=contact_exports_params) -def get_contact_export(export_id: int) -> ContactExportDetail: +def get_contact_export(export_id: int) -> mt.ContactExportDetail: return contact_exports_api.get_by_id(export_id)
11-18
: Wrapper functions are acceptable but could be inlined.The wrapper functions demonstrate a reasonable pattern but aren't strictly necessary in an example file. Direct API calls in the
__main__
block would make the example more concise and immediately show the API surface. However, the current approach is also acceptable as it demonstrates how users might structure their own code.If you prefer a more concise example, you could inline these calls:
if __name__ == "__main__": contact_export = contact_exports_api.create( contact_exports_params=mt.CreateContactExportParams( filters=[mt.ContactExportFilter(name="list_id", operator="equal", value=[10])] ) ) print(contact_export) contact_export = contact_exports_api.get_by_id(contact_export.id) print(contact_export)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
examples/contacts/contact_exports.py
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
examples/contacts/contact_exports.py (3)
mailtrap/api/contacts.py (2)
contacts
(31-32)contact_exports
(15-16)mailtrap/models/contacts.py (3)
ContactExportDetail
(140-145)CreateContactExportParams
(135-136)ContactExportFilter
(128-131)mailtrap/api/resources/contact_exports.py (2)
create
(13-21)get_by_id
(23-26)
🪛 Ruff (0.13.3)
examples/contacts/contact_exports.py
4-4: Possible hardcoded password assigned to: "API_TOKEN"
(S105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Test python3.13 on windows-latest
- GitHub Check: Test python3.9 on windows-latest
- GitHub Check: Test python3.10 on windows-latest
- GitHub Check: Test python3.12 on windows-latest
- GitHub Check: Test python3.11 on windows-latest
🔇 Additional comments (2)
examples/contacts/contact_exports.py (2)
4-5
: Static analysis false positive: hardcoded credentials are appropriate here.The Ruff warning about a hardcoded password on line 4 is a false positive. These placeholder values (
"YOUR_API_TOKEN"
and"YOUR_ACCOUNT_ID"
) are clearly marked for user replacement and are appropriate for an example file.
21-30
: LGTM! Clear demonstration of the API usage.The main block effectively demonstrates creating a contact export with filters and then retrieving it by ID. The flow is clear and easy to follow.
Motivation
In this PR I added ContactExportsApi, related models, tests, examples
How to test
Summary by CodeRabbit
New Features
Tests