Phase 2, Task 2.1, Steps 1-3 Complete: Async Client Architecture
This commit introduces comprehensive async/await support for the Wiki.js
Python SDK, providing high-performance concurrent operations using aiohttp.
Key Features:
------------
1. **AsyncWikiJSClient** (wikijs/aio/client.py)
- Full async/await support with aiohttp
- Connection pooling (100 connections, 30 per host)
- Async context manager support (async with)
- Same interface as sync client for easy migration
- Proper resource cleanup and session management
- DNS caching for improved performance
2. **Async Endpoints** (wikijs/aio/endpoints/)
- AsyncBaseEndpoint - Base class for all async endpoints
- AsyncPagesEndpoint - Complete async Pages API
* list() - List pages with filtering
* get() - Get page by ID
* get_by_path() - Get page by path
* create() - Create new page
* update() - Update existing page
* delete() - Delete page
* search() - Search pages
* get_by_tags() - Filter by tags
3. **Architecture**
- Mirrors sync client structure for consistency
- Reuses existing models, exceptions, and utilities
- Optional dependency (aiohttp) via extras_require
- Zero breaking changes to sync API
Performance Benefits:
--------------------
- Designed for >3x throughput vs sync client
- Efficient connection pooling and reuse
- Concurrent request handling
- Reduced latency with TCP keepalive
Usage Example:
--------------
```python
from wikijs.aio import AsyncWikiJSClient
async with AsyncWikiJSClient(url, auth='key') as client:
# Concurrent operations
pages = await client.pages.list()
page = await client.pages.get(123)
# Create/Update/Delete
new_page = await client.pages.create(page_data)
updated = await client.pages.update(123, updates)
await client.pages.delete(123)
```
Installation:
-------------
```bash
pip install wikijs-python-sdk[async]
```
Quality Metrics:
----------------
- ✅ All imports successful
- ✅ Black formatting applied
- ✅ Flake8 passing (complexity warnings expected)
- ✅ MyPy type checking (minor issues in base models)
- ✅ Zero breaking changes to sync API
Next Steps:
-----------
- Comprehensive async unit tests
- Integration tests with real Wiki.js instance
- Performance benchmarks (async vs sync)
- Documentation and usage examples
This lays the foundation for high-performance async operations
in the Wiki.js Python SDK.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
141 lines
3.8 KiB
Python
141 lines
3.8 KiB
Python
"""Base async endpoint class for wikijs-python-sdk."""
|
|
|
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
|
|
|
if TYPE_CHECKING:
|
|
from ..client import AsyncWikiJSClient
|
|
|
|
|
|
class AsyncBaseEndpoint:
|
|
"""Base class for all async API endpoints.
|
|
|
|
This class provides common functionality for making async API requests
|
|
and handling responses across all endpoint implementations.
|
|
|
|
Args:
|
|
client: The async WikiJS client instance
|
|
"""
|
|
|
|
def __init__(self, client: "AsyncWikiJSClient"):
|
|
"""Initialize endpoint with client reference.
|
|
|
|
Args:
|
|
client: Async WikiJS client instance
|
|
"""
|
|
self._client = client
|
|
|
|
async def _request(
|
|
self,
|
|
method: str,
|
|
endpoint: str,
|
|
params: Optional[Dict[str, Any]] = None,
|
|
json_data: Optional[Dict[str, Any]] = None,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Make async HTTP request through the client.
|
|
|
|
Args:
|
|
method: HTTP method (GET, POST, PUT, DELETE)
|
|
endpoint: API endpoint path
|
|
params: Query parameters
|
|
json_data: JSON data for request body
|
|
**kwargs: Additional request parameters
|
|
|
|
Returns:
|
|
Parsed response data
|
|
"""
|
|
return await self._client._request(
|
|
method=method,
|
|
endpoint=endpoint,
|
|
params=params,
|
|
json_data=json_data,
|
|
**kwargs,
|
|
)
|
|
|
|
async def _get(
|
|
self, endpoint: str, params: Optional[Dict[str, Any]] = None, **kwargs: Any
|
|
) -> Any:
|
|
"""Make async GET request.
|
|
|
|
Args:
|
|
endpoint: API endpoint path
|
|
params: Query parameters
|
|
**kwargs: Additional request parameters
|
|
|
|
Returns:
|
|
Parsed response data
|
|
"""
|
|
return await self._request("GET", endpoint, params=params, **kwargs)
|
|
|
|
async def _post(
|
|
self,
|
|
endpoint: str,
|
|
json_data: Optional[Dict[str, Any]] = None,
|
|
params: Optional[Dict[str, Any]] = None,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Make async POST request.
|
|
|
|
Args:
|
|
endpoint: API endpoint path
|
|
json_data: JSON data for request body
|
|
params: Query parameters
|
|
**kwargs: Additional request parameters
|
|
|
|
Returns:
|
|
Parsed response data
|
|
"""
|
|
return await self._request(
|
|
"POST", endpoint, params=params, json_data=json_data, **kwargs
|
|
)
|
|
|
|
async def _put(
|
|
self,
|
|
endpoint: str,
|
|
json_data: Optional[Dict[str, Any]] = None,
|
|
params: Optional[Dict[str, Any]] = None,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Make async PUT request.
|
|
|
|
Args:
|
|
endpoint: API endpoint path
|
|
json_data: JSON data for request body
|
|
params: Query parameters
|
|
**kwargs: Additional request parameters
|
|
|
|
Returns:
|
|
Parsed response data
|
|
"""
|
|
return await self._request(
|
|
"PUT", endpoint, params=params, json_data=json_data, **kwargs
|
|
)
|
|
|
|
async def _delete(
|
|
self, endpoint: str, params: Optional[Dict[str, Any]] = None, **kwargs: Any
|
|
) -> Any:
|
|
"""Make async DELETE request.
|
|
|
|
Args:
|
|
endpoint: API endpoint path
|
|
params: Query parameters
|
|
**kwargs: Additional request parameters
|
|
|
|
Returns:
|
|
Parsed response data
|
|
"""
|
|
return await self._request("DELETE", endpoint, params=params, **kwargs)
|
|
|
|
def _build_endpoint(self, *parts: str) -> str:
|
|
"""Build endpoint path from parts.
|
|
|
|
Args:
|
|
*parts: Path components
|
|
|
|
Returns:
|
|
Formatted endpoint path
|
|
"""
|
|
# Remove empty parts and join with /
|
|
clean_parts = [str(part).strip("/") for part in parts if part]
|
|
return "/" + "/".join(clean_parts)
|