Compare commits
2 Commits
main
...
claude/tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ace16f5f0 | ||
|
|
54de1ea8e1 |
287
INSTALLATION_GUIDE.md
Normal file
287
INSTALLATION_GUIDE.md
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
# Installation Guide - py-wikijs
|
||||||
|
|
||||||
|
**Quick reference for installing and using py-wikijs in your projects**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Installation Methods
|
||||||
|
|
||||||
|
### **Method 1: Install from GitHub (Recommended for now)**
|
||||||
|
|
||||||
|
Since this package is not yet on PyPI, install directly from GitHub:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install the latest release (v0.1.0)
|
||||||
|
pip install git+https://github.com/l3ocho/py-wikijs.git@v0.1.0
|
||||||
|
|
||||||
|
# Or install from a specific branch
|
||||||
|
pip install git+https://github.com/l3ocho/py-wikijs.git@main
|
||||||
|
|
||||||
|
# Or install from the current development branch
|
||||||
|
pip install git+https://github.com/l3ocho/py-wikijs.git@claude/test-tool-integration-011CUUU3JXwm8n8waD6UYeea
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Method 2: Install in requirements.txt**
|
||||||
|
|
||||||
|
Add to your `requirements.txt`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
# Install specific version tag
|
||||||
|
git+https://github.com/l3ocho/py-wikijs.git@v0.1.0
|
||||||
|
|
||||||
|
# Or install from main branch
|
||||||
|
git+https://github.com/l3ocho/py-wikijs.git@main
|
||||||
|
```
|
||||||
|
|
||||||
|
Then install:
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Method 3: Install in pyproject.toml (Poetry/Modern Python)**
|
||||||
|
|
||||||
|
Add to your `pyproject.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[project.dependencies]
|
||||||
|
py-wikijs = { git = "https://github.com/l3ocho/py-wikijs.git", tag = "v0.1.0" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Or for Poetry:
|
||||||
|
```toml
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
py-wikijs = { git = "https://github.com/l3ocho/py-wikijs.git", tag = "v0.1.0" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Method 4: Local Development (Editable Install)**
|
||||||
|
|
||||||
|
If you're developing both projects simultaneously:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone https://github.com/l3ocho/py-wikijs.git
|
||||||
|
cd py-wikijs
|
||||||
|
|
||||||
|
# Install in editable mode
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
# Or install with development dependencies
|
||||||
|
pip install -e ".[dev]"
|
||||||
|
|
||||||
|
# Or install with async support
|
||||||
|
pip install -e ".[async]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in your other project, the package will automatically reflect changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Verification
|
||||||
|
|
||||||
|
After installation, verify it works:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check installation
|
||||||
|
python -c "from wikijs import WikiJSClient, __version__; print(f'py-wikijs v{__version__} installed successfully!')"
|
||||||
|
|
||||||
|
# Should output: py-wikijs v0.1.0 installed successfully!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Basic Usage in Your Project
|
||||||
|
|
||||||
|
### **Simple Example**
|
||||||
|
|
||||||
|
Create a file `test_wikijs.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
# Initialize client with API key
|
||||||
|
client = WikiJSClient(
|
||||||
|
url='https://your-wiki.example.com',
|
||||||
|
auth='your-api-key-here'
|
||||||
|
)
|
||||||
|
|
||||||
|
# List all pages
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"Found {len(pages)} pages")
|
||||||
|
|
||||||
|
# Get a specific page
|
||||||
|
page = client.pages.get(page_id=1)
|
||||||
|
print(f"Page title: {page.title}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### **With Environment Variables (Recommended)**
|
||||||
|
|
||||||
|
Create `.env` file:
|
||||||
|
```env
|
||||||
|
WIKIJS_URL=https://your-wiki.example.com
|
||||||
|
WIKIJS_API_KEY=your-api-key-here
|
||||||
|
```
|
||||||
|
|
||||||
|
In your code:
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
# Load from environment
|
||||||
|
client = WikiJSClient(
|
||||||
|
url=os.getenv('WIKIJS_URL'),
|
||||||
|
auth=os.getenv('WIKIJS_API_KEY')
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Advanced Features**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Enable debug logging
|
||||||
|
client = WikiJSClient(
|
||||||
|
url='https://wiki.example.com',
|
||||||
|
auth='your-api-key',
|
||||||
|
log_level=logging.DEBUG,
|
||||||
|
rate_limit=10.0, # 10 requests/second
|
||||||
|
timeout=30.0 # 30 second timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a new page
|
||||||
|
from wikijs.models import PageCreate
|
||||||
|
|
||||||
|
new_page = client.pages.create(PageCreate(
|
||||||
|
title="My New Page",
|
||||||
|
path="documentation/my-new-page",
|
||||||
|
content="# Welcome\n\nThis is my new page!",
|
||||||
|
description="A new documentation page",
|
||||||
|
is_published=True,
|
||||||
|
is_private=False,
|
||||||
|
locale="en",
|
||||||
|
tags=["documentation", "tutorial"]
|
||||||
|
))
|
||||||
|
|
||||||
|
print(f"Created page: {new_page.title} (ID: {new_page.id})")
|
||||||
|
|
||||||
|
# Get metrics
|
||||||
|
metrics = client.get_metrics()
|
||||||
|
print(f"Total requests: {metrics['total_requests']}")
|
||||||
|
print(f"Error rate: {metrics['error_rate']:.2f}%")
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Async Usage (Future - v0.2.0)**
|
||||||
|
|
||||||
|
When async support is released:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from wikijs.aio import AsyncWikiJSClient
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async with AsyncWikiJSClient(
|
||||||
|
url='https://wiki.example.com',
|
||||||
|
auth='your-api-key'
|
||||||
|
) as client:
|
||||||
|
pages = await client.pages.list()
|
||||||
|
print(f"Found {len(pages)} pages")
|
||||||
|
|
||||||
|
# Run with asyncio
|
||||||
|
import asyncio
|
||||||
|
asyncio.run(main())
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Dependencies
|
||||||
|
|
||||||
|
**Required:**
|
||||||
|
- Python >= 3.8
|
||||||
|
- requests >= 2.28.0
|
||||||
|
- pydantic >= 1.10.0
|
||||||
|
- typing-extensions >= 4.0.0
|
||||||
|
|
||||||
|
**Optional:**
|
||||||
|
- aiohttp >= 3.8.0 (for async support - coming in v0.2.0)
|
||||||
|
- click >= 8.0.0 (for CLI tools - future)
|
||||||
|
- rich >= 12.0.0 (for rich output - future)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- **API Reference**: [docs/api_reference.md](docs/api_reference.md)
|
||||||
|
- **User Guide**: [docs/user_guide.md](docs/user_guide.md)
|
||||||
|
- **Examples**: [examples/](examples/)
|
||||||
|
- **Compatibility**: [docs/compatibility.md](docs/compatibility.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Important Notes
|
||||||
|
|
||||||
|
### **Before Going Public:**
|
||||||
|
|
||||||
|
1. ✅ **Version Tag Created**: v0.1.0 is now tagged
|
||||||
|
2. ✅ **Package Structure**: Ready for installation
|
||||||
|
3. ⏳ **PyPI Publishing**: Not yet published (GitHub-only for now)
|
||||||
|
4. ⏳ **GitHub Release**: Consider creating a GitHub Release page
|
||||||
|
|
||||||
|
### **Production Checklist:**
|
||||||
|
|
||||||
|
- [ ] Set up proper Wiki.js instance with API access
|
||||||
|
- [ ] Store API keys securely (use environment variables)
|
||||||
|
- [ ] Enable appropriate logging for production
|
||||||
|
- [ ] Set rate limits to respect your Wiki.js server
|
||||||
|
- [ ] Monitor metrics for performance issues
|
||||||
|
- [ ] Review security best practices in [docs/SECURITY.md](docs/SECURITY.md)
|
||||||
|
|
||||||
|
### **Wiki.js Requirements:**
|
||||||
|
|
||||||
|
- **Supported Versions**: Wiki.js 2.2 through 2.5.x
|
||||||
|
- **Not Supported**: Wiki.js 3.x (different API schema)
|
||||||
|
- **API Access**: Requires valid API key with appropriate permissions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### **Import Error**
|
||||||
|
```python
|
||||||
|
ModuleNotFoundError: No module named 'wikijs'
|
||||||
|
```
|
||||||
|
**Solution**: Ensure package is installed: `pip install git+https://github.com/l3ocho/py-wikijs.git@v0.1.0`
|
||||||
|
|
||||||
|
### **Authentication Error**
|
||||||
|
```python
|
||||||
|
wikijs.exceptions.AuthenticationError: Invalid API key
|
||||||
|
```
|
||||||
|
**Solution**: Check your API key is correct and has necessary permissions in Wiki.js
|
||||||
|
|
||||||
|
### **Connection Error**
|
||||||
|
```python
|
||||||
|
wikijs.exceptions.ConnectionError: Failed to connect to Wiki.js
|
||||||
|
```
|
||||||
|
**Solution**: Verify Wiki.js URL is correct and accessible from your network
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Next Steps
|
||||||
|
|
||||||
|
1. **Install the package** using one of the methods above
|
||||||
|
2. **Get your Wiki.js API key** from your Wiki.js admin panel
|
||||||
|
3. **Test basic connectivity** with a simple script
|
||||||
|
4. **Explore examples** in the [examples/](examples/) directory
|
||||||
|
5. **Read the documentation** for advanced features
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
- **Issues**: https://github.com/l3ocho/py-wikijs/issues
|
||||||
|
- **Discussions**: https://github.com/l3ocho/py-wikijs/discussions
|
||||||
|
- **Documentation**: https://github.com/l3ocho/py-wikijs/tree/main/docs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-25
|
||||||
|
**Package Version**: v0.1.0
|
||||||
|
**Status**: Production Ready (MVP)
|
||||||
545
docs/CONFIGURATION_GUIDE.md
Normal file
545
docs/CONFIGURATION_GUIDE.md
Normal file
@@ -0,0 +1,545 @@
|
|||||||
|
# Configuration Guide - py-wikijs
|
||||||
|
|
||||||
|
Complete guide to configuring the py-wikijs client for your project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Table of Contents
|
||||||
|
|
||||||
|
- [Quick Start](#quick-start)
|
||||||
|
- [Configuration Methods](#configuration-methods)
|
||||||
|
- [Configuration Options](#configuration-options)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Best Practices](#best-practices)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### **Simplest Method (Hardcoded)**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
client = WikiJSClient(
|
||||||
|
url='https://wiki.example.com',
|
||||||
|
auth='your-api-key-here'
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ **Not recommended for production** - credentials should not be hardcoded!
|
||||||
|
|
||||||
|
### **Recommended Method (Environment Variables)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set environment variables
|
||||||
|
export WIKIJS_URL="https://wiki.example.com"
|
||||||
|
export WIKIJS_API_KEY="your-api-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
client = WikiJSClient(
|
||||||
|
url=os.getenv('WIKIJS_URL'),
|
||||||
|
auth=os.getenv('WIKIJS_API_KEY')
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Best Method (Configuration File)**
|
||||||
|
|
||||||
|
Use the config helper (recommended):
|
||||||
|
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
# Auto-detects config file
|
||||||
|
client = create_client_from_config()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Configuration Methods
|
||||||
|
|
||||||
|
py-wikijs supports multiple configuration methods. Choose the one that best fits your workflow.
|
||||||
|
|
||||||
|
### **Method 1: Environment Variables (.env)**
|
||||||
|
|
||||||
|
**Best for**: Development, Docker deployments, 12-factor apps
|
||||||
|
|
||||||
|
#### Setup:
|
||||||
|
|
||||||
|
1. **Copy the example file**:
|
||||||
|
```bash
|
||||||
|
cp examples/config.env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit `.env`** with your settings:
|
||||||
|
```bash
|
||||||
|
WIKIJS_URL=https://wiki.example.com
|
||||||
|
WIKIJS_API_KEY=your-api-key-here
|
||||||
|
WIKIJS_TIMEOUT=30.0
|
||||||
|
WIKIJS_RATE_LIMIT=10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Load in your code**:
|
||||||
|
```python
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
client = create_client_from_config()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Advantages:
|
||||||
|
- ✅ Keep secrets out of code
|
||||||
|
- ✅ Easy to change without code modification
|
||||||
|
- ✅ Works great with Docker/containers
|
||||||
|
- ✅ Standard 12-factor app methodology
|
||||||
|
|
||||||
|
#### Requirements:
|
||||||
|
```bash
|
||||||
|
pip install python-dotenv
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Method 2: YAML Configuration**
|
||||||
|
|
||||||
|
**Best for**: Complex configurations, multiple environments
|
||||||
|
|
||||||
|
#### Setup:
|
||||||
|
|
||||||
|
1. **Copy the example file**:
|
||||||
|
```bash
|
||||||
|
cp examples/config.yaml.example config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit `config.yaml`**:
|
||||||
|
```yaml
|
||||||
|
wikijs:
|
||||||
|
url: "https://wiki.example.com"
|
||||||
|
auth:
|
||||||
|
method: "api_key"
|
||||||
|
api_key: "your-api-key-here"
|
||||||
|
|
||||||
|
client:
|
||||||
|
timeout: 30.0
|
||||||
|
rate_limit: 10.0
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level: "INFO"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Load in your code**:
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
client = create_client_from_config('config.yaml')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Advantages:
|
||||||
|
- ✅ Human-readable and editable
|
||||||
|
- ✅ Supports complex nested structures
|
||||||
|
- ✅ Easy to comment and document
|
||||||
|
- ✅ Great for environment-specific configs
|
||||||
|
|
||||||
|
#### Requirements:
|
||||||
|
```bash
|
||||||
|
pip install pyyaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Method 3: JSON Configuration**
|
||||||
|
|
||||||
|
**Best for**: Programmatic configuration, API-driven setups
|
||||||
|
|
||||||
|
#### Setup:
|
||||||
|
|
||||||
|
1. **Copy the example file**:
|
||||||
|
```bash
|
||||||
|
cp examples/config.json.example config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit `config.json`**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"wikijs": {
|
||||||
|
"url": "https://wiki.example.com",
|
||||||
|
"auth": {
|
||||||
|
"method": "api_key",
|
||||||
|
"api_key": "your-api-key-here"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"timeout": 30.0,
|
||||||
|
"rate_limit": 10.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Load in your code**:
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
client = create_client_from_config('config.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Advantages:
|
||||||
|
- ✅ Standard format
|
||||||
|
- ✅ Easy to generate programmatically
|
||||||
|
- ✅ Works with JSON APIs
|
||||||
|
- ✅ No additional dependencies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Method 4: INI Configuration**
|
||||||
|
|
||||||
|
**Best for**: Traditional configurations, legacy systems
|
||||||
|
|
||||||
|
#### Setup:
|
||||||
|
|
||||||
|
1. **Copy the example file**:
|
||||||
|
```bash
|
||||||
|
cp examples/config.ini.example config.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit `config.ini`**:
|
||||||
|
```ini
|
||||||
|
[wikijs]
|
||||||
|
url = https://wiki.example.com
|
||||||
|
auth_method = api_key
|
||||||
|
api_key = your-api-key-here
|
||||||
|
|
||||||
|
[client]
|
||||||
|
timeout = 30.0
|
||||||
|
rate_limit = 10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Load in your code**:
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
client = create_client_from_config('config.ini')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Advantages:
|
||||||
|
- ✅ Simple format
|
||||||
|
- ✅ No dependencies
|
||||||
|
- ✅ Familiar to many developers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Method 5: Python Dictionary**
|
||||||
|
|
||||||
|
**Best for**: Dynamic configuration, testing
|
||||||
|
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
config = {
|
||||||
|
'wikijs': {
|
||||||
|
'url': 'https://wiki.example.com',
|
||||||
|
'auth': {
|
||||||
|
'method': 'api_key',
|
||||||
|
'api_key': 'your-api-key-here'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'client': {
|
||||||
|
'timeout': 30.0,
|
||||||
|
'rate_limit': 10.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Configuration Options
|
||||||
|
|
||||||
|
### **Required Options**
|
||||||
|
|
||||||
|
| Option | Type | Description | Example |
|
||||||
|
|--------|------|-------------|---------|
|
||||||
|
| `wikijs.url` | string | Wiki.js instance URL | `https://wiki.example.com` |
|
||||||
|
| `wikijs.auth.api_key` | string | API key for authentication | `ey12345...` |
|
||||||
|
|
||||||
|
### **Client Options**
|
||||||
|
|
||||||
|
| Option | Type | Default | Description |
|
||||||
|
|--------|------|---------|-------------|
|
||||||
|
| `client.timeout` | float | 30.0 | Request timeout (seconds) |
|
||||||
|
| `client.rate_limit` | float | None | Max requests per second |
|
||||||
|
| `client.max_retries` | int | 3 | Number of retry attempts |
|
||||||
|
| `client.verify_ssl` | bool | true | Verify SSL certificates |
|
||||||
|
| `client.pool_size` | int | 10 | Connection pool size |
|
||||||
|
| `client.user_agent` | string | Auto | Custom User-Agent header |
|
||||||
|
|
||||||
|
### **Authentication Options**
|
||||||
|
|
||||||
|
| Option | Type | Default | Description |
|
||||||
|
|--------|------|---------|-------------|
|
||||||
|
| `wikijs.auth.method` | string | "api_key" | Auth method (api_key, jwt, none) |
|
||||||
|
| `wikijs.auth.api_key` | string | - | API key (for api_key method) |
|
||||||
|
| `wikijs.auth.jwt_token` | string | - | JWT token (for jwt method) |
|
||||||
|
|
||||||
|
### **Logging Options**
|
||||||
|
|
||||||
|
| Option | Type | Default | Description |
|
||||||
|
|--------|------|---------|-------------|
|
||||||
|
| `logging.debug` | bool | false | Enable debug logging |
|
||||||
|
| `logging.level` | string | "INFO" | Log level (DEBUG, INFO, WARNING, ERROR) |
|
||||||
|
| `logging.format` | string | - | Custom log format string |
|
||||||
|
|
||||||
|
### **Metrics Options**
|
||||||
|
|
||||||
|
| Option | Type | Default | Description |
|
||||||
|
|--------|------|---------|-------------|
|
||||||
|
| `metrics.enabled` | bool | true | Enable metrics collection |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Examples
|
||||||
|
|
||||||
|
### **Example 1: Basic Connection**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
# Auto-detect config file
|
||||||
|
client = create_client_from_config()
|
||||||
|
|
||||||
|
# List pages
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"Found {len(pages)} pages")
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Example 2: Multiple Environments**
|
||||||
|
|
||||||
|
**config.yaml**:
|
||||||
|
```yaml
|
||||||
|
environments:
|
||||||
|
production:
|
||||||
|
wikijs:
|
||||||
|
url: "https://wiki.company.com"
|
||||||
|
logging:
|
||||||
|
level: "WARNING"
|
||||||
|
|
||||||
|
staging:
|
||||||
|
wikijs:
|
||||||
|
url: "https://wiki-staging.company.com"
|
||||||
|
logging:
|
||||||
|
level: "INFO"
|
||||||
|
|
||||||
|
development:
|
||||||
|
wikijs:
|
||||||
|
url: "http://localhost:3000"
|
||||||
|
logging:
|
||||||
|
level: "DEBUG"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code**:
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
from examples.config_helper import load_config, create_client_from_config
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
config = load_config('config.yaml')
|
||||||
|
|
||||||
|
# Get environment
|
||||||
|
env = os.getenv('ENVIRONMENT', 'development')
|
||||||
|
env_config = config['environments'][env]
|
||||||
|
|
||||||
|
# Merge with base config
|
||||||
|
config.update(env_config)
|
||||||
|
|
||||||
|
# Create client
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Example 3: Override Configuration**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
# Load from file but override specific values
|
||||||
|
client = create_client_from_config(
|
||||||
|
'config.yaml',
|
||||||
|
timeout=60.0, # Override timeout
|
||||||
|
rate_limit=20.0, # Override rate limit
|
||||||
|
log_level='DEBUG' # Override log level
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Example 4: Docker/Container Deployment**
|
||||||
|
|
||||||
|
**docker-compose.yml**:
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
environment:
|
||||||
|
- WIKIJS_URL=https://wiki.example.com
|
||||||
|
- WIKIJS_API_KEY=${WIKIJS_API_KEY}
|
||||||
|
- WIKIJS_TIMEOUT=30.0
|
||||||
|
- WIKIJS_RATE_LIMIT=10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code** (loads from environment automatically):
|
||||||
|
```python
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
client = create_client_from_config() # Auto-loads from env vars
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Example 5: Testing with Mock Config**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# test_example.py
|
||||||
|
import pytest
|
||||||
|
from examples.config_helper import create_client_from_config
|
||||||
|
|
||||||
|
def test_client_creation():
|
||||||
|
config = {
|
||||||
|
'wikijs': {
|
||||||
|
'url': 'http://test.example.com',
|
||||||
|
'auth': {'api_key': 'test-key'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
assert client.base_url == 'http://test.example.com'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 Best Practices
|
||||||
|
|
||||||
|
### **1. Security**
|
||||||
|
|
||||||
|
#### ✅ **DO:**
|
||||||
|
- Store credentials in environment variables or secure vaults
|
||||||
|
- Use `.env` files for development (add to `.gitignore`)
|
||||||
|
- Rotate API keys regularly
|
||||||
|
- Use least-privilege API keys
|
||||||
|
|
||||||
|
#### ❌ **DON'T:**
|
||||||
|
- Hardcode credentials in source code
|
||||||
|
- Commit `.env` files to git
|
||||||
|
- Share API keys in public channels
|
||||||
|
- Use production keys in development
|
||||||
|
|
||||||
|
### **2. Configuration Management**
|
||||||
|
|
||||||
|
#### ✅ **DO:**
|
||||||
|
- Use different configs for each environment
|
||||||
|
- Version control config templates (`.example` files)
|
||||||
|
- Validate configuration on startup
|
||||||
|
- Document all configuration options
|
||||||
|
|
||||||
|
#### ❌ **DON'T:**
|
||||||
|
- Mix environments in the same config
|
||||||
|
- Leave sensitive data in example files
|
||||||
|
- Skip validation checks
|
||||||
|
|
||||||
|
### **3. File Structure**
|
||||||
|
|
||||||
|
Recommended project structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
your-project/
|
||||||
|
├── .env # Local dev config (gitignored)
|
||||||
|
├── config.yaml.example # Template (committed)
|
||||||
|
├── config/
|
||||||
|
│ ├── production.yaml # Production config (no secrets)
|
||||||
|
│ ├── staging.yaml # Staging config
|
||||||
|
│ └── development.yaml # Dev config
|
||||||
|
├── src/
|
||||||
|
│ └── your_app.py
|
||||||
|
└── .gitignore # Ignore .env and config with secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
**.gitignore**:
|
||||||
|
```gitignore
|
||||||
|
.env
|
||||||
|
config.yaml
|
||||||
|
config.json
|
||||||
|
config.ini
|
||||||
|
*.local.yaml
|
||||||
|
*-secret.*
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Troubleshooting
|
||||||
|
|
||||||
|
### **Issue: "No configuration file found"**
|
||||||
|
|
||||||
|
**Solution**: Create a config file from an example:
|
||||||
|
```bash
|
||||||
|
cp examples/config.env.example .env
|
||||||
|
# Edit .env with your settings
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Issue: "WIKIJS_URL is required"**
|
||||||
|
|
||||||
|
**Solution**: Ensure URL is set in your config:
|
||||||
|
```bash
|
||||||
|
# .env file
|
||||||
|
WIKIJS_URL=https://wiki.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Issue: "PyYAML is required"**
|
||||||
|
|
||||||
|
**Solution**: Install YAML support:
|
||||||
|
```bash
|
||||||
|
pip install pyyaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Issue: "Authentication failed"**
|
||||||
|
|
||||||
|
**Solution**: Check your API key:
|
||||||
|
1. Log in to Wiki.js admin panel
|
||||||
|
2. Go to Administration → API Access
|
||||||
|
3. Create or copy an API key
|
||||||
|
4. Update your config with the correct key
|
||||||
|
|
||||||
|
### **Issue: SSL verification fails**
|
||||||
|
|
||||||
|
**Solution**: For self-signed certificates (development only):
|
||||||
|
```python
|
||||||
|
client = create_client_from_config(verify_ssl=False)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in `.env`:
|
||||||
|
```bash
|
||||||
|
WIKIJS_VERIFY_SSL=false
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ **Never disable SSL verification in production!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Additional Resources
|
||||||
|
|
||||||
|
- **Config Examples**: See `examples/` directory for full examples
|
||||||
|
- **API Reference**: [docs/api_reference.md](api_reference.md)
|
||||||
|
- **User Guide**: [docs/user_guide.md](user_guide.md)
|
||||||
|
- **Security**: [docs/SECURITY.md](SECURITY.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Need Help?
|
||||||
|
|
||||||
|
- 📖 **Documentation**: Check [README.md](../README.md)
|
||||||
|
- 🐛 **Issues**: https://github.com/l3ocho/py-wikijs/issues
|
||||||
|
- 💬 **Discussions**: https://github.com/l3ocho/py-wikijs/discussions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-25
|
||||||
|
**py-wikijs Version**: v0.1.0
|
||||||
97
examples/config.env.example
Normal file
97
examples/config.env.example
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# py-wikijs Configuration File
|
||||||
|
# Copy this file to .env and update with your actual values
|
||||||
|
# Usage: Load with python-dotenv package
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# REQUIRED: Wiki.js Connection Settings
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Your Wiki.js instance URL (no trailing slash)
|
||||||
|
WIKIJS_URL=https://wiki.example.com
|
||||||
|
|
||||||
|
# Your Wiki.js API key (get from Admin > API Access)
|
||||||
|
WIKIJS_API_KEY=your-api-key-here
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# OPTIONAL: Client Configuration
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Request timeout in seconds (default: 30.0)
|
||||||
|
WIKIJS_TIMEOUT=30.0
|
||||||
|
|
||||||
|
# Rate limit in requests per second (default: None - no limit)
|
||||||
|
# Set to prevent overwhelming your Wiki.js server
|
||||||
|
WIKIJS_RATE_LIMIT=10.0
|
||||||
|
|
||||||
|
# Maximum number of retries for failed requests (default: 3)
|
||||||
|
WIKIJS_MAX_RETRIES=3
|
||||||
|
|
||||||
|
# Enable debug logging (default: false)
|
||||||
|
# Options: true, false
|
||||||
|
WIKIJS_DEBUG=false
|
||||||
|
|
||||||
|
# Log level (default: INFO)
|
||||||
|
# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||||
|
WIKIJS_LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# OPTIONAL: Authentication Settings
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Authentication method (default: api_key)
|
||||||
|
# Options: api_key, jwt, none
|
||||||
|
WIKIJS_AUTH_METHOD=api_key
|
||||||
|
|
||||||
|
# JWT Token (if using JWT authentication)
|
||||||
|
# WIKIJS_JWT_TOKEN=your-jwt-token-here
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# OPTIONAL: Advanced Settings
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Verify SSL certificates (default: true)
|
||||||
|
# Set to false only for development with self-signed certificates
|
||||||
|
WIKIJS_VERIFY_SSL=true
|
||||||
|
|
||||||
|
# Custom User-Agent header
|
||||||
|
# WIKIJS_USER_AGENT=MyApp/1.0 py-wikijs/0.1.0
|
||||||
|
|
||||||
|
# Connection pool size (default: 10)
|
||||||
|
WIKIJS_POOL_SIZE=10
|
||||||
|
|
||||||
|
# Enable metrics collection (default: true)
|
||||||
|
WIKIJS_ENABLE_METRICS=true
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# OPTIONAL: Cache Settings (for future versions)
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Enable caching (default: false)
|
||||||
|
# WIKIJS_CACHE_ENABLED=false
|
||||||
|
|
||||||
|
# Cache TTL in seconds (default: 300)
|
||||||
|
# WIKIJS_CACHE_TTL=300
|
||||||
|
|
||||||
|
# Cache backend (default: memory)
|
||||||
|
# Options: memory, redis, file
|
||||||
|
# WIKIJS_CACHE_BACKEND=memory
|
||||||
|
|
||||||
|
# Redis URL (if using redis cache backend)
|
||||||
|
# WIKIJS_REDIS_URL=redis://localhost:6379/0
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# NOTES
|
||||||
|
# ============================================================
|
||||||
|
#
|
||||||
|
# 1. Security: NEVER commit .env files to git!
|
||||||
|
# Add .env to your .gitignore file
|
||||||
|
#
|
||||||
|
# 2. Loading: Use python-dotenv to load this file:
|
||||||
|
# pip install python-dotenv
|
||||||
|
# from dotenv import load_dotenv
|
||||||
|
# load_dotenv()
|
||||||
|
#
|
||||||
|
# 3. Override: Environment variables set in shell take precedence
|
||||||
|
#
|
||||||
|
# 4. Validation: Use the config helper to validate settings
|
||||||
|
# See examples/config_helper.py
|
||||||
91
examples/config.ini.example
Normal file
91
examples/config.ini.example
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# py-wikijs INI Configuration File
|
||||||
|
# Copy this file to config.ini and update with your actual values
|
||||||
|
# Usage: Load with Python's configparser
|
||||||
|
|
||||||
|
[wikijs]
|
||||||
|
# Your Wiki.js instance URL (required)
|
||||||
|
url = https://wiki.example.com
|
||||||
|
|
||||||
|
# Authentication method: api_key, jwt, or none
|
||||||
|
auth_method = api_key
|
||||||
|
|
||||||
|
# Your Wiki.js API key
|
||||||
|
api_key = your-api-key-here
|
||||||
|
|
||||||
|
# JWT token (alternative to API key)
|
||||||
|
# jwt_token = your-jwt-token-here
|
||||||
|
|
||||||
|
[client]
|
||||||
|
# Request timeout in seconds
|
||||||
|
timeout = 30.0
|
||||||
|
|
||||||
|
# Rate limit in requests per second (0 = no limit)
|
||||||
|
rate_limit = 10.0
|
||||||
|
|
||||||
|
# Maximum retry attempts
|
||||||
|
max_retries = 3
|
||||||
|
|
||||||
|
# Verify SSL certificates (true/false)
|
||||||
|
verify_ssl = true
|
||||||
|
|
||||||
|
# Connection pool size
|
||||||
|
pool_size = 10
|
||||||
|
|
||||||
|
# Custom User-Agent header
|
||||||
|
user_agent = MyApp/1.0 py-wikijs/0.1.0
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
# Enable debug logging (true/false)
|
||||||
|
debug = false
|
||||||
|
|
||||||
|
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||||
|
level = INFO
|
||||||
|
|
||||||
|
# Log format string
|
||||||
|
format = %%(asctime)s - %%(name)s - %%(levelname)s - %%(message)s
|
||||||
|
|
||||||
|
# Enable file logging (true/false)
|
||||||
|
file_enabled = false
|
||||||
|
|
||||||
|
# Log file path
|
||||||
|
file_path = /var/log/wikijs-client.log
|
||||||
|
|
||||||
|
# Max log file size in bytes
|
||||||
|
file_max_bytes = 10485760
|
||||||
|
|
||||||
|
# Number of backup log files
|
||||||
|
file_backup_count = 5
|
||||||
|
|
||||||
|
[metrics]
|
||||||
|
# Enable metrics collection (true/false)
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Metrics format: prometheus, json, statsd
|
||||||
|
format = prometheus
|
||||||
|
|
||||||
|
[cache]
|
||||||
|
# Enable caching (true/false)
|
||||||
|
enabled = false
|
||||||
|
|
||||||
|
# Cache backend: memory, redis, file
|
||||||
|
backend = memory
|
||||||
|
|
||||||
|
# Cache TTL in seconds
|
||||||
|
ttl = 300
|
||||||
|
|
||||||
|
# Maximum cache size (entries)
|
||||||
|
max_size = 1000
|
||||||
|
|
||||||
|
[cache.redis]
|
||||||
|
# Redis connection URL (if using redis backend)
|
||||||
|
url = redis://localhost:6379/0
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Enable async support (true/false)
|
||||||
|
async_enabled = false
|
||||||
|
|
||||||
|
# Enable batch operations (true/false)
|
||||||
|
batch_enabled = true
|
||||||
|
|
||||||
|
# Enable auto-pagination (true/false)
|
||||||
|
auto_pagination = true
|
||||||
51
examples/config.json.example
Normal file
51
examples/config.json.example
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"_comment": "py-wikijs JSON Configuration File",
|
||||||
|
"_usage": "Copy to config.json and update with your values",
|
||||||
|
|
||||||
|
"wikijs": {
|
||||||
|
"url": "https://wiki.example.com",
|
||||||
|
"auth": {
|
||||||
|
"method": "api_key",
|
||||||
|
"api_key": "your-api-key-here"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"client": {
|
||||||
|
"timeout": 30.0,
|
||||||
|
"rate_limit": 10.0,
|
||||||
|
"max_retries": 3,
|
||||||
|
"verify_ssl": true,
|
||||||
|
"pool_size": 10,
|
||||||
|
"user_agent": "MyApp/1.0 py-wikijs/0.1.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
"logging": {
|
||||||
|
"debug": false,
|
||||||
|
"level": "INFO",
|
||||||
|
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||||
|
"file": {
|
||||||
|
"enabled": false,
|
||||||
|
"path": "/var/log/wikijs-client.log",
|
||||||
|
"max_bytes": 10485760,
|
||||||
|
"backup_count": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"metrics": {
|
||||||
|
"enabled": true,
|
||||||
|
"format": "prometheus"
|
||||||
|
},
|
||||||
|
|
||||||
|
"cache": {
|
||||||
|
"enabled": false,
|
||||||
|
"backend": "memory",
|
||||||
|
"ttl": 300,
|
||||||
|
"max_size": 1000
|
||||||
|
},
|
||||||
|
|
||||||
|
"features": {
|
||||||
|
"async_enabled": false,
|
||||||
|
"batch_enabled": true,
|
||||||
|
"auto_pagination": true
|
||||||
|
}
|
||||||
|
}
|
||||||
161
examples/config.yaml.example
Normal file
161
examples/config.yaml.example
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# py-wikijs YAML Configuration File
|
||||||
|
# Copy this file to config.yaml and update with your actual values
|
||||||
|
# Usage: Load with PyYAML package
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Wiki.js Connection Settings
|
||||||
|
# ============================================================
|
||||||
|
wikijs:
|
||||||
|
# Your Wiki.js instance URL (required)
|
||||||
|
url: "https://wiki.example.com"
|
||||||
|
|
||||||
|
# Authentication settings
|
||||||
|
auth:
|
||||||
|
# Method: api_key, jwt, or none
|
||||||
|
method: "api_key"
|
||||||
|
|
||||||
|
# API key (get from Admin > API Access)
|
||||||
|
api_key: "your-api-key-here"
|
||||||
|
|
||||||
|
# JWT token (alternative to API key)
|
||||||
|
# jwt_token: "your-jwt-token-here"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Client Configuration
|
||||||
|
# ============================================================
|
||||||
|
client:
|
||||||
|
# Request timeout in seconds
|
||||||
|
timeout: 30.0
|
||||||
|
|
||||||
|
# Rate limiting (requests per second)
|
||||||
|
# Set to null for no limit
|
||||||
|
rate_limit: 10.0
|
||||||
|
|
||||||
|
# Maximum retry attempts
|
||||||
|
max_retries: 3
|
||||||
|
|
||||||
|
# Verify SSL certificates
|
||||||
|
verify_ssl: true
|
||||||
|
|
||||||
|
# Connection pool size
|
||||||
|
pool_size: 10
|
||||||
|
|
||||||
|
# Custom User-Agent
|
||||||
|
user_agent: "MyApp/1.0 py-wikijs/0.1.0"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Logging Configuration
|
||||||
|
# ============================================================
|
||||||
|
logging:
|
||||||
|
# Enable debug logging
|
||||||
|
debug: false
|
||||||
|
|
||||||
|
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||||
|
level: "INFO"
|
||||||
|
|
||||||
|
# Log format
|
||||||
|
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||||
|
|
||||||
|
# Log to file
|
||||||
|
file:
|
||||||
|
enabled: false
|
||||||
|
path: "/var/log/wikijs-client.log"
|
||||||
|
max_bytes: 10485760 # 10MB
|
||||||
|
backup_count: 5
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Metrics Configuration
|
||||||
|
# ============================================================
|
||||||
|
metrics:
|
||||||
|
# Enable metrics collection
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Metrics export format
|
||||||
|
format: "prometheus" # prometheus, json, statsd
|
||||||
|
|
||||||
|
# Prometheus settings
|
||||||
|
prometheus:
|
||||||
|
port: 9090
|
||||||
|
path: "/metrics"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Cache Configuration (for future versions)
|
||||||
|
# ============================================================
|
||||||
|
cache:
|
||||||
|
# Enable caching
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Cache backend: memory, redis, file
|
||||||
|
backend: "memory"
|
||||||
|
|
||||||
|
# Cache TTL in seconds
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
# Maximum cache size (entries)
|
||||||
|
max_size: 1000
|
||||||
|
|
||||||
|
# Redis settings (if backend is redis)
|
||||||
|
redis:
|
||||||
|
url: "redis://localhost:6379/0"
|
||||||
|
password: null
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
# File cache settings (if backend is file)
|
||||||
|
file:
|
||||||
|
path: "/tmp/wikijs-cache"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Feature Flags
|
||||||
|
# ============================================================
|
||||||
|
features:
|
||||||
|
# Enable async support (requires aiohttp)
|
||||||
|
async_enabled: false
|
||||||
|
|
||||||
|
# Enable batch operations
|
||||||
|
batch_enabled: true
|
||||||
|
|
||||||
|
# Enable auto-pagination
|
||||||
|
auto_pagination: true
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Development Settings
|
||||||
|
# ============================================================
|
||||||
|
development:
|
||||||
|
# Enable development mode
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Mock API responses
|
||||||
|
mock_api: false
|
||||||
|
|
||||||
|
# Save requests/responses for debugging
|
||||||
|
save_debug_data: false
|
||||||
|
debug_data_path: "/tmp/wikijs-debug"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Environment-Specific Overrides
|
||||||
|
# ============================================================
|
||||||
|
environments:
|
||||||
|
production:
|
||||||
|
logging:
|
||||||
|
level: "WARNING"
|
||||||
|
client:
|
||||||
|
verify_ssl: true
|
||||||
|
development:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
staging:
|
||||||
|
wikijs:
|
||||||
|
url: "https://wiki-staging.example.com"
|
||||||
|
logging:
|
||||||
|
level: "INFO"
|
||||||
|
|
||||||
|
development:
|
||||||
|
wikijs:
|
||||||
|
url: "http://localhost:3000"
|
||||||
|
logging:
|
||||||
|
level: "DEBUG"
|
||||||
|
debug: true
|
||||||
|
client:
|
||||||
|
verify_ssl: false
|
||||||
|
development:
|
||||||
|
enabled: true
|
||||||
487
examples/config_helper.py
Executable file
487
examples/config_helper.py
Executable file
@@ -0,0 +1,487 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Configuration helper for py-wikijs.
|
||||||
|
|
||||||
|
This module provides utilities to load configuration from various sources:
|
||||||
|
- Environment variables (.env files)
|
||||||
|
- YAML files
|
||||||
|
- JSON files
|
||||||
|
- INI files
|
||||||
|
- Python dictionaries
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
from config_helper import load_config, create_client_from_config
|
||||||
|
|
||||||
|
# Load config from file
|
||||||
|
config = load_config('config.yaml')
|
||||||
|
|
||||||
|
# Create client from config
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
|
||||||
|
# Or use auto-detection
|
||||||
|
client = create_client_from_config() # Searches for config files
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from configparser import ConfigParser
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
# Optional dependencies
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
YAML_AVAILABLE = True
|
||||||
|
except ImportError:
|
||||||
|
YAML_AVAILABLE = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
DOTENV_AVAILABLE = True
|
||||||
|
except ImportError:
|
||||||
|
DOTENV_AVAILABLE = False
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigLoader:
|
||||||
|
"""Load configuration from various sources."""
|
||||||
|
|
||||||
|
def __init__(self, config_dir: Optional[str] = None):
|
||||||
|
"""Initialize config loader.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_dir: Directory to search for config files (default: current dir)
|
||||||
|
"""
|
||||||
|
self.config_dir = Path(config_dir) if config_dir else Path.cwd()
|
||||||
|
|
||||||
|
def load_env(self, env_file: Optional[str] = None) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from environment variables.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
env_file: Path to .env file (optional)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
"""
|
||||||
|
# Load .env file if available
|
||||||
|
if env_file and DOTENV_AVAILABLE:
|
||||||
|
load_dotenv(env_file)
|
||||||
|
elif DOTENV_AVAILABLE:
|
||||||
|
# Try to find .env in config directory
|
||||||
|
env_path = self.config_dir / ".env"
|
||||||
|
if env_path.exists():
|
||||||
|
load_dotenv(env_path)
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"wikijs": {
|
||||||
|
"url": os.getenv("WIKIJS_URL"),
|
||||||
|
"auth": {
|
||||||
|
"method": os.getenv("WIKIJS_AUTH_METHOD", "api_key"),
|
||||||
|
"api_key": os.getenv("WIKIJS_API_KEY"),
|
||||||
|
"jwt_token": os.getenv("WIKIJS_JWT_TOKEN"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"timeout": float(os.getenv("WIKIJS_TIMEOUT", "30.0")),
|
||||||
|
"rate_limit": (
|
||||||
|
float(os.getenv("WIKIJS_RATE_LIMIT"))
|
||||||
|
if os.getenv("WIKIJS_RATE_LIMIT")
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"max_retries": int(os.getenv("WIKIJS_MAX_RETRIES", "3")),
|
||||||
|
"verify_ssl": os.getenv("WIKIJS_VERIFY_SSL", "true").lower()
|
||||||
|
== "true",
|
||||||
|
"pool_size": int(os.getenv("WIKIJS_POOL_SIZE", "10")),
|
||||||
|
"user_agent": os.getenv("WIKIJS_USER_AGENT"),
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
"debug": os.getenv("WIKIJS_DEBUG", "false").lower() == "true",
|
||||||
|
"level": os.getenv("WIKIJS_LOG_LEVEL", "INFO"),
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"enabled": os.getenv("WIKIJS_ENABLE_METRICS", "true").lower()
|
||||||
|
== "true",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove None values
|
||||||
|
return self._clean_dict(config)
|
||||||
|
|
||||||
|
def load_yaml(self, yaml_file: Union[str, Path]) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from YAML file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
yaml_file: Path to YAML file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ImportError: If PyYAML is not installed
|
||||||
|
"""
|
||||||
|
if not YAML_AVAILABLE:
|
||||||
|
raise ImportError(
|
||||||
|
"PyYAML is required for YAML config files. "
|
||||||
|
"Install with: pip install pyyaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
yaml_path = Path(yaml_file)
|
||||||
|
if not yaml_path.is_absolute():
|
||||||
|
yaml_path = self.config_dir / yaml_path
|
||||||
|
|
||||||
|
with open(yaml_path, "r", encoding="utf-8") as f:
|
||||||
|
return yaml.safe_load(f)
|
||||||
|
|
||||||
|
def load_json(self, json_file: Union[str, Path]) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from JSON file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
json_file: Path to JSON file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
"""
|
||||||
|
json_path = Path(json_file)
|
||||||
|
if not json_path.is_absolute():
|
||||||
|
json_path = self.config_dir / json_path
|
||||||
|
|
||||||
|
with open(json_path, "r", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def load_ini(self, ini_file: Union[str, Path]) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from INI file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ini_file: Path to INI file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
"""
|
||||||
|
ini_path = Path(ini_file)
|
||||||
|
if not ini_path.is_absolute():
|
||||||
|
ini_path = self.config_dir / ini_path
|
||||||
|
|
||||||
|
parser = ConfigParser()
|
||||||
|
parser.read(ini_path)
|
||||||
|
|
||||||
|
config: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
# Convert INI sections to nested dict
|
||||||
|
for section in parser.sections():
|
||||||
|
section_dict: Dict[str, Any] = {}
|
||||||
|
for key, value in parser.items(section):
|
||||||
|
# Convert string values to appropriate types
|
||||||
|
section_dict[key] = self._parse_value(value)
|
||||||
|
|
||||||
|
# Handle nested sections (e.g., cache.redis)
|
||||||
|
if "." in section:
|
||||||
|
parent, child = section.split(".", 1)
|
||||||
|
if parent not in config:
|
||||||
|
config[parent] = {}
|
||||||
|
config[parent][child] = section_dict
|
||||||
|
else:
|
||||||
|
config[section] = section_dict
|
||||||
|
|
||||||
|
# Restructure for consistency with other formats
|
||||||
|
if "wikijs" in config:
|
||||||
|
config["wikijs"]["auth"] = {
|
||||||
|
"method": config["wikijs"].pop("auth_method", "api_key"),
|
||||||
|
"api_key": config["wikijs"].pop("api_key", None),
|
||||||
|
"jwt_token": config["wikijs"].pop("jwt_token", None),
|
||||||
|
}
|
||||||
|
|
||||||
|
if "logging" in config:
|
||||||
|
if "file_enabled" in config["logging"]:
|
||||||
|
config["logging"]["file"] = {
|
||||||
|
"enabled": config["logging"].pop("file_enabled"),
|
||||||
|
"path": config["logging"].pop("file_path", None),
|
||||||
|
"max_bytes": config["logging"].pop("file_max_bytes", None),
|
||||||
|
"backup_count": config["logging"].pop("file_backup_count", None),
|
||||||
|
}
|
||||||
|
|
||||||
|
return self._clean_dict(config)
|
||||||
|
|
||||||
|
def auto_load(self) -> Dict[str, Any]:
|
||||||
|
"""Auto-detect and load configuration from available sources.
|
||||||
|
|
||||||
|
Searches for config files in this order:
|
||||||
|
1. .env file
|
||||||
|
2. config.yaml
|
||||||
|
3. config.yml
|
||||||
|
4. config.json
|
||||||
|
5. config.ini
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If no config file is found
|
||||||
|
"""
|
||||||
|
# Try .env
|
||||||
|
env_path = self.config_dir / ".env"
|
||||||
|
if env_path.exists():
|
||||||
|
return self.load_env(env_path)
|
||||||
|
|
||||||
|
# Try YAML
|
||||||
|
for yaml_name in ["config.yaml", "config.yml"]:
|
||||||
|
yaml_path = self.config_dir / yaml_name
|
||||||
|
if yaml_path.exists():
|
||||||
|
return self.load_yaml(yaml_path)
|
||||||
|
|
||||||
|
# Try JSON
|
||||||
|
json_path = self.config_dir / "config.json"
|
||||||
|
if json_path.exists():
|
||||||
|
return self.load_json(json_path)
|
||||||
|
|
||||||
|
# Try INI
|
||||||
|
ini_path = self.config_dir / "config.ini"
|
||||||
|
if ini_path.exists():
|
||||||
|
return self.load_ini(ini_path)
|
||||||
|
|
||||||
|
raise FileNotFoundError(
|
||||||
|
f"No configuration file found in {self.config_dir}. "
|
||||||
|
"Tried: .env, config.yaml, config.yml, config.json, config.ini"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _parse_value(self, value: str) -> Any:
|
||||||
|
"""Parse string value to appropriate type."""
|
||||||
|
# Boolean
|
||||||
|
if value.lower() in ("true", "yes", "1", "on"):
|
||||||
|
return True
|
||||||
|
if value.lower() in ("false", "no", "0", "off"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# None/null
|
||||||
|
if value.lower() in ("none", "null", ""):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Number
|
||||||
|
try:
|
||||||
|
if "." in value:
|
||||||
|
return float(value)
|
||||||
|
return int(value)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# String
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _clean_dict(self, d: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""Remove None values from nested dictionary."""
|
||||||
|
cleaned = {}
|
||||||
|
for key, value in d.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
nested = self._clean_dict(value)
|
||||||
|
if nested: # Only add if not empty
|
||||||
|
cleaned[key] = nested
|
||||||
|
elif value is not None:
|
||||||
|
cleaned[key] = value
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
|
||||||
|
def load_config(
|
||||||
|
source: Optional[Union[str, Path, Dict[str, Any]]] = None,
|
||||||
|
config_dir: Optional[str] = None,
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from a source.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source: Config source (file path, dict, or None for auto-detection)
|
||||||
|
config_dir: Directory to search for config files
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration dictionary
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> config = load_config('config.yaml')
|
||||||
|
>>> config = load_config('.env')
|
||||||
|
>>> config = load_config() # Auto-detect
|
||||||
|
>>> config = load_config({'wikijs': {'url': '...'}})
|
||||||
|
"""
|
||||||
|
loader = ConfigLoader(config_dir)
|
||||||
|
|
||||||
|
# If source is a dict, return it directly
|
||||||
|
if isinstance(source, dict):
|
||||||
|
return source
|
||||||
|
|
||||||
|
# If source is provided, load it
|
||||||
|
if source:
|
||||||
|
source_path = Path(source)
|
||||||
|
|
||||||
|
# Determine file type by extension
|
||||||
|
suffix = source_path.suffix.lower()
|
||||||
|
|
||||||
|
if suffix in [".yaml", ".yml"]:
|
||||||
|
return loader.load_yaml(source)
|
||||||
|
elif suffix == ".json":
|
||||||
|
return loader.load_json(source)
|
||||||
|
elif suffix == ".ini":
|
||||||
|
return loader.load_ini(source)
|
||||||
|
elif suffix == ".env" or source_path.name == ".env":
|
||||||
|
return loader.load_env(source)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown config file type: {suffix}")
|
||||||
|
|
||||||
|
# Auto-detect
|
||||||
|
return loader.auto_load()
|
||||||
|
|
||||||
|
|
||||||
|
def create_client_from_config(
|
||||||
|
config: Optional[Union[str, Path, Dict[str, Any]]] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Any:
|
||||||
|
"""Create WikiJSClient from configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: Config source (file path, dict, or None for auto-detection)
|
||||||
|
**kwargs: Additional arguments to override config values
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configured WikiJSClient instance
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> client = create_client_from_config('config.yaml')
|
||||||
|
>>> client = create_client_from_config() # Auto-detect
|
||||||
|
>>> client = create_client_from_config(timeout=60.0) # Override
|
||||||
|
"""
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
# Load configuration
|
||||||
|
if config is None:
|
||||||
|
# Try to auto-load, fall back to env vars
|
||||||
|
try:
|
||||||
|
cfg = load_config()
|
||||||
|
except FileNotFoundError:
|
||||||
|
cfg = ConfigLoader().load_env()
|
||||||
|
else:
|
||||||
|
cfg = load_config(config)
|
||||||
|
|
||||||
|
# Extract Wiki.js settings
|
||||||
|
wikijs_cfg = cfg.get("wikijs", {})
|
||||||
|
url = kwargs.pop("url", wikijs_cfg.get("url"))
|
||||||
|
|
||||||
|
if not url:
|
||||||
|
raise ValueError("Wiki.js URL is required (set WIKIJS_URL or in config file)")
|
||||||
|
|
||||||
|
# Determine auth
|
||||||
|
auth_cfg = wikijs_cfg.get("auth", {})
|
||||||
|
auth_method = auth_cfg.get("method", "api_key")
|
||||||
|
|
||||||
|
if "auth" not in kwargs:
|
||||||
|
if auth_method == "api_key":
|
||||||
|
auth = auth_cfg.get("api_key")
|
||||||
|
if not auth:
|
||||||
|
raise ValueError(
|
||||||
|
"API key is required (set WIKIJS_API_KEY or in config file)"
|
||||||
|
)
|
||||||
|
elif auth_method == "jwt":
|
||||||
|
auth = auth_cfg.get("jwt_token")
|
||||||
|
if not auth:
|
||||||
|
raise ValueError(
|
||||||
|
"JWT token is required (set WIKIJS_JWT_TOKEN or in config file)"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
auth = None
|
||||||
|
else:
|
||||||
|
auth = kwargs.pop("auth")
|
||||||
|
|
||||||
|
# Extract client settings
|
||||||
|
client_cfg = cfg.get("client", {})
|
||||||
|
timeout = kwargs.pop("timeout", client_cfg.get("timeout", 30.0))
|
||||||
|
rate_limit = kwargs.pop("rate_limit", client_cfg.get("rate_limit"))
|
||||||
|
max_retries = kwargs.pop("max_retries", client_cfg.get("max_retries", 3))
|
||||||
|
verify_ssl = kwargs.pop("verify_ssl", client_cfg.get("verify_ssl", True))
|
||||||
|
|
||||||
|
# Extract logging settings
|
||||||
|
logging_cfg = cfg.get("logging", {})
|
||||||
|
log_level_str = kwargs.pop("log_level", logging_cfg.get("level", "INFO"))
|
||||||
|
|
||||||
|
# Convert log level string to logging constant
|
||||||
|
log_level = getattr(logging, log_level_str.upper(), logging.INFO)
|
||||||
|
|
||||||
|
# Create client
|
||||||
|
client = WikiJSClient(
|
||||||
|
url=url,
|
||||||
|
auth=auth,
|
||||||
|
timeout=timeout,
|
||||||
|
rate_limit=rate_limit,
|
||||||
|
max_retries=max_retries,
|
||||||
|
verify_ssl=verify_ssl,
|
||||||
|
log_level=log_level,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
def validate_config(config: Dict[str, Any]) -> bool:
|
||||||
|
"""Validate configuration dictionary.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: Configuration dictionary
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if valid
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If configuration is invalid
|
||||||
|
"""
|
||||||
|
# Check required fields
|
||||||
|
if "wikijs" not in config:
|
||||||
|
raise ValueError("Missing 'wikijs' section in config")
|
||||||
|
|
||||||
|
wikijs = config["wikijs"]
|
||||||
|
|
||||||
|
if "url" not in wikijs:
|
||||||
|
raise ValueError("Missing 'wikijs.url' in config")
|
||||||
|
|
||||||
|
# Validate URL format
|
||||||
|
url = wikijs["url"]
|
||||||
|
if not url.startswith(("http://", "https://")):
|
||||||
|
raise ValueError(f"Invalid URL format: {url}")
|
||||||
|
|
||||||
|
# Check auth
|
||||||
|
if "auth" in wikijs:
|
||||||
|
auth = wikijs["auth"]
|
||||||
|
method = auth.get("method", "api_key")
|
||||||
|
|
||||||
|
if method == "api_key" and not auth.get("api_key"):
|
||||||
|
raise ValueError("Missing API key for api_key auth method")
|
||||||
|
|
||||||
|
if method == "jwt" and not auth.get("jwt_token"):
|
||||||
|
raise ValueError("Missing JWT token for jwt auth method")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Example usage
|
||||||
|
print("🔧 py-wikijs Configuration Helper\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Try to load config
|
||||||
|
config = load_config()
|
||||||
|
print(f"✅ Loaded configuration from auto-detected source")
|
||||||
|
print(f"\nConfiguration:")
|
||||||
|
print(json.dumps(config, indent=2))
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
validate_config(config)
|
||||||
|
print("\n✅ Configuration is valid")
|
||||||
|
|
||||||
|
# Create client
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
print(f"\n✅ Created WikiJSClient")
|
||||||
|
print(f" URL: {client.base_url}")
|
||||||
|
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
print(f"❌ {e}")
|
||||||
|
print("\nℹ️ Create a config file from one of the examples:")
|
||||||
|
print(" - config.env.example → .env")
|
||||||
|
print(" - config.yaml.example → config.yaml")
|
||||||
|
print(" - config.json.example → config.json")
|
||||||
|
print(" - config.ini.example → config.ini")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
151
examples/quick_test.py
Executable file
151
examples/quick_test.py
Executable file
@@ -0,0 +1,151 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Quick test script to verify py-wikijs installation and connectivity.
|
||||||
|
|
||||||
|
This script helps you verify that py-wikijs is installed correctly and can
|
||||||
|
connect to your Wiki.js instance.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python quick_test.py
|
||||||
|
|
||||||
|
Or set environment variables:
|
||||||
|
export WIKIJS_URL="https://your-wiki.example.com"
|
||||||
|
export WIKIJS_API_KEY="your-api-key-here"
|
||||||
|
python quick_test.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
def test_import() -> bool:
|
||||||
|
"""Test that py-wikijs can be imported."""
|
||||||
|
print("=" * 60)
|
||||||
|
print("TEST 1: Package Import")
|
||||||
|
print("=" * 60)
|
||||||
|
try:
|
||||||
|
from wikijs import WikiJSClient, __version__
|
||||||
|
|
||||||
|
print(f"✅ Successfully imported py-wikijs v{__version__}")
|
||||||
|
return True
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"❌ Failed to import py-wikijs: {e}")
|
||||||
|
print("\nInstall with: pip install git+https://github.com/l3ocho/py-wikijs.git@v0.1.0")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_connectivity(url: Optional[str] = None, api_key: Optional[str] = None) -> bool:
|
||||||
|
"""Test connectivity to Wiki.js instance."""
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("TEST 2: Wiki.js Connectivity")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Get credentials
|
||||||
|
url = url or os.getenv("WIKIJS_URL")
|
||||||
|
api_key = api_key or os.getenv("WIKIJS_API_KEY")
|
||||||
|
|
||||||
|
if not url or not api_key:
|
||||||
|
print("⚠️ Skipping connectivity test - credentials not provided")
|
||||||
|
print("\nTo test connectivity, set environment variables:")
|
||||||
|
print(" export WIKIJS_URL='https://your-wiki.example.com'")
|
||||||
|
print(" export WIKIJS_API_KEY='your-api-key-here'")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
from wikijs import WikiJSClient
|
||||||
|
|
||||||
|
print(f"🔗 Connecting to: {url}")
|
||||||
|
client = WikiJSClient(url=url, auth=api_key)
|
||||||
|
|
||||||
|
# Try to list pages
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"✅ Successfully connected to Wiki.js")
|
||||||
|
print(f"✅ Found {len(pages)} page(s)")
|
||||||
|
|
||||||
|
# Show first page if available
|
||||||
|
if pages:
|
||||||
|
first_page = pages[0]
|
||||||
|
print(f"\nFirst page:")
|
||||||
|
print(f" - ID: {first_page.id}")
|
||||||
|
print(f" - Title: {first_page.title}")
|
||||||
|
print(f" - Path: {first_page.path}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to connect: {e}")
|
||||||
|
print("\nPlease verify:")
|
||||||
|
print(" 1. Wiki.js URL is correct and accessible")
|
||||||
|
print(" 2. API key is valid and has necessary permissions")
|
||||||
|
print(" 3. Wiki.js version is 2.2 or higher (not 3.x)")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_features() -> bool:
|
||||||
|
"""Test that key features are available."""
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("TEST 3: Feature Availability")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from wikijs import (
|
||||||
|
APIKeyAuth,
|
||||||
|
AuthenticationError,
|
||||||
|
JWTAuth,
|
||||||
|
Page,
|
||||||
|
PageCreate,
|
||||||
|
WikiJSClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
print("✅ Core client: WikiJSClient")
|
||||||
|
print("✅ Authentication: APIKeyAuth, JWTAuth")
|
||||||
|
print("✅ Models: Page, PageCreate")
|
||||||
|
print("✅ Exceptions: AuthenticationError")
|
||||||
|
print("✅ All core features available")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"❌ Missing features: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
"""Run all tests."""
|
||||||
|
print("\n🧪 py-wikijs Installation & Connectivity Test")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
# Test 1: Import
|
||||||
|
results.append(test_import())
|
||||||
|
|
||||||
|
# Test 2: Connectivity (optional)
|
||||||
|
results.append(test_connectivity())
|
||||||
|
|
||||||
|
# Test 3: Features
|
||||||
|
results.append(test_features())
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("TEST SUMMARY")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
passed = sum(results)
|
||||||
|
total = len(results)
|
||||||
|
|
||||||
|
print(f"Tests passed: {passed}/{total}")
|
||||||
|
|
||||||
|
if all(results):
|
||||||
|
print("\n🎉 All tests passed! py-wikijs is ready to use.")
|
||||||
|
return 0
|
||||||
|
elif results[0] and results[2]: # Import and features work
|
||||||
|
print("\n✅ Installation verified!")
|
||||||
|
print("ℹ️ Set WIKIJS_URL and WIKIJS_API_KEY to test connectivity")
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
print("\n❌ Some tests failed. Please check the errors above.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
103
examples/using_env_config.py
Executable file
103
examples/using_env_config.py
Executable file
@@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Example: Using .env configuration file with py-wikijs.
|
||||||
|
|
||||||
|
This example shows how to use environment variables (.env file) to configure
|
||||||
|
the WikiJS client.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
pip install python-dotenv
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
1. Copy config.env.example to .env
|
||||||
|
2. Update .env with your Wiki.js credentials
|
||||||
|
3. Run this script
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python using_env_config.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add examples directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
except ImportError:
|
||||||
|
print("❌ python-dotenv is required for .env files")
|
||||||
|
print("Install with: pip install python-dotenv")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
from config_helper import create_client_from_config, load_config
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function."""
|
||||||
|
print("=" * 60)
|
||||||
|
print("Using .env Configuration with py-wikijs")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Method 1: Load .env explicitly
|
||||||
|
print("\n📁 Method 1: Load .env explicitly")
|
||||||
|
env_file = Path(__file__).parent / ".env"
|
||||||
|
|
||||||
|
if not env_file.exists():
|
||||||
|
print(f"⚠️ .env file not found at {env_file}")
|
||||||
|
print(" Copy config.env.example to .env and update it")
|
||||||
|
print("\n📁 Method 2: Using config helper")
|
||||||
|
|
||||||
|
# Load the .env file
|
||||||
|
load_dotenv(env_file)
|
||||||
|
|
||||||
|
# Method 2: Use config helper (recommended)
|
||||||
|
try:
|
||||||
|
config = load_config(".env")
|
||||||
|
print(f"✅ Loaded configuration from .env")
|
||||||
|
print(f"\nConfiguration:")
|
||||||
|
print(f" URL: {config.get('wikijs', {}).get('url')}")
|
||||||
|
print(f" Auth method: {config.get('wikijs', {}).get('auth', {}).get('method')}")
|
||||||
|
print(f" Timeout: {config.get('client', {}).get('timeout')}s")
|
||||||
|
print(f" Rate limit: {config.get('client', {}).get('rate_limit')} req/s")
|
||||||
|
|
||||||
|
# Create client
|
||||||
|
print("\n🔌 Creating WikiJS client...")
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
print(f"✅ Client created successfully")
|
||||||
|
print(f" Base URL: {client.base_url}")
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
print("\n🔍 Testing connection...")
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"✅ Connected! Found {len(pages)} page(s)")
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
print(f"\n📄 First page:")
|
||||||
|
print(f" ID: {pages[0].id}")
|
||||||
|
print(f" Title: {pages[0].title}")
|
||||||
|
print(f" Path: {pages[0].path}")
|
||||||
|
|
||||||
|
# Show metrics
|
||||||
|
metrics = client.get_metrics()
|
||||||
|
print(f"\n📊 Metrics:")
|
||||||
|
print(f" Total requests: {metrics['total_requests']}")
|
||||||
|
print(f" Successful: {metrics['successful_requests']}")
|
||||||
|
print(f" Failed: {metrics['failed_requests']}")
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("❌ .env file not found")
|
||||||
|
print(" 1. Copy config.env.example to .env")
|
||||||
|
print(" 2. Update with your Wiki.js credentials")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ Example completed successfully!")
|
||||||
|
print("=" * 60)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
108
examples/using_json_config.py
Executable file
108
examples/using_json_config.py
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Example: Using JSON configuration file with py-wikijs.
|
||||||
|
|
||||||
|
This example shows how to use a JSON configuration file to configure
|
||||||
|
the WikiJS client.
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
1. Copy config.json.example to config.json
|
||||||
|
2. Update config.json with your Wiki.js credentials
|
||||||
|
3. Run this script
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python using_json_config.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add examples directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent))
|
||||||
|
|
||||||
|
from config_helper import create_client_from_config, load_config
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function."""
|
||||||
|
print("=" * 60)
|
||||||
|
print("Using JSON Configuration with py-wikijs")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
json_file = Path(__file__).parent / "config.json"
|
||||||
|
|
||||||
|
if not json_file.exists():
|
||||||
|
print(f"\n⚠️ config.json not found at {json_file}")
|
||||||
|
print(" Copy config.json.example to config.json and update it")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load configuration
|
||||||
|
print("\n📁 Loading configuration from config.json...")
|
||||||
|
config = load_config(json_file)
|
||||||
|
print("✅ Configuration loaded successfully")
|
||||||
|
|
||||||
|
# Pretty print config (without sensitive data)
|
||||||
|
safe_config = config.copy()
|
||||||
|
if "wikijs" in safe_config and "auth" in safe_config["wikijs"]:
|
||||||
|
if "api_key" in safe_config["wikijs"]["auth"]:
|
||||||
|
safe_config["wikijs"]["auth"]["api_key"] = "***REDACTED***"
|
||||||
|
|
||||||
|
print(f"\nConfiguration (sanitized):")
|
||||||
|
print(json.dumps(safe_config, indent=2))
|
||||||
|
|
||||||
|
# Create client
|
||||||
|
print("\n🔌 Creating WikiJS client...")
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
print(f"✅ Client created successfully")
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
print("\n🔍 Testing connection...")
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"✅ Connected! Found {len(pages)} page(s)")
|
||||||
|
|
||||||
|
# Create a new page (example)
|
||||||
|
if input("\n❓ Create a test page? (y/N): ").lower() == "y":
|
||||||
|
from wikijs.models import PageCreate
|
||||||
|
|
||||||
|
test_page = PageCreate(
|
||||||
|
title="Test Page from JSON Config",
|
||||||
|
path="test/json-config-example",
|
||||||
|
content="# Test Page\n\nCreated using JSON configuration!",
|
||||||
|
description="Example page created from JSON config",
|
||||||
|
is_published=False,
|
||||||
|
locale="en",
|
||||||
|
tags=["test", "json", "config"],
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\n📝 Creating test page...")
|
||||||
|
created = client.pages.create(test_page)
|
||||||
|
print(f"✅ Page created: {created.title} (ID: {created.id})")
|
||||||
|
print(f" Path: {created.path}")
|
||||||
|
|
||||||
|
# Show metrics
|
||||||
|
metrics = client.get_metrics()
|
||||||
|
print(f"\n📊 Client Metrics:")
|
||||||
|
print(f" Total requests: {metrics['total_requests']}")
|
||||||
|
print(f" Successful: {metrics['successful_requests']}")
|
||||||
|
print(f" Failed: {metrics['failed_requests']}")
|
||||||
|
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
print(f"❌ {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
traceback.print_exc()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ Example completed successfully!")
|
||||||
|
print("=" * 60)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
104
examples/using_yaml_config.py
Executable file
104
examples/using_yaml_config.py
Executable file
@@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Example: Using YAML configuration file with py-wikijs.
|
||||||
|
|
||||||
|
This example shows how to use a YAML configuration file to configure
|
||||||
|
the WikiJS client.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
pip install pyyaml
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
1. Copy config.yaml.example to config.yaml
|
||||||
|
2. Update config.yaml with your Wiki.js credentials
|
||||||
|
3. Run this script
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python using_yaml_config.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add examples directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent))
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
print("❌ PyYAML is required for YAML config files")
|
||||||
|
print("Install with: pip install pyyaml")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
from config_helper import create_client_from_config, load_config
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function."""
|
||||||
|
print("=" * 60)
|
||||||
|
print("Using YAML Configuration with py-wikijs")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
yaml_file = Path(__file__).parent / "config.yaml"
|
||||||
|
|
||||||
|
if not yaml_file.exists():
|
||||||
|
print(f"\n⚠️ config.yaml not found at {yaml_file}")
|
||||||
|
print(" Copy config.yaml.example to config.yaml and update it")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load configuration
|
||||||
|
print("\n📁 Loading configuration from config.yaml...")
|
||||||
|
config = load_config(yaml_file)
|
||||||
|
print("✅ Configuration loaded successfully")
|
||||||
|
|
||||||
|
print(f"\nConfiguration:")
|
||||||
|
print(f" URL: {config.get('wikijs', {}).get('url')}")
|
||||||
|
print(f" Auth method: {config.get('wikijs', {}).get('auth', {}).get('method')}")
|
||||||
|
print(f" Timeout: {config.get('client', {}).get('timeout')}s")
|
||||||
|
print(f" Rate limit: {config.get('client', {}).get('rate_limit')} req/s")
|
||||||
|
print(f" Log level: {config.get('logging', {}).get('level')}")
|
||||||
|
|
||||||
|
# Create client with environment-specific config
|
||||||
|
env = config.get("environments", {}).get("development", {})
|
||||||
|
if env:
|
||||||
|
print(f"\n🔧 Using development environment settings")
|
||||||
|
|
||||||
|
print("\n🔌 Creating WikiJS client...")
|
||||||
|
client = create_client_from_config(config)
|
||||||
|
print(f"✅ Client created successfully")
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
print("\n🔍 Testing connection...")
|
||||||
|
pages = client.pages.list()
|
||||||
|
print(f"✅ Connected! Found {len(pages)} page(s)")
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
print(f"\n📄 Sample pages:")
|
||||||
|
for page in pages[:3]: # Show first 3
|
||||||
|
print(f" - [{page.id}] {page.title} ({page.path})")
|
||||||
|
|
||||||
|
# Show metrics
|
||||||
|
metrics = client.get_metrics()
|
||||||
|
print(f"\n📊 Client Metrics:")
|
||||||
|
print(f" Total requests: {metrics['total_requests']}")
|
||||||
|
print(f" Error rate: {metrics.get('error_rate', 0):.2f}%")
|
||||||
|
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
print(f"❌ {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
traceback.print_exc()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ Example completed successfully!")
|
||||||
|
print("=" * 60)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user