learningcircuit--local-deep-research
7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
222 行
5.8 KiB
Markdown
222 行
5.8 KiB
Markdown
# News API Exception Handling
|
|
|
|
## Overview
|
|
|
|
The news API module now uses a structured exception handling approach instead of returning error dictionaries. This provides better error handling, cleaner code, and consistent API responses.
|
|
|
|
## Exception Hierarchy
|
|
|
|
All news API exceptions inherit from `NewsAPIException`, which provides:
|
|
- Human-readable error messages
|
|
- HTTP status codes
|
|
- Machine-readable error codes
|
|
- Optional additional details
|
|
|
|
```python
|
|
from local_deep_research.news.exceptions import NewsAPIException
|
|
|
|
class NewsAPIException(Exception):
|
|
def __init__(self, message: str, status_code: int = 500,
|
|
error_code: Optional[str] = None,
|
|
details: Optional[Dict[str, Any]] = None)
|
|
```
|
|
|
|
## Available Exceptions
|
|
|
|
### InvalidLimitException
|
|
- **Status Code**: 400
|
|
- **Error Code**: `INVALID_LIMIT`
|
|
- **Usage**: When an invalid limit parameter is provided
|
|
- **Example**:
|
|
```python
|
|
if limit < 1:
|
|
raise InvalidLimitException(limit)
|
|
```
|
|
|
|
### SubscriptionNotFoundException
|
|
- **Status Code**: 404
|
|
- **Error Code**: `SUBSCRIPTION_NOT_FOUND`
|
|
- **Usage**: When a requested subscription doesn't exist
|
|
- **Example**:
|
|
```python
|
|
if not subscription:
|
|
raise SubscriptionNotFoundException(subscription_id)
|
|
```
|
|
|
|
### SubscriptionCreationException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `SUBSCRIPTION_CREATE_FAILED`
|
|
- **Usage**: When subscription creation fails
|
|
- **Example**:
|
|
```python
|
|
except Exception as e:
|
|
raise SubscriptionCreationException(str(e), {"query": query})
|
|
```
|
|
|
|
### SubscriptionUpdateException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `SUBSCRIPTION_UPDATE_FAILED`
|
|
- **Usage**: When subscription update fails
|
|
|
|
### SubscriptionDeletionException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `SUBSCRIPTION_DELETE_FAILED`
|
|
- **Usage**: When subscription deletion fails
|
|
|
|
### DatabaseAccessException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `DATABASE_ERROR`
|
|
- **Usage**: When database operations fail
|
|
- **Example**:
|
|
```python
|
|
except Exception as e:
|
|
raise DatabaseAccessException("operation_name", str(e))
|
|
```
|
|
|
|
### NewsFeedGenerationException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `FEED_GENERATION_FAILED`
|
|
- **Usage**: When news feed generation fails
|
|
|
|
### ResearchProcessingException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `RESEARCH_PROCESSING_FAILED`
|
|
- **Usage**: When processing research items fails
|
|
|
|
### NotImplementedException
|
|
- **Status Code**: 501
|
|
- **Error Code**: `NOT_IMPLEMENTED`
|
|
- **Usage**: For features not yet implemented
|
|
- **Example**:
|
|
```python
|
|
raise NotImplementedException("feature_name")
|
|
```
|
|
|
|
### InvalidParameterException
|
|
- **Status Code**: 400
|
|
- **Error Code**: `INVALID_PARAMETER`
|
|
- **Usage**: When invalid parameters are provided
|
|
|
|
### SchedulerNotificationException
|
|
- **Status Code**: 500
|
|
- **Error Code**: `SCHEDULER_NOTIFICATION_FAILED`
|
|
- **Usage**: When scheduler notification fails (non-critical)
|
|
|
|
## Flask Integration
|
|
|
|
### Error Handlers
|
|
|
|
The Flask application automatically handles `NewsAPIException` and its subclasses:
|
|
|
|
```python
|
|
@app.errorhandler(NewsAPIException)
|
|
def handle_news_api_exception(error):
|
|
return jsonify(error.to_dict()), error.status_code
|
|
```
|
|
|
|
### Response Format
|
|
|
|
All exceptions are converted to consistent JSON responses:
|
|
|
|
```json
|
|
{
|
|
"error": "Human-readable error message",
|
|
"error_code": "MACHINE_READABLE_CODE",
|
|
"status_code": 400,
|
|
"details": {
|
|
"additional": "context",
|
|
"if": "available"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Migration Guide
|
|
|
|
### Before (Error Dictionaries)
|
|
|
|
```python
|
|
def get_news_feed(limit):
|
|
if limit < 1:
|
|
return {
|
|
"error": "Limit must be at least 1",
|
|
"news_items": []
|
|
}
|
|
|
|
try:
|
|
# ... code ...
|
|
except Exception as e:
|
|
logger.exception("Error getting news feed")
|
|
return {"error": str(e), "news_items": []}
|
|
```
|
|
|
|
### After (Exceptions)
|
|
|
|
```python
|
|
def get_news_feed(limit):
|
|
if limit < 1:
|
|
raise InvalidLimitException(limit)
|
|
|
|
try:
|
|
# ... code ...
|
|
except NewsAPIException:
|
|
raise # Re-raise our custom exceptions
|
|
except Exception as e:
|
|
logger.exception("Error getting news feed")
|
|
raise NewsFeedGenerationException(str(e))
|
|
```
|
|
|
|
## Benefits
|
|
|
|
1. **Cleaner Code**: Functions focus on their primary logic without error response formatting
|
|
2. **Consistent Error Handling**: All errors follow the same format
|
|
3. **Better Testing**: Easier to test exception cases with pytest.raises
|
|
4. **Type Safety**: IDEs can better understand return types
|
|
5. **Centralized Logging**: Error logging can be handled in one place
|
|
6. **HTTP Status Codes**: Proper HTTP status codes are automatically set
|
|
|
|
## Testing
|
|
|
|
Test exception handling using pytest:
|
|
|
|
```python
|
|
import pytest
|
|
from local_deep_research.news.exceptions import InvalidLimitException
|
|
|
|
def test_invalid_limit():
|
|
with pytest.raises(InvalidLimitException) as exc_info:
|
|
news_api.get_news_feed(limit=-1)
|
|
|
|
assert exc_info.value.status_code == 400
|
|
assert exc_info.value.details["provided_limit"] == -1
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Always catch and re-raise NewsAPIException subclasses**:
|
|
```python
|
|
except NewsAPIException:
|
|
raise # Let Flask handle it
|
|
except Exception as e:
|
|
# Convert to appropriate NewsAPIException
|
|
raise DatabaseAccessException("operation", str(e))
|
|
```
|
|
|
|
2. **Include relevant details**:
|
|
```python
|
|
raise SubscriptionCreationException(
|
|
"Database constraint violated",
|
|
details={"query": query, "type": subscription_type}
|
|
)
|
|
```
|
|
|
|
3. **Use appropriate exception types**: Choose the most specific exception that matches the error condition
|
|
|
|
4. **Log before raising**: For unexpected errors, log the full exception before converting to NewsAPIException
|
|
|
|
## Future Improvements
|
|
|
|
- Add retry logic for transient errors
|
|
- Implement exception metrics/monitoring
|
|
- Add internationalization support for error messages
|
|
- Create exception middleware for advanced error handling
|