ready for try

This commit is contained in:
2025-07-29 20:16:11 -04:00
parent 29001b02a5
commit 18a82711cb
33 changed files with 7446 additions and 47 deletions

305
examples/README.md Normal file
View File

@@ -0,0 +1,305 @@
# Examples
This directory contains practical examples demonstrating how to use the Wiki.js Python SDK for various tasks.
## 📁 Example Files
### [`basic_usage.py`](basic_usage.py)
**Getting Started Examples**
Demonstrates fundamental operations:
- Connecting to Wiki.js
- Listing and searching pages
- Creating, updating, and deleting pages
- Working with page metadata and tags
- Basic error handling
**Usage:**
```bash
export WIKIJS_URL='https://your-wiki.example.com'
export WIKIJS_API_KEY='your-api-key'
python examples/basic_usage.py
```
### [`content_management.py`](content_management.py)
**Advanced Content Management**
Shows advanced content operations:
- Template-based page creation
- Bulk operations and batch processing
- Content migration and format conversion
- Content auditing and analysis
- Automated content updates
**Usage:**
```bash
export WIKIJS_URL='https://your-wiki.example.com'
export WIKIJS_API_KEY='your-api-key'
python examples/content_management.py
```
## 🚀 Quick Start
1. **Set up your environment:**
```bash
# Clone the repository
git clone https://github.com/yourusername/wikijs-python-sdk
cd wikijs-python-sdk
# Install the SDK
pip install -e .
# Set environment variables
export WIKIJS_URL='https://your-wiki.example.com'
export WIKIJS_API_KEY='your-api-key'
```
2. **Get your API key:**
- Log into your Wiki.js admin panel
- Go to Administration → API Keys
- Create a new API key with appropriate permissions
- Copy the generated key
3. **Run an example:**
```bash
python examples/basic_usage.py
```
## 📋 Example Scenarios
### Content Creation Workflows
```python
from wikijs import WikiJSClient
from wikijs.models import PageCreate
# Template-based page creation
def create_meeting_notes(client, meeting_data):
content = f"""# {meeting_data['title']}
**Date:** {meeting_data['date']}
**Attendees:** {', '.join(meeting_data['attendees'])}
## Agenda
{meeting_data['agenda']}
## Action Items
{meeting_data['actions']}
"""
page_data = PageCreate(
title=meeting_data['title'],
path=f"meetings/{meeting_data['date']}-{meeting_data['slug']}",
content=content,
tags=['meeting'] + meeting_data.get('tags', [])
)
return client.pages.create(page_data)
```
### Content Analysis
```python
def analyze_wiki_health(client):
"""Analyze wiki content health metrics."""
pages = client.pages.list()
# Calculate metrics
total_pages = len(pages)
published_pages = len([p for p in pages if p.is_published])
tagged_pages = len([p for p in pages if p.tags])
# Word count analysis
word_counts = [p.word_count for p in pages]
avg_words = sum(word_counts) / len(word_counts) if word_counts else 0
return {
'total_pages': total_pages,
'published_ratio': published_pages / total_pages,
'tagged_ratio': tagged_pages / total_pages,
'avg_word_count': avg_words
}
```
### Batch Operations
```python
def bulk_update_tags(client, search_term, new_tags):
"""Add tags to pages matching a search term."""
pages = client.pages.search(search_term)
updated_count = 0
for page in pages:
try:
# Merge existing and new tags
updated_tags = list(set(page.tags + new_tags))
update_data = PageUpdate(tags=updated_tags)
client.pages.update(page.id, update_data)
updated_count += 1
except Exception as e:
print(f"Failed to update {page.title}: {e}")
return updated_count
```
## 🛠️ Development Examples
### Custom Authentication
```python
from wikijs.auth import AuthHandler
class CustomAuth(AuthHandler):
"""Custom authentication handler example."""
def __init__(self, custom_token):
self.token = custom_token
def get_headers(self):
return {
'Authorization': f'Custom {self.token}',
'X-Custom-Header': 'MyApp/1.0'
}
def validate_credentials(self):
if not self.token:
raise ValueError("Custom token is required")
# Usage
client = WikiJSClient(
base_url="https://wiki.example.com",
auth=CustomAuth("your-custom-token")
)
```
### Error Handling Patterns
```python
from wikijs.exceptions import (
APIError, AuthenticationError, ValidationError,
ConnectionError, TimeoutError
)
def robust_page_operation(client, operation_func):
"""Wrapper for robust page operations with retry logic."""
max_retries = 3
retry_delay = 1
for attempt in range(max_retries):
try:
return operation_func()
except (ConnectionError, TimeoutError) as e:
if attempt == max_retries - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}. Retrying...")
time.sleep(retry_delay * (2 ** attempt))
except AuthenticationError:
print("Authentication failed. Check your API key.")
raise
except ValidationError as e:
print(f"Invalid input: {e}")
raise
except APIError as e:
print(f"API error: {e}")
raise
# Usage
result = robust_page_operation(
client,
lambda: client.pages.get(123)
)
```
## 🔧 Configuration Examples
### Environment-based Configuration
```python
import os
from wikijs import WikiJSClient
def create_client_from_env():
"""Create client from environment variables."""
config = {
'base_url': os.getenv('WIKIJS_URL'),
'auth': os.getenv('WIKIJS_API_KEY'),
'timeout': int(os.getenv('WIKIJS_TIMEOUT', '30')),
'verify_ssl': os.getenv('WIKIJS_VERIFY_SSL', 'true').lower() == 'true'
}
# Validate required settings
if not config['base_url'] or not config['auth']:
raise ValueError("WIKIJS_URL and WIKIJS_API_KEY are required")
return WikiJSClient(**config)
```
### Configuration File
```python
import json
from wikijs import WikiJSClient
def create_client_from_file(config_file='config.json'):
"""Create client from configuration file."""
with open(config_file, 'r') as f:
config = json.load(f)
return WikiJSClient(
base_url=config['wikijs']['url'],
auth=config['wikijs']['api_key'],
timeout=config.get('timeout', 30),
verify_ssl=config.get('verify_ssl', True)
)
# config.json example:
# {
# "wikijs": {
# "url": "https://wiki.example.com",
# "api_key": "your-api-key"
# },
# "timeout": 45,
# "verify_ssl": true
# }
```
## 📚 Additional Resources
- **[API Reference](../docs/api_reference.md)** - Complete API documentation
- **[User Guide](../docs/user_guide.md)** - Comprehensive usage guide
- **[Contributing](../docs/CONTRIBUTING.md)** - How to contribute to the project
- **[Wiki.js Documentation](https://docs.js.wiki/)** - Official Wiki.js documentation
## 💡 Tips for Success
1. **Always use context managers** for automatic resource cleanup
2. **Handle exceptions appropriately** for robust applications
3. **Use environment variables** for configuration
4. **Test your code** with different scenarios
5. **Be respectful** of the Wiki.js server (don't overwhelm with requests)
6. **Keep your API key secure** and never commit it to version control
## 🆘 Getting Help
If you encounter issues with these examples:
1. **Check your configuration** - Ensure URL and API key are correct
2. **Verify connectivity** - Test that you can reach the Wiki.js instance
3. **Check permissions** - Ensure your API key has necessary permissions
4. **Enable debug logging** - Use logging to see what's happening
5. **Create an issue** - Report bugs or request help on GitHub
---
**Happy coding! 🚀**

170
examples/basic_usage.py Normal file
View File

@@ -0,0 +1,170 @@
#!/usr/bin/env python3
"""
Basic usage examples for the Wiki.js Python SDK.
This script demonstrates fundamental operations like connecting,
listing pages, and basic CRUD operations.
"""
import os
from wikijs import WikiJSClient
from wikijs.models import PageCreate, PageUpdate
from wikijs.exceptions import APIError, AuthenticationError
def main():
"""Run basic usage examples."""
# Get configuration from environment variables
base_url = os.getenv("WIKIJS_URL", "https://wiki.example.com")
api_key = os.getenv("WIKIJS_API_KEY", "your-api-key-here")
print("🚀 Wiki.js Python SDK - Basic Usage Examples")
print("=" * 50)
# Initialize the client
print(f"📡 Connecting to {base_url}...")
try:
with WikiJSClient(base_url=base_url, auth=api_key) as client:
# Test connection
print("🔍 Testing connection...")
if client.test_connection():
print("✅ Connected successfully!")
else:
print("❌ Connection failed!")
return
# Example 1: List all pages
print("\n📚 Example 1: Listing Pages")
print("-" * 30)
pages = client.pages.list(limit=5)
print(f"Found {len(pages)} pages (showing first 5):")
for page in pages:
print(f"{page.title} (ID: {page.id}, Path: /{page.path})")
# Example 2: Search for pages
print("\n🔍 Example 2: Searching Pages")
print("-" * 30)
search_results = client.pages.search("guide", limit=3)
print(f"Found {len(search_results)} pages matching 'guide':")
for page in search_results:
print(f"{page.title}")
print(f" Words: {page.word_count}, Reading time: {page.reading_time}min")
# Example 3: Get a specific page
if pages:
print(f"\n📄 Example 3: Getting Page Details")
print("-" * 30)
first_page = pages[0]
page_details = client.pages.get(first_page.id)
print(f"Title: {page_details.title}")
print(f"Path: /{page_details.path}")
print(f"Published: {page_details.is_published}")
print(f"Tags: {', '.join(page_details.tags) if page_details.tags else 'None'}")
print(f"Content preview: {page_details.content[:100]}...")
# Show headings if available
headings = page_details.extract_headings()
if headings:
print(f"Headings: {', '.join(headings[:3])}")
# Example 4: Create a new page
print(f"\n✏️ Example 4: Creating a New Page")
print("-" * 30)
new_page_data = PageCreate(
title="SDK Example Page",
path="sdk-example-page",
content="""# SDK Example Page
This page was created using the Wiki.js Python SDK!
## Features Demonstrated
- Page creation via API
- Markdown content support
- Tag assignment
- Metadata handling
## Next Steps
Try updating this page using the SDK's update functionality.
""",
description="A demonstration page created by the Python SDK",
tags=["sdk", "example", "python", "demo"],
is_published=True,
editor="markdown"
)
try:
created_page = client.pages.create(new_page_data)
print(f"✅ Created page: {created_page.title} (ID: {created_page.id})")
# Example 5: Update the created page
print(f"\n🔄 Example 5: Updating the Page")
print("-" * 30)
update_data = PageUpdate(
content=created_page.content + "\n\n## Update Log\n\n- Page updated via SDK!",
tags=created_page.tags + ["updated"]
)
updated_page = client.pages.update(created_page.id, update_data)
print(f"✅ Updated page: {updated_page.title}")
print(f" New tag count: {len(updated_page.tags)}")
# Example 6: Get page by path
print(f"\n🔍 Example 6: Getting Page by Path")
print("-" * 30)
page_by_path = client.pages.get_by_path("sdk-example-page")
print(f"Retrieved page: {page_by_path.title}")
print(f"Same page? {page_by_path.id == created_page.id}")
# Cleanup: Delete the created page
print(f"\n🗑️ Cleaning up: Deleting the example page")
print("-" * 30)
if client.pages.delete(created_page.id):
print("✅ Example page deleted successfully")
else:
print("❌ Failed to delete example page")
except APIError as e:
print(f"❌ Failed to create page: {e}")
# Example 7: Working with tags
print(f"\n🏷️ Example 7: Working with Tags")
print("-" * 30)
# Find pages with specific tags
tagged_pages = client.pages.get_by_tags(["tutorial"], limit=3)
print(f"Found {len(tagged_pages)} pages with 'tutorial' tag:")
for page in tagged_pages:
print(f"{page.title}")
print(f" All tags: {', '.join(page.tags)}")
print(f"\n✨ All examples completed successfully!")
except AuthenticationError:
print("❌ Authentication failed!")
print("💡 Please check your API key and permissions")
except Exception as e:
print(f"❌ Unexpected error: {e}")
if __name__ == "__main__":
print("💡 Before running this example:")
print(" export WIKIJS_URL='https://your-wiki.example.com'")
print(" export WIKIJS_API_KEY='your-api-key'")
print()
main()

View File

@@ -0,0 +1,429 @@
#!/usr/bin/env python3
"""
Content management examples for the Wiki.js Python SDK.
This script demonstrates advanced content management operations
like bulk operations, content migration, and template usage.
"""
import os
import time
from datetime import datetime
from wikijs import WikiJSClient
from wikijs.models import PageCreate, PageUpdate
from wikijs.exceptions import APIError
def create_page_template(template_type, **kwargs):
"""Create page content from templates."""
templates = {
"meeting_notes": """# {title}
**Date:** {date}
**Attendees:** {attendees}
**Duration:** {duration}
## Agenda
{agenda}
## Discussion Points
{discussion}
## Decisions Made
{decisions}
## Action Items
{action_items}
## Next Meeting
**Date:** {next_meeting_date}
**Topics:** {next_meeting_topics}
""",
"project_doc": """# {project_name}
## Project Overview
{overview}
## Objectives
{objectives}
## Scope
### In Scope
{in_scope}
### Out of Scope
{out_of_scope}
## Timeline
{timeline}
## Resources
### Team Members
{team_members}
### Budget
{budget}
## Risks and Mitigation
{risks}
## Success Criteria
{success_criteria}
## Status Updates
*Last updated: {last_updated}*
{status}
""",
"api_doc": """# {api_name} API
## Overview
{overview}
## Base URL
```
{base_url}
```
## Authentication
{authentication}
## Endpoints
### {endpoint_name}
```http
{http_method} {endpoint_path}
```
**Description:** {endpoint_description}
**Parameters:**
{parameters}
**Example Request:**
```json
{example_request}
```
**Example Response:**
```json
{example_response}
```
## Error Codes
{error_codes}
""",
"troubleshooting": """# {title} - Troubleshooting Guide
## Common Issues
### Issue: {issue_1_title}
**Symptoms:** {issue_1_symptoms}
**Cause:** {issue_1_cause}
**Solution:** {issue_1_solution}
### Issue: {issue_2_title}
**Symptoms:** {issue_2_symptoms}
**Cause:** {issue_2_cause}
**Solution:** {issue_2_solution}
## FAQ
{faq}
## Getting Help
{help_info}
## Related Documentation
{related_docs}
"""
}
template = templates.get(template_type)
if not template:
raise ValueError(f"Unknown template type: {template_type}")
return template.format(**kwargs)
def bulk_create_pages(client, pages_data):
"""Create multiple pages with error handling and progress tracking."""
created_pages = []
failed_pages = []
print(f"📝 Creating {len(pages_data)} pages...")
for i, page_data in enumerate(pages_data, 1):
try:
print(f" [{i}/{len(pages_data)}] Creating: {page_data.title}")
created_page = client.pages.create(page_data)
created_pages.append(created_page)
# Be nice to the server
time.sleep(0.2)
except APIError as e:
print(f" ❌ Failed: {e}")
failed_pages.append((page_data.title, str(e)))
print(f"✅ Successfully created {len(created_pages)} pages")
if failed_pages:
print(f"❌ Failed to create {len(failed_pages)} pages:")
for title, error in failed_pages:
print(f"{title}: {error}")
return created_pages, failed_pages
def content_migration_example(client):
"""Demonstrate content migration and format conversion."""
print("🔄 Content Migration Example")
print("-" * 40)
# Find pages that need migration (example: old format markers)
pages_to_migrate = client.pages.search("OLD_FORMAT", limit=5)
if not pages_to_migrate:
print("No pages found that need migration")
return
print(f"Found {len(pages_to_migrate)} pages to migrate")
migration_count = 0
for page in pages_to_migrate:
try:
print(f" Migrating: {page.title}")
# Example migration: Convert old-style headers
new_content = page.content
# Convert old format markers
new_content = new_content.replace("OLD_FORMAT", "")
new_content = new_content.replace("==Header==", "## Header")
new_content = new_content.replace("===Subheader===", "### Subheader")
# Add migration notice
migration_notice = f"\n\n---\n*Migrated on {datetime.now().strftime('%Y-%m-%d')}*\n"
new_content += migration_notice
# Update the page
update_data = PageUpdate(
content=new_content,
tags=page.tags + ["migrated"] if page.tags else ["migrated"]
)
client.pages.update(page.id, update_data)
migration_count += 1
except APIError as e:
print(f" ❌ Migration failed: {e}")
print(f"✅ Successfully migrated {migration_count} pages")
def content_audit_example(client):
"""Perform a content audit to analyze wiki structure."""
print("📊 Content Audit Example")
print("-" * 40)
# Get all pages for analysis
all_pages = client.pages.list()
print(f"📚 Total pages: {len(all_pages)}")
# Analyze by status
published = [p for p in all_pages if p.is_published]
private = [p for p in all_pages if p.is_private]
print(f"📖 Published: {len(published)}")
print(f"🔒 Private: {len(private)}")
# Analyze by tags
all_tags = set()
for page in all_pages:
if page.tags:
all_tags.update(page.tags)
print(f"🏷️ Unique tags: {len(all_tags)}")
# Find most common tags
tag_counts = {}
for page in all_pages:
if page.tags:
for tag in page.tags:
tag_counts[tag] = tag_counts.get(tag, 0) + 1
if tag_counts:
top_tags = sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:5]
print("🔥 Most common tags:")
for tag, count in top_tags:
print(f"{tag}: {count} pages")
# Analyze content length
word_counts = [p.word_count for p in all_pages]
if word_counts:
avg_words = sum(word_counts) / len(word_counts)
max_words = max(word_counts)
min_words = min(word_counts)
print(f"📝 Content analysis:")
print(f" • Average words: {avg_words:.0f}")
print(f" • Longest page: {max_words} words")
print(f" • Shortest page: {min_words} words")
# Find pages without tags
untagged = [p for p in all_pages if not p.tags]
if untagged:
print(f"⚠️ Pages without tags: {len(untagged)}")
print(" Consider adding tags to improve organization")
# Find very short pages (potential stubs)
stubs = [p for p in all_pages if p.word_count < 50]
if stubs:
print(f"📝 Potential stubs (< 50 words): {len(stubs)}")
for stub in stubs[:3]:
print(f"{stub.title} ({stub.word_count} words)")
def main():
"""Run content management examples."""
base_url = os.getenv("WIKIJS_URL", "https://wiki.example.com")
api_key = os.getenv("WIKIJS_API_KEY", "your-api-key-here")
print("📚 Wiki.js Python SDK - Content Management Examples")
print("=" * 60)
try:
with WikiJSClient(base_url=base_url, auth=api_key) as client:
# Test connection
if not client.test_connection():
print("❌ Connection failed!")
return
print("✅ Connected successfully!")
# Example 1: Template-based page creation
print("\n📝 Example 1: Template-based Page Creation")
print("-" * 50)
# Create meeting notes from template
meeting_content = create_page_template(
"meeting_notes",
title="Weekly Team Sync - Dec 15, 2023",
date="December 15, 2023",
attendees="Alice, Bob, Charlie, Diana",
duration="1 hour",
agenda="• Project updates\n• Q1 planning\n• Process improvements",
discussion="• Discussed current sprint progress\n• Reviewed Q1 roadmap priorities",
decisions="• Approved new deployment process\n• Selected project management tool",
action_items="• Alice: Update documentation by Dec 20\n• Bob: Set up new CI pipeline",
next_meeting_date="December 22, 2023",
next_meeting_topics="Holiday schedule, Q1 kickoff planning"
)
meeting_page = PageCreate(
title="Weekly Team Sync - Dec 15, 2023",
path="meetings/2023-12-15-team-sync",
content=meeting_content,
tags=["meeting", "team", "weekly"],
description="Weekly team synchronization meeting notes"
)
# Create project documentation from template
project_content = create_page_template(
"project_doc",
project_name="Wiki.js Python SDK",
overview="A comprehensive Python SDK for interacting with Wiki.js API",
objectives="• Provide easy-to-use Python interface\n• Support all major Wiki.js features\n• Maintain high code quality",
in_scope="Pages API, authentication, error handling, documentation",
out_of_scope="Advanced admin features, custom plugins",
timeline="• Phase 1: MVP (2 weeks)\n• Phase 2: Advanced features (4 weeks)",
team_members="• Lead Developer: Alice\n• Contributors: Community",
budget="Open source project - volunteer contributions",
risks="• API changes in Wiki.js\n• Community adoption",
success_criteria="• >85% test coverage\n• Complete documentation\n• Community feedback",
last_updated=datetime.now().strftime('%Y-%m-%d'),
status="✅ Phase 1 completed\n🔄 Phase 2 in progress"
)
project_page = PageCreate(
title="Wiki.js Python SDK - Project Documentation",
path="projects/wikijs-python-sdk",
content=project_content,
tags=["project", "sdk", "python", "documentation"],
description="Project documentation for the Wiki.js Python SDK"
)
# Bulk create pages
template_pages = [meeting_page, project_page]
created_pages, failed_pages = bulk_create_pages(client, template_pages)
# Example 2: Content audit
print("\n📊 Example 2: Content Audit")
print("-" * 50)
content_audit_example(client)
# Example 3: Batch operations
print("\n🔄 Example 3: Batch Tag Updates")
print("-" * 50)
# Find pages without descriptions
pages_without_desc = client.pages.list()[:5] # Sample for demo
pages_to_update = [p for p in pages_without_desc if not p.description]
if pages_to_update:
print(f"Found {len(pages_to_update)} pages without descriptions")
update_count = 0
for page in pages_to_update:
try:
# Generate a basic description
description = f"Wiki page about {page.title.lower()}"
update_data = PageUpdate(
description=description,
tags=page.tags + ["auto-description"] if page.tags else ["auto-description"]
)
client.pages.update(page.id, update_data)
update_count += 1
print(f" ✅ Updated: {page.title}")
except APIError as e:
print(f" ❌ Failed to update {page.title}: {e}")
print(f"✅ Updated {update_count} pages with descriptions")
else:
print("All pages already have descriptions!")
# Cleanup created pages
print("\n🧹 Cleaning up example pages...")
for page in created_pages:
try:
client.pages.delete(page.id)
print(f" 🗑️ Deleted: {page.title}")
except APIError as e:
print(f" ❌ Failed to delete {page.title}: {e}")
print("\n✨ Content management examples completed!")
except Exception as e:
print(f"❌ Error: {e}")
if __name__ == "__main__":
print("💡 Before running this example:")
print(" export WIKIJS_URL='https://your-wiki.example.com'")
print(" export WIKIJS_API_KEY='your-api-key'")
print()
main()