Skip to content

Commit 612dfac

Browse files
docs: update all examples to Python 3.13 with proper error handling
1 parent 915ffcf commit 612dfac

19 files changed

Lines changed: 2683 additions & 744 deletions

docs/changelog.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,54 @@
22

33
All notable changes to ArchiPy are documented in this changelog, organized by version.
44

5+
## [3.13.3]
6+
7+
### Changed
8+
9+
#### Documentation Examples - Complete Python 3.13 & Best Practices Update
10+
11+
- **Comprehensive Example Documentation Refactor** - Updated all 17 example files to follow modern Python 3.13 standards and ArchiPy best practices
12+
- Updated all type hints to Python 3.13 syntax (`|` for unions, lowercase built-ins, `type` instead of `Type`)
13+
- Replaced `Union[X, Y]` with `X | Y` throughout all examples
14+
- Replaced `Optional[X]` with `X | None` throughout all examples
15+
- Changed `List`, `Dict` to lowercase `list`, `dict` consistently
16+
- Removed `from typing import Union, Optional` in favor of native syntax
17+
18+
- **Exception Handling Standardization** - Implemented proper exception handling patterns across all examples
19+
- Added `try-except-else` pattern with explicit `return` statements in `else` blocks
20+
- Ensured all exceptions use `raise ... from e` for proper error chaining
21+
- Removed operation/query messages from exception constructors (per workspace rules)
22+
- Replaced generic `Exception`, `ValueError` with specific ArchiPy error types
23+
- Added comprehensive error handling examples in all adapter documentation
24+
25+
- **Logging Standardization** - Replaced all print statements with proper logging
26+
- Added `logger = logging.getLogger(__name__)` to all example files
27+
- Replaced all `print()` statements with appropriate `logger.info()`, `logger.error()`, etc.
28+
- Implemented consistent logging levels and informative messages
29+
- Added logging configuration examples in code snippets
30+
31+
- **Documentation Structure Improvements** - Enhanced navigation and cross-referencing
32+
- Added "See Also" sections to all adapter examples
33+
- Linked adapter examples to corresponding BDD test `.feature` files
34+
- Added cross-references to error handling, configuration, and API documentation
35+
- Improved code explanations with detailed docstrings
36+
- Added warnings for common pitfalls and best practices
37+
38+
- **New Complete Examples Added**
39+
- Email adapter with FastAPI integration and comprehensive error handling
40+
- SQLite adapter with async operations and context managers
41+
- StarRocks adapter with analytical query patterns and batch operations
42+
- Metaclasses with singleton pattern, thread safety, and best practices
43+
- Parsian payment gateway with complete payment flow and error recovery
44+
- Temporal workflow orchestration with atomic activities and worker management
45+
46+
- **Code Quality Improvements**
47+
- All examples now syntactically correct with proper indentation
48+
- Fixed indentation errors in `error_handling.md`
49+
- Added security warnings for sensitive data (passwords in `.env` files)
50+
- Improved FastAPI integration examples with proper dependency injection
51+
- Enhanced async/await patterns with proper error handling
52+
553
## [3.13.2]
654

755
### Changed

docs/examples/adapters/email.md

Lines changed: 282 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
# Email Adapter Examples
22

3-
This page demonstrates how to use ArchiPy's email adapter functionality.
3+
This page demonstrates how to use ArchiPy's email adapter functionality for sending emails with proper error handling and logging.
44

55
## Basic Usage
66

77
```python
8+
import logging
9+
810
from archipy.adapters.email import EmailAdapter
11+
from archipy.models.errors import InternalError, InvalidArgumentError
12+
13+
# Configure logging
14+
logger = logging.getLogger(__name__)
915

1016
# Configure email adapter
17+
try:
18+
email_adapter = EmailAdapter(
19+
host="smtp.example.com",
20+
port=587,
21+
username="your-username",
22+
password="your-password",
23+
use_tls=True
24+
)
25+
except Exception as e:
26+
logger.error(f"Failed to configure email adapter: {e}")
27+
raise InternalError() from e
28+
else:
29+
logger.info("Email adapter configured successfully")
30+
```
31+
32+
## Sending Simple Emails
33+
34+
```python
35+
import logging
36+
37+
from archipy.adapters.email import EmailAdapter
38+
from archipy.models.errors import InternalError
39+
40+
# Configure logging
41+
logger = logging.getLogger(__name__)
42+
1143
email_adapter = EmailAdapter(
1244
host="smtp.example.com",
1345
port=587,
@@ -17,15 +49,255 @@ email_adapter = EmailAdapter(
1749
)
1850

1951
# Send an email
20-
email_adapter.send_email(
21-
subject="Test Email",
22-
body="This is a test email from ArchiPy",
23-
recipients=["recipient@example.com"],
24-
cc=["cc@example.com"],
25-
bcc=["bcc@example.com"],
26-
from_email="sender@example.com"
52+
try:
53+
email_adapter.send_email(
54+
subject="Test Email",
55+
body="This is a test email from ArchiPy",
56+
recipients=["recipient@example.com"],
57+
from_email="sender@example.com"
58+
)
59+
except InvalidArgumentError as e:
60+
logger.error(f"Invalid email parameters: {e}")
61+
raise
62+
except InternalError as e:
63+
logger.error(f"Failed to send email: {e}")
64+
raise
65+
else:
66+
logger.info("Email sent successfully")
67+
```
68+
69+
## Sending Emails with CC and BCC
70+
71+
```python
72+
import logging
73+
74+
from archipy.adapters.email import EmailAdapter
75+
from archipy.models.errors import InternalError
76+
77+
# Configure logging
78+
logger = logging.getLogger(__name__)
79+
80+
email_adapter = EmailAdapter(
81+
host="smtp.example.com",
82+
port=587,
83+
username="your-username",
84+
password="your-password",
85+
use_tls=True
86+
)
87+
88+
# Send email with CC and BCC
89+
try:
90+
email_adapter.send_email(
91+
subject="Important Notification",
92+
body="This message has CC and BCC recipients",
93+
recipients=["primary@example.com"],
94+
cc=["cc1@example.com", "cc2@example.com"],
95+
bcc=["bcc@example.com"],
96+
from_email="sender@example.com"
97+
)
98+
except InternalError as e:
99+
logger.error(f"Failed to send email with CC/BCC: {e}")
100+
raise
101+
else:
102+
logger.info("Email sent with CC and BCC recipients")
103+
```
104+
105+
## Sending HTML Emails
106+
107+
```python
108+
import logging
109+
110+
from archipy.adapters.email import EmailAdapter
111+
from archipy.models.errors import InternalError
112+
113+
# Configure logging
114+
logger = logging.getLogger(__name__)
115+
116+
email_adapter = EmailAdapter(
117+
host="smtp.example.com",
118+
port=587,
119+
username="your-username",
120+
password="your-password",
121+
use_tls=True
122+
)
123+
124+
html_content = """
125+
<html>
126+
<body>
127+
<h1>Welcome to ArchiPy!</h1>
128+
<p>This is an <strong>HTML</strong> email.</p>
129+
</body>
130+
</html>
131+
"""
132+
133+
try:
134+
email_adapter.send_email(
135+
subject="HTML Email",
136+
body=html_content,
137+
recipients=["user@example.com"],
138+
from_email="sender@example.com",
139+
is_html=True
140+
)
141+
except InternalError as e:
142+
logger.error(f"Failed to send HTML email: {e}")
143+
raise
144+
else:
145+
logger.info("HTML email sent successfully")
146+
```
147+
148+
## Sending Emails with Attachments
149+
150+
```python
151+
import logging
152+
153+
from archipy.adapters.email import EmailAdapter
154+
from archipy.models.errors import InternalError, InvalidArgumentError
155+
156+
# Configure logging
157+
logger = logging.getLogger(__name__)
158+
159+
email_adapter = EmailAdapter(
160+
host="smtp.example.com",
161+
port=587,
162+
username="your-username",
163+
password="your-password",
164+
use_tls=True
165+
)
166+
167+
try:
168+
email_adapter.send_email(
169+
subject="Email with Attachment",
170+
body="Please find the attached document",
171+
recipients=["user@example.com"],
172+
from_email="sender@example.com",
173+
attachments=["/path/to/document.pdf", "/path/to/image.png"]
174+
)
175+
except InvalidArgumentError as e:
176+
logger.error(f"Invalid attachment path: {e}")
177+
raise
178+
except InternalError as e:
179+
logger.error(f"Failed to send email with attachments: {e}")
180+
raise
181+
else:
182+
logger.info("Email with attachments sent successfully")
183+
```
184+
185+
## Integration with FastAPI
186+
187+
```python
188+
import logging
189+
190+
from fastapi import FastAPI, HTTPException
191+
from pydantic import BaseModel, EmailStr
192+
193+
from archipy.adapters.email import EmailAdapter
194+
from archipy.models.errors import InternalError, InvalidArgumentError
195+
196+
# Configure logging
197+
logger = logging.getLogger(__name__)
198+
199+
app = FastAPI()
200+
email_adapter = EmailAdapter(
201+
host="smtp.example.com",
202+
port=587,
203+
username="your-username",
204+
password="your-password",
205+
use_tls=True
27206
)
207+
208+
209+
class EmailRequest(BaseModel):
210+
to: list[EmailStr]
211+
subject: str
212+
body: str
213+
cc: list[EmailStr] | None = None
214+
bcc: list[EmailStr] | None = None
215+
216+
217+
@app.post("/send-email")
218+
async def send_email(email_request: EmailRequest) -> dict[str, str]:
219+
"""Send an email via API endpoint."""
220+
try:
221+
email_adapter.send_email(
222+
subject=email_request.subject,
223+
body=email_request.body,
224+
recipients=email_request.to,
225+
cc=email_request.cc,
226+
bcc=email_request.bcc,
227+
from_email="noreply@example.com"
228+
)
229+
except InvalidArgumentError as e:
230+
logger.error(f"Invalid email request: {e}")
231+
raise HTTPException(status_code=400, detail="Invalid email parameters") from e
232+
except InternalError as e:
233+
logger.error(f"Failed to send email: {e}")
234+
raise HTTPException(status_code=500, detail="Failed to send email") from e
235+
else:
236+
logger.info(f"Email sent to {len(email_request.to)} recipient(s)")
237+
return {"message": "Email sent successfully"}
28238
```
29239

30-
This documentation is being migrated from Sphinx to MkDocs format.
31-
Please check back soon for complete content.
240+
## Error Handling Patterns
241+
242+
```python
243+
import logging
244+
245+
from archipy.adapters.email import EmailAdapter
246+
from archipy.models.errors import InternalError, InvalidArgumentError, ConfigurationError
247+
248+
# Configure logging
249+
logger = logging.getLogger(__name__)
250+
251+
252+
def send_notification_email(recipient: str, subject: str, body: str) -> bool:
253+
"""Send a notification email with comprehensive error handling.
254+
255+
Args:
256+
recipient: Email address of the recipient
257+
subject: Email subject line
258+
body: Email body content
259+
260+
Returns:
261+
True if email sent successfully, False otherwise
262+
263+
Raises:
264+
InvalidArgumentError: If email parameters are invalid
265+
InternalError: If email service fails
266+
ConfigurationError: If email adapter is not configured
267+
"""
268+
try:
269+
email_adapter = EmailAdapter(
270+
host="smtp.example.com",
271+
port=587,
272+
username="your-username",
273+
password="your-password",
274+
use_tls=True
275+
)
276+
except Exception as e:
277+
logger.error(f"Email adapter configuration failed: {e}")
278+
raise ConfigurationError() from e
279+
280+
try:
281+
email_adapter.send_email(
282+
subject=subject,
283+
body=body,
284+
recipients=[recipient],
285+
from_email="noreply@example.com"
286+
)
287+
except InvalidArgumentError as e:
288+
logger.error(f"Invalid email parameters: {e}")
289+
raise
290+
except InternalError as e:
291+
logger.error(f"Failed to send email: {e}")
292+
raise
293+
else:
294+
logger.info(f"Notification email sent to {recipient}")
295+
return True
296+
```
297+
298+
## See Also
299+
300+
- [Error Handling](../error_handling.md) - Exception handling patterns with proper chaining
301+
- [Configuration Management](../config_management.md) - Email configuration setup
302+
- [BDD Testing](../bdd_testing.md) - Testing email operations
303+
- [API Reference](../../api_reference/adapters.md) - Full Email adapter API documentation

0 commit comments

Comments
 (0)