Files
py-wikijs/examples/users_async.py
Claude 5ad98e469e Add comprehensive Users API documentation and examples
Documentation:
- Complete Users API guide (docs/users_api.md)
  - User models overview with validation rules
  - Sync and async usage examples
  - CRUD operations guide
  - Advanced patterns (pagination, bulk ops, concurrent)
  - Error handling best practices
  - Complete API reference

Examples:
- Basic sync operations (examples/users_basic.py)
  - List, search, CRUD operations
  - Group management
  - Bulk operations
  - Pagination patterns
  - Error handling demonstrations

- Async operations (examples/users_async.py)
  - Concurrent user fetching
  - Bulk user creation/updates
  - Performance comparisons (sync vs async)
  - Batch updates with progress tracking
  - Advanced error handling patterns

Both examples are production-ready with comprehensive error handling
and demonstrate real-world usage patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 20:21:45 +00:00

399 lines
13 KiB
Python

"""Async users management example for wikijs-python-sdk.
This example demonstrates:
- Async user operations
- Concurrent user processing
- Bulk operations with asyncio.gather
- Performance comparison with sync operations
"""
import asyncio
import time
from typing import List
from wikijs.aio import AsyncWikiJSClient
from wikijs.exceptions import APIError, ValidationError
from wikijs.models import User, UserCreate, UserUpdate
async def basic_async_operations():
"""Demonstrate basic async user operations."""
print("=" * 60)
print("Async Users API - Basic Operations")
print("=" * 60)
# Initialize async client with context manager
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as client:
# 1. List users
print("\n1. Listing all users...")
try:
users = await client.users.list()
print(f" Found {len(users)} users")
for user in users[:5]:
print(f" - {user.name} ({user.email})")
except APIError as e:
print(f" Error: {e}")
# 2. Search users
print("\n2. Searching for users...")
try:
results = await client.users.search("admin", limit=5)
print(f" Found {len(results)} matching users")
except APIError as e:
print(f" Error: {e}")
# 3. Create user
print("\n3. Creating a new user...")
try:
new_user_data = UserCreate(
email="asynctest@example.com",
name="Async Test User",
password_raw="SecurePassword123",
location="Remote",
job_title="Engineer",
)
created_user = await client.users.create(new_user_data)
print(f" ✓ Created: {created_user.name} (ID: {created_user.id})")
test_user_id = created_user.id
except (ValidationError, APIError) as e:
print(f" ✗ Error: {e}")
return
# 4. Get user
print(f"\n4. Getting user {test_user_id}...")
try:
user = await client.users.get(test_user_id)
print(f" User: {user.name}")
print(f" Email: {user.email}")
print(f" Location: {user.location}")
except APIError as e:
print(f" Error: {e}")
# 5. Update user
print(f"\n5. Updating user...")
try:
update_data = UserUpdate(
name="Updated Async User", location="San Francisco"
)
updated_user = await client.users.update(test_user_id, update_data)
print(f" ✓ Updated: {updated_user.name}")
print(f" Location: {updated_user.location}")
except APIError as e:
print(f" Error: {e}")
# 6. Delete user
print(f"\n6. Deleting test user...")
try:
await client.users.delete(test_user_id)
print(f" ✓ User deleted")
except APIError as e:
print(f" Error: {e}")
async def concurrent_user_fetch():
"""Demonstrate concurrent user fetching for better performance."""
print("\n" + "=" * 60)
print("Concurrent User Fetching")
print("=" * 60)
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as client:
# Get list of user IDs
print("\n1. Getting list of users...")
users = await client.users.list(limit=10)
user_ids = [user.id for user in users]
print(f" Will fetch {len(user_ids)} users concurrently")
# Fetch all users concurrently
print("\n2. Fetching users concurrently...")
start_time = time.time()
tasks = [client.users.get(user_id) for user_id in user_ids]
fetched_users = await asyncio.gather(*tasks, return_exceptions=True)
elapsed = time.time() - start_time
# Process results
successful = [u for u in fetched_users if isinstance(u, User)]
failed = [u for u in fetched_users if isinstance(u, Exception)]
print(f" ✓ Fetched {len(successful)} users successfully")
print(f" ✗ Failed: {len(failed)}")
print(f" ⏱ Time: {elapsed:.2f}s")
print(f" 📊 Average: {elapsed/len(user_ids):.3f}s per user")
async def bulk_user_creation():
"""Demonstrate bulk user creation with concurrent operations."""
print("\n" + "=" * 60)
print("Bulk User Creation (Concurrent)")
print("=" * 60)
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as client:
# Prepare user data
print("\n1. Preparing user data...")
users_to_create = [
UserCreate(
email=f"bulkuser{i}@example.com",
name=f"Bulk User {i}",
password_raw=f"SecurePass{i}123",
location="Test Location",
job_title="Test Engineer",
)
for i in range(1, 6)
]
print(f" Prepared {len(users_to_create)} users")
# Create all users concurrently
print("\n2. Creating users concurrently...")
start_time = time.time()
tasks = [client.users.create(user_data) for user_data in users_to_create]
results = await asyncio.gather(*tasks, return_exceptions=True)
elapsed = time.time() - start_time
# Process results
created_users = [r for r in results if isinstance(r, User)]
failed = [r for r in results if isinstance(r, Exception)]
print(f" ✓ Created: {len(created_users)} users")
print(f" ✗ Failed: {len(failed)}")
print(f" ⏱ Time: {elapsed:.2f}s")
# Show created users
for user in created_users:
print(f" - {user.name} (ID: {user.id})")
# Update all users concurrently
if created_users:
print("\n3. Updating all users concurrently...")
update_data = UserUpdate(location="Updated Location", is_verified=True)
tasks = [
client.users.update(user.id, update_data) for user in created_users
]
updated_users = await asyncio.gather(*tasks, return_exceptions=True)
successful_updates = [u for u in updated_users if isinstance(u, User)]
print(f" ✓ Updated: {len(successful_updates)} users")
# Delete all test users
if created_users:
print("\n4. Cleaning up (deleting test users)...")
tasks = [client.users.delete(user.id) for user in created_users]
results = await asyncio.gather(*tasks, return_exceptions=True)
successful_deletes = [r for r in results if r is True]
print(f" ✓ Deleted: {len(successful_deletes)} users")
async def performance_comparison():
"""Compare sync vs async performance."""
print("\n" + "=" * 60)
print("Performance Comparison: Sync vs Async")
print("=" * 60)
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as async_client:
# Get list of user IDs
users = await async_client.users.list(limit=20)
user_ids = [user.id for user in users[:10]] # Use first 10
print(f"\nFetching {len(user_ids)} users...")
# Async concurrent fetching
print("\n1. Async (concurrent):")
start_time = time.time()
tasks = [async_client.users.get(user_id) for user_id in user_ids]
async_results = await asyncio.gather(*tasks, return_exceptions=True)
async_time = time.time() - start_time
async_successful = len([r for r in async_results if isinstance(r, User)])
print(f" Fetched: {async_successful} users")
print(f" Time: {async_time:.2f}s")
print(f" Rate: {len(user_ids)/async_time:.1f} users/sec")
# Async sequential fetching (for comparison)
print("\n2. Async (sequential):")
start_time = time.time()
sequential_results = []
for user_id in user_ids:
try:
user = await async_client.users.get(user_id)
sequential_results.append(user)
except Exception as e:
sequential_results.append(e)
sequential_time = time.time() - start_time
seq_successful = len([r for r in sequential_results if isinstance(r, User)])
print(f" Fetched: {seq_successful} users")
print(f" Time: {sequential_time:.2f}s")
print(f" Rate: {len(user_ids)/sequential_time:.1f} users/sec")
# Calculate speedup
speedup = sequential_time / async_time
print(f"\n📊 Performance Summary:")
print(f" Concurrent speedup: {speedup:.1f}x faster")
print(f" Time saved: {sequential_time - async_time:.2f}s")
async def batch_user_updates():
"""Demonstrate batch updates with progress tracking."""
print("\n" + "=" * 60)
print("Batch User Updates with Progress Tracking")
print("=" * 60)
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as client:
# Get users to update
print("\n1. Finding users to update...")
users = await client.users.list(limit=10)
print(f" Found {len(users)} users")
# Update all users concurrently with progress
print("\n2. Updating users...")
update_data = UserUpdate(is_verified=True)
async def update_with_progress(user: User, index: int, total: int):
"""Update user and show progress."""
try:
updated = await client.users.update(user.id, update_data)
print(f" [{index}/{total}] ✓ Updated: {updated.name}")
return updated
except Exception as e:
print(f" [{index}/{total}] ✗ Failed: {user.name} - {e}")
return e
tasks = [
update_with_progress(user, i + 1, len(users))
for i, user in enumerate(users)
]
results = await asyncio.gather(*tasks)
# Summary
successful = len([r for r in results if isinstance(r, User)])
failed = len([r for r in results if isinstance(r, Exception)])
print(f"\n Summary:")
print(f" ✓ Successful: {successful}")
print(f" ✗ Failed: {failed}")
async def advanced_error_handling():
"""Demonstrate advanced error handling patterns."""
print("\n" + "=" * 60)
print("Advanced Error Handling")
print("=" * 60)
async with AsyncWikiJSClient(
base_url="https://wiki.example.com", auth="your-api-key-here"
) as client:
print("\n1. Individual error handling:")
# Try to create multiple users with mixed valid/invalid data
test_users = [
{
"email": "valid1@example.com",
"name": "Valid User 1",
"password_raw": "SecurePass123",
},
{
"email": "invalid-email",
"name": "Invalid Email",
"password_raw": "SecurePass123",
},
{
"email": "valid2@example.com",
"name": "Valid User 2",
"password_raw": "123",
}, # Weak password
{
"email": "valid3@example.com",
"name": "Valid User 3",
"password_raw": "SecurePass123",
},
]
async def create_user_safe(user_data: dict):
"""Create user with error handling."""
try:
validated_data = UserCreate(**user_data)
user = await client.users.create(validated_data)
print(f" ✓ Created: {user.name}")
return user
except ValidationError as e:
print(f" ✗ Validation error for {user_data.get('email')}: {e}")
return None
except APIError as e:
print(f" ✗ API error for {user_data.get('email')}: {e}")
return None
results = await asyncio.gather(*[create_user_safe(u) for u in test_users])
# Clean up created users
created = [r for r in results if r is not None]
if created:
print(f"\n2. Cleaning up {len(created)} created users...")
await asyncio.gather(*[client.users.delete(u.id) for u in created])
print(" ✓ Cleanup complete")
async def main():
"""Run all async examples."""
try:
# Basic operations
await basic_async_operations()
# Concurrent operations
await concurrent_user_fetch()
# Bulk operations
await bulk_user_creation()
# Performance comparison
await performance_comparison()
# Batch updates
await batch_user_updates()
# Error handling
await advanced_error_handling()
print("\n" + "=" * 60)
print("All examples completed!")
print("=" * 60)
except KeyboardInterrupt:
print("\n\nInterrupted by user")
except Exception as e:
print(f"\n\nUnexpected error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
# Run all examples
asyncio.run(main())