Complete package renaming and platform migration: Package Name Changes: - Rename package from 'wikijs-python-sdk' to 'py-wikijs' - Update setup.py package name - Update pyproject.toml package name - Users can now install with: pip install py-wikijs URL Migration (Gitea → GitHub): - Replace all Gitea URLs with GitHub URLs - Update repository: github.com/l3ocho/py-wikijs - Update issue tracker: github.com/l3ocho/py-wikijs/issues - Update documentation links - Fix URL path format (/src/branch/main/ → /blob/main/) Documentation Updates: - Update README.md badges (PyPI, GitHub) - Update installation instructions (pip install py-wikijs) - Update all doc references to new package name - Update all examples with GitHub URLs - Update DEPLOYMENT_READY.md with new package name - Update deployment.md with new package name Testing: - Successfully built py_wikijs-0.1.0.tar.gz (138 KB) - Successfully built py_wikijs-0.1.0-py3-none-any.whl (66 KB) - Package installs correctly: pip install py-wikijs - Imports work: from wikijs import WikiJSClient - Package metadata correct (Home-page: github.com/l3ocho/py-wikijs) Breaking Changes: - Package name changed from wikijs-python-sdk to py-wikijs - Repository migrated from Gitea to GitHub - All URLs updated to GitHub Users should now: pip install py-wikijs # Instead of wikijs-python-sdk 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
399 lines
13 KiB
Python
399 lines
13 KiB
Python
"""Async users management example for py-wikijs.
|
|
|
|
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())
|