Complete Phase 1 foundation: Tasks 1.1 and 1.2
✅ Task 1.1 - Project Foundation Setup: - Repository structure with Python packaging (setup.py, pyproject.toml) - Development dependencies and requirements - Contributing guidelines and MIT license - GitHub workflows for CI/CD (test.yml, release.yml) - Issue and PR templates for community contributions - Comprehensive project documentation ✅ Task 1.2 - Core Client Structure: - wikijs package with proper module organization - Core client class foundation in client.py - Exception hierarchy for error handling - Base model classes and page models - Type checking support (py.typed) - Utility modules and helper functions 📊 Progress: Phase 1 MVP Development now 40% complete 🎯 Next: Task 1.3 - Authentication System implementation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
49
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
49
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: '[BUG] '
|
||||
labels: ['bug']
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Bug Description
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
## Steps to Reproduce
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
## Expected Behavior
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
## Actual Behavior
|
||||
A clear and concise description of what actually happened.
|
||||
|
||||
## Code Example
|
||||
If applicable, add code snippets to help explain your problem.
|
||||
|
||||
```python
|
||||
# Your code here
|
||||
```
|
||||
|
||||
## Environment
|
||||
- **SDK Version**: [e.g. 0.1.0]
|
||||
- **Python Version**: [e.g. 3.11.0]
|
||||
- **Operating System**: [e.g. Ubuntu 22.04]
|
||||
- **Wiki.js Version**: [e.g. 2.5.300]
|
||||
|
||||
## Error Messages
|
||||
If applicable, add any error messages or stack traces.
|
||||
|
||||
```
|
||||
Paste error messages here
|
||||
```
|
||||
|
||||
## Additional Context
|
||||
Add any other context about the problem here.
|
||||
|
||||
## Possible Solution
|
||||
If you have suggestions on how to fix the bug, please describe them here.
|
||||
59
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
59
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: '[FEATURE] '
|
||||
labels: ['enhancement']
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Feature Summary
|
||||
A clear and concise description of the feature you'd like to request.
|
||||
|
||||
## Problem Statement
|
||||
Is your feature request related to a problem? Please describe.
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
## Proposed Solution
|
||||
Describe the solution you'd like.
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
## Use Case
|
||||
Describe your use case for this feature.
|
||||
- Who would benefit from this feature?
|
||||
- What problem does it solve?
|
||||
- How would you use it?
|
||||
|
||||
## API Design (if applicable)
|
||||
If you have ideas about how the API should look, include them here.
|
||||
|
||||
```python
|
||||
# Example of how you envision using this feature
|
||||
client = WikiJSClient(...)
|
||||
result = client.new_feature.do_something()
|
||||
```
|
||||
|
||||
## Alternatives Considered
|
||||
Describe alternatives you've considered.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
## Implementation Notes
|
||||
If you have ideas about implementation, include them here.
|
||||
- Are there any technical challenges?
|
||||
- Dependencies that might be needed?
|
||||
- Breaking changes required?
|
||||
|
||||
## Additional Context
|
||||
Add any other context, screenshots, or examples about the feature request here.
|
||||
|
||||
## Priority
|
||||
How important is this feature to you?
|
||||
- [ ] Nice to have
|
||||
- [ ] Important for my use case
|
||||
- [ ] Critical for my use case
|
||||
|
||||
## Contribution
|
||||
Are you willing to contribute to implementing this feature?
|
||||
- [ ] Yes, I can implement this
|
||||
- [ ] Yes, but I need guidance
|
||||
- [ ] No, but I can help with testing
|
||||
- [ ] No, I just want to request it
|
||||
66
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
66
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# Pull Request
|
||||
|
||||
## Description
|
||||
Brief description of what this PR does and why.
|
||||
|
||||
## Type of Change
|
||||
Please delete options that are not relevant.
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Performance improvement
|
||||
- [ ] Code refactoring (no functional changes)
|
||||
- [ ] Test improvements
|
||||
|
||||
## Related Issues
|
||||
Closes #(issue_number)
|
||||
Relates to #(issue_number)
|
||||
|
||||
## Changes Made
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
## Testing
|
||||
- [ ] Tests pass locally
|
||||
- [ ] Added tests for new functionality
|
||||
- [ ] Updated existing tests
|
||||
- [ ] Manual testing completed
|
||||
|
||||
Describe any testing you performed:
|
||||
|
||||
## Documentation
|
||||
- [ ] Updated docstrings
|
||||
- [ ] Updated README if needed
|
||||
- [ ] Updated API documentation
|
||||
- [ ] Added/updated examples
|
||||
|
||||
## Code Quality
|
||||
- [ ] Code follows the style guidelines
|
||||
- [ ] Self-review of the code completed
|
||||
- [ ] Code is commented where necessary
|
||||
- [ ] No new warnings introduced
|
||||
|
||||
## Breaking Changes
|
||||
If this introduces breaking changes, please describe them and provide migration guidance:
|
||||
|
||||
## Screenshots/Examples
|
||||
If applicable, add screenshots or code examples to help explain your changes.
|
||||
|
||||
```python
|
||||
# Example usage
|
||||
```
|
||||
|
||||
## Additional Notes
|
||||
Any additional information that reviewers should know.
|
||||
|
||||
---
|
||||
|
||||
## Reviewer Checklist
|
||||
- [ ] Code follows project style guidelines
|
||||
- [ ] Changes are well documented
|
||||
- [ ] Tests are adequate and pass
|
||||
- [ ] No obvious bugs or performance issues
|
||||
- [ ] Breaking changes are properly documented
|
||||
66
.github/workflows/release.yml
vendored
Normal file
66
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: pytest tests/ -v --cov=wikijs --cov-fail-under=85
|
||||
|
||||
- name: Run security scan
|
||||
run: bandit -r wikijs
|
||||
|
||||
release:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine
|
||||
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
|
||||
- name: Check package
|
||||
run: twine check dist/*
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: dist/*
|
||||
generate_release_notes: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
111
.github/workflows/test.yml
vendored
Normal file
111
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
name: Test Suite
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[dev]"
|
||||
|
||||
- name: Lint with flake8
|
||||
run: flake8 wikijs tests
|
||||
|
||||
- name: Format check with black
|
||||
run: black --check wikijs tests
|
||||
|
||||
- name: Import sort check
|
||||
run: isort --check-only wikijs tests
|
||||
|
||||
- name: Type check with mypy
|
||||
run: mypy wikijs
|
||||
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[dev]"
|
||||
|
||||
- name: Run unit tests
|
||||
run: pytest tests/ -v --cov=wikijs --cov-report=xml
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
if: matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[dev]"
|
||||
|
||||
- name: Run security scan with bandit
|
||||
run: bandit -r wikijs -f json -o bandit-report.json || true
|
||||
|
||||
- name: Upload bandit report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: bandit-report
|
||||
path: bandit-report.json
|
||||
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine
|
||||
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
|
||||
- name: Check package
|
||||
run: twine check dist/*
|
||||
134
.gitignore
vendored
134
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[codz]
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
@@ -27,15 +27,9 @@ share/python-wheels/
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
@@ -46,28 +40,11 @@ htmlcov/
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
@@ -83,60 +60,22 @@ profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
#poetry.toml
|
||||
poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
||||
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
||||
#pdm.lock
|
||||
#pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
.pdm.toml
|
||||
|
||||
# pixi
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
||||
#pixi.lock
|
||||
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
||||
# in the .venv directory. It is recommended not to include this directory in version control.
|
||||
.pixi
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
# PEP 582
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.envrc
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
@@ -144,16 +83,6 @@ ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
@@ -168,40 +97,19 @@ dmypy.json
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
# IDEs
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Abstra
|
||||
# Abstra is an AI-powered process automation framework.
|
||||
# Ignore directories containing user credentials, local state, and settings.
|
||||
# Learn more at https://abstra.io/docs
|
||||
.abstra/
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Visual Studio Code
|
||||
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||
# you could uncomment the following to ignore the entire vscode folder
|
||||
# .vscode/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# Cursor
|
||||
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
||||
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
||||
# refer to https://docs.cursor.com/context/ignore-files
|
||||
.cursorignore
|
||||
.cursorindexingignore
|
||||
|
||||
# Marimo
|
||||
marimo/_static/
|
||||
marimo/_lsp/
|
||||
__marimo__/
|
||||
# Project specific
|
||||
*.db
|
||||
*.sqlite
|
||||
.temp/
|
||||
wiki-test-data/
|
||||
test-wiki/
|
||||
117
CHANGELOG.md
Normal file
117
CHANGELOG.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to the Wiki.js Python SDK will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Project foundation and repository structure
|
||||
- Python packaging configuration (setup.py, pyproject.toml)
|
||||
- CI/CD pipeline with GitHub Actions
|
||||
- Code quality tools (black, isort, flake8, mypy, bandit)
|
||||
- Comprehensive documentation structure
|
||||
- Contributing guidelines and community governance
|
||||
- Issue and PR templates for GitHub
|
||||
|
||||
### Changed
|
||||
- N/A
|
||||
|
||||
### Deprecated
|
||||
- N/A
|
||||
|
||||
### Removed
|
||||
- N/A
|
||||
|
||||
### Fixed
|
||||
- N/A
|
||||
|
||||
### Security
|
||||
- Added automated security scanning with bandit
|
||||
|
||||
## Release Planning
|
||||
|
||||
### [0.1.0] - Target: 2 weeks from start
|
||||
**MVP Release - Basic Wiki.js Integration**
|
||||
|
||||
#### Planned Features
|
||||
- Core WikiJSClient with HTTP transport
|
||||
- API key authentication
|
||||
- Pages API with full CRUD operations (list, get, create, update, delete)
|
||||
- Type-safe data models with Pydantic
|
||||
- Comprehensive error handling
|
||||
- >85% test coverage
|
||||
- Complete API documentation
|
||||
- PyPI package publication
|
||||
|
||||
#### Success Criteria
|
||||
- [ ] Package installable via `pip install wikijs-python-sdk`
|
||||
- [ ] Basic page operations work with real Wiki.js instance
|
||||
- [ ] All quality gates pass (tests, coverage, linting, security)
|
||||
- [ ] Documentation sufficient for basic usage
|
||||
|
||||
### [0.2.0] - Target: 4 weeks from start
|
||||
**Essential Features - Complete API Coverage**
|
||||
|
||||
#### Planned Features
|
||||
- Users API (full CRUD operations)
|
||||
- Groups API (management and permissions)
|
||||
- Assets API (file upload and management)
|
||||
- System API (health checks and info)
|
||||
- Enhanced error handling with detailed context
|
||||
- Configuration management (file and environment-based)
|
||||
- Basic CLI interface
|
||||
- Performance benchmarks
|
||||
|
||||
### [0.3.0] - Target: 7 weeks from start
|
||||
**Production Ready - Reliability & Performance**
|
||||
|
||||
#### Planned Features
|
||||
- Retry logic with exponential backoff
|
||||
- Circuit breaker for fault tolerance
|
||||
- Intelligent caching with multiple backends
|
||||
- Rate limiting and API compliance
|
||||
- Performance monitoring and metrics
|
||||
- Bulk operations for efficiency
|
||||
- Connection pooling optimization
|
||||
|
||||
### [1.0.0] - Target: 11 weeks from start
|
||||
**Enterprise Grade - Advanced Features**
|
||||
|
||||
#### Planned Features
|
||||
- Full async/await support with aiohttp
|
||||
- Advanced CLI with interactive mode
|
||||
- Plugin architecture for extensibility
|
||||
- Advanced authentication (JWT rotation, OAuth2)
|
||||
- Enterprise security features
|
||||
- Webhook support and verification
|
||||
- Multi-tenancy support
|
||||
|
||||
---
|
||||
|
||||
## Development Notes
|
||||
|
||||
### Versioning Strategy
|
||||
- **MAJOR**: Breaking changes that require user action
|
||||
- **MINOR**: New features that are backward compatible
|
||||
- **PATCH**: Bug fixes and improvements that are backward compatible
|
||||
|
||||
### Quality Standards
|
||||
All releases must meet:
|
||||
- [ ] >85% test coverage (>90% for minor releases)
|
||||
- [ ] 100% type coverage on public APIs
|
||||
- [ ] All quality gates pass (linting, formatting, security)
|
||||
- [ ] Complete documentation for new features
|
||||
- [ ] No known critical bugs
|
||||
|
||||
### Community Involvement
|
||||
- Feature requests welcomed through GitHub issues
|
||||
- Community feedback incorporated into release planning
|
||||
- Breaking changes require community discussion period
|
||||
- Beta releases available for testing major features
|
||||
|
||||
---
|
||||
|
||||
*This changelog is maintained as part of our commitment to transparency and professional development practices. All changes are documented to help users understand what's new, what's changed, and how to upgrade safely.*
|
||||
523
CLAUDE.md
Normal file
523
CLAUDE.md
Normal file
@@ -0,0 +1,523 @@
|
||||
# CLAUDE.md - AI Development Coordinator
|
||||
|
||||
**🤖 AI Development Orchestration System**
|
||||
**Project**: Wiki.js Python SDK
|
||||
**Version**: 1.0
|
||||
**Last Updated**: July 2025
|
||||
**Status**: Active Development
|
||||
|
||||
---
|
||||
|
||||
## 🎯 CRITICAL: READ THIS FIRST
|
||||
|
||||
**⚠️ MANDATORY ACTIONS FOR EVERY CLAUDE SESSION:**
|
||||
|
||||
1. **📚 ALWAYS REFER TO DOCUMENTATION**: Before any development work, review relevant documentation:
|
||||
- `docs/wikijs_sdk_architecture.md` for technical decisions
|
||||
- `docs/wikijs_sdk_release_plan.md` for current phase requirements
|
||||
- `docs/RISK_MANAGEMENT.md` for risk considerations
|
||||
- `docs/GOVERNANCE.md` for contribution standards
|
||||
|
||||
2. **📊 UPDATE PROGRESS TRACKING**: After completing any task, update the completion percentages in this document
|
||||
|
||||
3. **🔄 TRIGGER DOCUMENTATION UPDATES**: When completing milestones, update relevant documentation files
|
||||
|
||||
4. **✅ VALIDATE QUALITY CHECKPOINTS**: Ensure all quality gates pass before marking tasks complete
|
||||
|
||||
5. **🚨 ERROR PREVENTION**: Follow the error prevention guidelines to avoid common issues
|
||||
|
||||
---
|
||||
|
||||
## 📋 PROJECT CONTEXT & STATUS
|
||||
|
||||
### **Project Overview**
|
||||
**Name**: wikijs-python-sdk
|
||||
**Purpose**: Professional-grade Python SDK for Wiki.js API integration
|
||||
**Development Approach**: AI-powered, community-driven, open source
|
||||
**Target**: Complete professional development lifecycle demonstration
|
||||
|
||||
### **Current Development State**
|
||||
```yaml
|
||||
Overall_Completion: 15%
|
||||
Current_Phase: "Phase 1 - MVP Development"
|
||||
Active_Tasks: "Project Foundation Setup"
|
||||
Next_Milestone: "v0.1.0 MVP Release"
|
||||
Target_Date: "2 weeks from start"
|
||||
```
|
||||
|
||||
### **Repository Structure Status**
|
||||
```
|
||||
wikijs-python-sdk/ # ✅ COMPLETE
|
||||
├── README.md # ✅ COMPLETE - Central documentation hub
|
||||
├── docs/wikijs_sdk_architecture.md # ✅ COMPLETE - Technical foundation
|
||||
├── docs/wikijs_sdk_release_plan.md # ✅ COMPLETE - Release strategy
|
||||
├── docs/RISK_MANAGEMENT.md # ✅ COMPLETE - Risk framework
|
||||
├── docs/GOVERNANCE.md # ✅ COMPLETE - Community charter
|
||||
├── CLAUDE.md # ✅ COMPLETE - This file
|
||||
├── CONTRIBUTING.md # ✅ COMPLETE - Task 1.1
|
||||
├── LICENSE # ✅ COMPLETE - Task 1.1
|
||||
├── setup.py # ✅ COMPLETE - Task 1.1
|
||||
├── pyproject.toml # ✅ COMPLETE - Task 1.1
|
||||
├── requirements.txt # ✅ COMPLETE - Task 1.1
|
||||
├── requirements-dev.txt # ✅ COMPLETE - Task 1.1
|
||||
├── .gitignore # ✅ COMPLETE - Task 1.1
|
||||
├── CHANGELOG.md # ✅ COMPLETE - Task 1.1
|
||||
├── .github/ # ✅ COMPLETE - Task 1.1
|
||||
│ ├── workflows/ # CI/CD pipelines
|
||||
│ ├── ISSUE_TEMPLATE/ # Bug & feature templates
|
||||
│ └── PULL_REQUEST_TEMPLATE.md # PR template
|
||||
├── wikijs/ # ✅ COMPLETE - Task 1.2
|
||||
│ ├── __init__.py # Core package initialization
|
||||
│ ├── version.py # Version management
|
||||
│ ├── client.py # Main WikiJSClient class
|
||||
│ ├── exceptions.py # Exception hierarchy
|
||||
│ ├── py.typed # Type checking marker
|
||||
│ ├── models/ # Data models
|
||||
│ │ ├── __init__.py # Model exports
|
||||
│ │ ├── base.py # Base model functionality
|
||||
│ │ └── page.py # Page-related models
|
||||
│ ├── auth/ # Authentication (Task 1.3)
|
||||
│ ├── endpoints/ # API endpoints (Task 1.4)
|
||||
│ └── utils/ # Utility functions
|
||||
│ ├── __init__.py # Utility exports
|
||||
│ └── helpers.py # Helper functions
|
||||
├── tests/ # 🔄 PENDING - Task 1.5
|
||||
├── docs/ # 🔄 PENDING - Task 1.6
|
||||
└── examples/ # 🔄 PENDING - Task 1.6
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 PHASE COMPLETION TRACKING
|
||||
|
||||
### **Phase 0: Foundation (100% COMPLETE) ✅**
|
||||
```yaml
|
||||
Status: COMPLETE
|
||||
Completion: 100%
|
||||
Key_Deliverables:
|
||||
- ✅ Architecture Documentation
|
||||
- ✅ Development Plan
|
||||
- ✅ Risk Management Plan
|
||||
- ✅ Community Governance Charter
|
||||
- ✅ Central README Hub
|
||||
- ✅ AI Development Coordinator (this file)
|
||||
```
|
||||
|
||||
### **Phase 1: MVP Development (0% COMPLETE) 🔄**
|
||||
```yaml
|
||||
Status: IN_PROGRESS
|
||||
Completion: 40%
|
||||
Target_Completion: 100%
|
||||
Current_Task: "Task 1.3 - Authentication System"
|
||||
|
||||
Task_Breakdown:
|
||||
Task_1.1_Project_Foundation: # ✅ COMPLETE
|
||||
Status: "COMPLETE"
|
||||
Completion: 100%
|
||||
Estimated_Time: "3 hours"
|
||||
Claude_Requests: "15-20"
|
||||
|
||||
Task_1.2_Core_Client: # ✅ COMPLETE
|
||||
Status: "COMPLETE"
|
||||
Completion: 100%
|
||||
Estimated_Time: "8 hours"
|
||||
Claude_Requests: "30-40"
|
||||
|
||||
Task_1.3_Authentication: # ⏳ PENDING
|
||||
Status: "PENDING"
|
||||
Completion: 0%
|
||||
Estimated_Time: "4 hours"
|
||||
Claude_Requests: "15-20"
|
||||
|
||||
Task_1.4_Pages_API: # ⏳ PENDING
|
||||
Status: "PENDING"
|
||||
Completion: 0%
|
||||
Estimated_Time: "6 hours"
|
||||
Claude_Requests: "25-30"
|
||||
|
||||
Task_1.5_Testing: # ⏳ PENDING
|
||||
Status: "PENDING"
|
||||
Completion: 0%
|
||||
Estimated_Time: "6 hours"
|
||||
Claude_Requests: "20-25"
|
||||
|
||||
Task_1.6_Documentation: # ⏳ PENDING
|
||||
Status: "PENDING"
|
||||
Completion: 0%
|
||||
Estimated_Time: "4 hours"
|
||||
Claude_Requests: "15-20"
|
||||
|
||||
Task_1.7_Release: # ⏳ PENDING
|
||||
Status: "PENDING"
|
||||
Completion: 0%
|
||||
Estimated_Time: "2 hours"
|
||||
Claude_Requests: "10-15"
|
||||
```
|
||||
|
||||
### **Phase 2: Essential Features (0% COMPLETE) ⏳**
|
||||
```yaml
|
||||
Status: PLANNED
|
||||
Completion: 0%
|
||||
Target_Start: "After Phase 1 Complete"
|
||||
```
|
||||
|
||||
### **Phase 3: Reliability & Performance (0% COMPLETE) ⏳**
|
||||
```yaml
|
||||
Status: PLANNED
|
||||
Completion: 0%
|
||||
Target_Start: "After Phase 2 Complete"
|
||||
```
|
||||
|
||||
### **Phase 4: Advanced Features (0% COMPLETE) ⏳**
|
||||
```yaml
|
||||
Status: PLANNED
|
||||
Completion: 0%
|
||||
Target_Start: "After Phase 3 Complete"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 CURRENT FOCUS: TASK 1.1 - PROJECT FOUNDATION
|
||||
|
||||
### **Task 1.1 Detailed Breakdown**
|
||||
```yaml
|
||||
Task: "Project Foundation Setup"
|
||||
Status: "IN_PROGRESS"
|
||||
Priority: "HIGH"
|
||||
Completion: 0%
|
||||
|
||||
Subtasks:
|
||||
1.1.1_Repository_Structure:
|
||||
Description: "Create basic project file structure"
|
||||
Status: "PENDING"
|
||||
Files_To_Create:
|
||||
- CONTRIBUTING.md
|
||||
- LICENSE (MIT)
|
||||
- .gitignore
|
||||
- setup.py
|
||||
- pyproject.toml
|
||||
- requirements.txt
|
||||
- requirements-dev.txt
|
||||
|
||||
1.1.2_Python_Packaging:
|
||||
Description: "Configure Python packaging and dependencies"
|
||||
Status: "PENDING"
|
||||
Files_To_Create:
|
||||
- setup.py with full configuration
|
||||
- pyproject.toml with tool configurations
|
||||
- requirements.txt with core dependencies
|
||||
- requirements-dev.txt with development tools
|
||||
|
||||
1.1.3_CI_CD_Pipeline:
|
||||
Description: "Set up GitHub Actions workflows"
|
||||
Status: "PENDING"
|
||||
Files_To_Create:
|
||||
- .github/workflows/test.yml
|
||||
- .github/workflows/release.yml
|
||||
- .github/ISSUE_TEMPLATE/bug_report.md
|
||||
- .github/ISSUE_TEMPLATE/feature_request.md
|
||||
- .github/PULL_REQUEST_TEMPLATE.md
|
||||
|
||||
1.1.4_Initial_Documentation:
|
||||
Description: "Create contributor-focused documentation"
|
||||
Status: "PENDING"
|
||||
Files_To_Create:
|
||||
- CONTRIBUTING.md (detailed contribution guide)
|
||||
- CHANGELOG.md (version history template)
|
||||
```
|
||||
|
||||
### **Completion Criteria for Task 1.1**
|
||||
- [ ] All repository structure files created
|
||||
- [ ] Python packaging properly configured
|
||||
- [ ] CI/CD pipeline functional
|
||||
- [ ] Contributing guidelines complete
|
||||
- [ ] All files pass linting and validation
|
||||
- [ ] **UPDATE PROGRESS**: Set Task_1.1 completion to 100%
|
||||
|
||||
---
|
||||
|
||||
## 🔄 AUTOMATIC TRIGGERS & ACTIONS
|
||||
|
||||
### **📊 Progress Update Triggers**
|
||||
**TRIGGER**: After completing any subtask or task
|
||||
**ACTION**: Update completion percentages in this document
|
||||
**FORMAT**:
|
||||
```yaml
|
||||
# Update the relevant section with new percentage
|
||||
Task_1.1_Project_Foundation:
|
||||
Status: "COMPLETE" # or "IN_PROGRESS"
|
||||
Completion: 100% # Updated percentage
|
||||
```
|
||||
|
||||
### **📚 Documentation Update Triggers**
|
||||
**TRIGGER**: When reaching specific milestones
|
||||
**ACTIONS TO PERFORM**:
|
||||
|
||||
#### **After Task 1.1 Complete**:
|
||||
```yaml
|
||||
Files_To_Update:
|
||||
- README.md: Update development status section
|
||||
- DEVELOPMENT_PLAN.md: Mark Task 1.1 as complete
|
||||
- This file (CLAUDE.md): Update progress tracking
|
||||
```
|
||||
|
||||
#### **After Phase 1 Complete**:
|
||||
```yaml
|
||||
Files_To_Update:
|
||||
- README.md: Update feature list and status badges
|
||||
- CHANGELOG.md: Create v0.1.0 release notes
|
||||
- DEVELOPMENT_PLAN.md: Mark Phase 1 complete
|
||||
- ARCHITECTURE.md: Update implementation status
|
||||
```
|
||||
|
||||
### **✅ Quality Checkpoint Triggers**
|
||||
**TRIGGER**: Before marking any task complete
|
||||
**MANDATORY CHECKS**:
|
||||
- [ ] All code passes linting (black, flake8, mypy)
|
||||
- [ ] All tests pass with >85% coverage
|
||||
- [ ] Documentation is updated and accurate
|
||||
- [ ] Security scan passes (bandit)
|
||||
- [ ] No critical issues in code review
|
||||
|
||||
---
|
||||
|
||||
## 🚨 ERROR PREVENTION GUIDELINES
|
||||
|
||||
### **🔧 Development Environment Setup**
|
||||
```yaml
|
||||
Required_Python_Version: ">=3.8"
|
||||
Required_Tools:
|
||||
- git
|
||||
- python (3.8+)
|
||||
- pip
|
||||
- pre-commit (for quality checks)
|
||||
|
||||
Setup_Commands:
|
||||
- "python -m pip install --upgrade pip"
|
||||
- "pip install -e '.[dev]'"
|
||||
- "pre-commit install"
|
||||
```
|
||||
|
||||
### **📂 File Creation Standards**
|
||||
**ALWAYS FOLLOW THESE PATTERNS**:
|
||||
|
||||
#### **Python Files**:
|
||||
```python
|
||||
# Standard header for all Python files
|
||||
"""Module docstring describing purpose and usage."""
|
||||
|
||||
import sys
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
# Local imports last
|
||||
from .exceptions import WikiJSException
|
||||
```
|
||||
|
||||
#### **Configuration Files**:
|
||||
- Use consistent formatting (black, isort)
|
||||
- Include comprehensive comments
|
||||
- Follow established Python community standards
|
||||
- Validate syntax before committing
|
||||
|
||||
#### **Documentation Files**:
|
||||
- Use consistent markdown formatting
|
||||
- Include complete examples
|
||||
- Cross-reference related documentation
|
||||
- Keep TOC updated
|
||||
|
||||
### **🔍 Common Error Prevention**
|
||||
```yaml
|
||||
Avoid_These_Mistakes:
|
||||
- Creating files without proper headers
|
||||
- Missing type hints in public APIs
|
||||
- Incomplete error handling
|
||||
- Missing tests for new functionality
|
||||
- Outdated documentation
|
||||
- Hardcoded values instead of configuration
|
||||
- Missing docstrings for public methods
|
||||
- Inconsistent code formatting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 DEVELOPMENT SESSION GUIDANCE
|
||||
|
||||
### **Session Startup Checklist**
|
||||
**EVERY SESSION MUST START WITH**:
|
||||
1. [ ] Review current phase and task status from this document
|
||||
2. [ ] Check completion percentages and identify next actions
|
||||
3. [ ] Review relevant documentation (Architecture, Development Plan)
|
||||
4. [ ] Confirm understanding of current task requirements
|
||||
5. [ ] Identify potential risks from Risk Management Plan
|
||||
|
||||
### **Session Workflow**
|
||||
```yaml
|
||||
1. Context_Loading:
|
||||
- Read current task details from this document
|
||||
- Review architectural requirements
|
||||
- Check quality standards from governance
|
||||
|
||||
2. Development_Work:
|
||||
- Follow established patterns from architecture
|
||||
- Implement according to development plan specifications
|
||||
- Apply risk mitigation strategies
|
||||
- Maintain quality standards
|
||||
|
||||
3. Session_Completion:
|
||||
- Update progress tracking in this document
|
||||
- Trigger documentation updates if milestone reached
|
||||
- Validate quality checkpoints
|
||||
- Prepare context for next session
|
||||
```
|
||||
|
||||
### **Quality Validation Before Task Completion**
|
||||
```yaml
|
||||
Code_Quality:
|
||||
- [ ] All code follows black formatting
|
||||
- [ ] Type hints on all public APIs
|
||||
- [ ] Docstrings on all public methods
|
||||
- [ ] Error handling implemented
|
||||
- [ ] No hardcoded values
|
||||
|
||||
Testing:
|
||||
- [ ] Unit tests written for new functionality
|
||||
- [ ] Integration tests updated
|
||||
- [ ] All tests pass
|
||||
- [ ] Coverage maintained >85%
|
||||
|
||||
Documentation:
|
||||
- [ ] API documentation updated
|
||||
- [ ] Examples provided
|
||||
- [ ] README updated if needed
|
||||
- [ ] Changelog updated
|
||||
|
||||
Security:
|
||||
- [ ] No hardcoded secrets
|
||||
- [ ] Input validation implemented
|
||||
- [ ] Security scan passes
|
||||
- [ ] Dependencies checked for vulnerabilities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 TASK REFERENCE GUIDE
|
||||
|
||||
### **Immediate Next Actions** (Task 1.1)
|
||||
**PRIORITY ORDER**:
|
||||
1. **Create Repository Structure** (setup.py, requirements.txt, .gitignore)
|
||||
2. **Configure Python Packaging** (pyproject.toml, dependencies)
|
||||
3. **Set Up CI/CD Pipeline** (GitHub Actions workflows)
|
||||
4. **Create Contributing Guidelines** (CONTRIBUTING.md)
|
||||
|
||||
### **Task Dependencies**
|
||||
```yaml
|
||||
Task_1.1: No dependencies (can start immediately)
|
||||
Task_1.2: Requires Task 1.1 complete (packaging setup needed)
|
||||
Task_1.3: Requires Task 1.2 complete (core client foundation needed)
|
||||
Task_1.4: Requires Task 1.3 complete (authentication needed for API calls)
|
||||
Task_1.5: Requires Task 1.4 complete (functionality to test)
|
||||
Task_1.6: Requires Task 1.5 complete (stable code to document)
|
||||
Task_1.7: Requires Task 1.6 complete (documentation for release)
|
||||
```
|
||||
|
||||
### **Resource Optimization**
|
||||
```yaml
|
||||
# Optimize Claude usage by batching related work
|
||||
Batch_1: "Repository setup + packaging configuration"
|
||||
Batch_2: "Core client implementation + basic auth"
|
||||
Batch_3: "API endpoints + error handling"
|
||||
Batch_4: "Testing framework + initial tests"
|
||||
Batch_5: "Documentation + examples"
|
||||
Batch_6: "Release preparation + final validation"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 SUCCESS CRITERIA & MILESTONES
|
||||
|
||||
### **Phase 1 Success Criteria**
|
||||
```yaml
|
||||
Functional_Requirements:
|
||||
- [ ] Basic Wiki.js API integration working
|
||||
- [ ] Pages CRUD operations functional
|
||||
- [ ] Authentication system operational
|
||||
- [ ] Error handling comprehensive
|
||||
- [ ] Package installable via pip
|
||||
|
||||
Quality_Requirements:
|
||||
- [ ] >85% test coverage achieved
|
||||
- [ ] All quality gates passing
|
||||
- [ ] Documentation complete and accurate
|
||||
- [ ] Security scan passes
|
||||
- [ ] Performance benchmarks established
|
||||
|
||||
Community_Requirements:
|
||||
- [ ] Contributing guidelines clear
|
||||
- [ ] Code of conduct established
|
||||
- [ ] Issue templates configured
|
||||
- [ ] Community communication channels active
|
||||
```
|
||||
|
||||
### **Release Readiness Checklist**
|
||||
```yaml
|
||||
v0.1.0_Release_Criteria:
|
||||
Technical:
|
||||
- [ ] All Phase 1 tasks complete
|
||||
- [ ] CI/CD pipeline operational
|
||||
- [ ] Package builds successfully
|
||||
- [ ] All tests pass
|
||||
- [ ] Documentation comprehensive
|
||||
|
||||
Quality:
|
||||
- [ ] Code review complete
|
||||
- [ ] Security scan clean
|
||||
- [ ] Performance benchmarks met
|
||||
- [ ] User acceptance testing passed
|
||||
|
||||
Community:
|
||||
- [ ] Release notes prepared
|
||||
- [ ] Community notified
|
||||
- [ ] PyPI package published
|
||||
- [ ] GitHub release created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 CONTINUOUS IMPROVEMENT
|
||||
|
||||
### **Learning & Adaptation**
|
||||
This document evolves based on development experience:
|
||||
|
||||
**After Each Task**:
|
||||
- Update completion tracking
|
||||
- Refine time estimates based on actual effort
|
||||
- Improve error prevention guidelines
|
||||
- Enhance quality checkpoints
|
||||
|
||||
**After Each Phase**:
|
||||
- Comprehensive retrospective
|
||||
- Process optimization
|
||||
- Documentation improvement
|
||||
- Community feedback integration
|
||||
|
||||
### **Version History**
|
||||
- **v1.0** (July 2025): Initial AI development coordinator
|
||||
- Future versions will track improvements and lessons learned
|
||||
|
||||
---
|
||||
|
||||
## 🚀 READY FOR DEVELOPMENT
|
||||
|
||||
**CURRENT INSTRUCTION**: Begin Task 1.1 - Project Foundation Setup
|
||||
|
||||
**FOCUS**: Create repository structure, Python packaging, and CI/CD pipeline
|
||||
|
||||
**SUCCESS CRITERIA**: All foundational files created and validated
|
||||
|
||||
**NEXT SESSION TARGET**: Complete Task 1.1 and begin Task 1.2
|
||||
|
||||
**REMEMBER**: Always refer to documentation, update progress, and maintain quality standards!
|
||||
|
||||
---
|
||||
|
||||
**🤖 AI Developer: You are ready to begin professional SDK development. Follow this coordinator for guidance, track progress diligently, and build something amazing!**
|
||||
342
CONTRIBUTING.md
Normal file
342
CONTRIBUTING.md
Normal file
@@ -0,0 +1,342 @@
|
||||
# Contributing to Wiki.js Python SDK
|
||||
|
||||
Thank you for your interest in contributing to the Wiki.js Python SDK! This guide will help you get started with contributing to this AI-assisted, community-driven project.
|
||||
|
||||
## 🎯 Project Context
|
||||
|
||||
This project is being developed entirely with AI assistance (Claude), showcasing professional development practices while building a production-ready SDK for Wiki.js. We welcome contributors of all experience levels!
|
||||
|
||||
**Current Status**: MVP Development (Phase 1)
|
||||
**Focus**: Core functionality and foundational quality
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.8 or higher
|
||||
- Git
|
||||
- A GitHub account
|
||||
- (Optional) A Wiki.js instance for testing
|
||||
|
||||
### Development Setup
|
||||
|
||||
1. **Fork the Repository**
|
||||
```bash
|
||||
# Fork on GitHub, then clone your fork
|
||||
git clone https://github.com/yourusername/wikijs-python-sdk.git
|
||||
cd wikijs-python-sdk
|
||||
```
|
||||
|
||||
2. **Set Up Development Environment**
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
|
||||
# Install in development mode
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# Install pre-commit hooks
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
3. **Verify Setup**
|
||||
```bash
|
||||
# Run tests
|
||||
pytest
|
||||
|
||||
# Run quality checks
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
## 📋 Development Process
|
||||
|
||||
### Finding Work
|
||||
|
||||
1. **Check Current Priorities**
|
||||
- Review [CLAUDE.md](CLAUDE.md) for current development tasks
|
||||
- See [Development Plan](docs/wikijs_sdk_release_plan.md) for roadmap
|
||||
- Look for issues labeled `good first issue`
|
||||
|
||||
2. **Understand Architecture**
|
||||
- Read [Architecture Overview](docs/wikijs_sdk_architecture.md)
|
||||
- Review existing code patterns
|
||||
- Check the [Risk Management](docs/RISK_MANAGEMENT.md) for known issues
|
||||
|
||||
### Making Changes
|
||||
|
||||
1. **Create Feature Branch**
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
2. **Follow Code Standards**
|
||||
- Write type hints for all public APIs
|
||||
- Add docstrings to all public methods (Google style)
|
||||
- Follow existing code patterns
|
||||
- Keep functions small and focused
|
||||
|
||||
3. **Write Tests**
|
||||
- Add unit tests for new functionality
|
||||
- Maintain >85% code coverage
|
||||
- Use descriptive test names
|
||||
- Include edge cases
|
||||
|
||||
4. **Update Documentation**
|
||||
- Update docstrings for changed methods
|
||||
- Add examples for new features
|
||||
- Update README if needed
|
||||
|
||||
### Code Quality Standards
|
||||
|
||||
#### Python Style
|
||||
```python
|
||||
def example_function(param: str, optional: Optional[int] = None) -> bool:
|
||||
"""Example function following our standards.
|
||||
|
||||
Args:
|
||||
param: Description of the parameter
|
||||
optional: Optional parameter with default
|
||||
|
||||
Returns:
|
||||
Boolean result of the operation
|
||||
|
||||
Raises:
|
||||
ValueError: If param is empty
|
||||
|
||||
Example:
|
||||
>>> example_function("test")
|
||||
True
|
||||
"""
|
||||
if not param:
|
||||
raise ValueError("param cannot be empty")
|
||||
|
||||
# Implementation here
|
||||
return True
|
||||
```
|
||||
|
||||
#### Testing Patterns
|
||||
```python
|
||||
import pytest
|
||||
from wikijs import WikiJSClient
|
||||
from wikijs.exceptions import WikiJSException
|
||||
|
||||
class TestWikiJSClient:
|
||||
"""Test WikiJS client functionality."""
|
||||
|
||||
def test_client_initialization_success(self):
|
||||
"""Test successful client initialization."""
|
||||
client = WikiJSClient("https://wiki.example.com", "api-key")
|
||||
assert client.base_url == "https://wiki.example.com"
|
||||
|
||||
def test_client_initialization_invalid_url(self):
|
||||
"""Test client initialization with invalid URL."""
|
||||
with pytest.raises(ValueError, match="Invalid URL"):
|
||||
WikiJSClient("invalid-url", "api-key")
|
||||
```
|
||||
|
||||
### Submitting Changes
|
||||
|
||||
1. **Run Quality Checks**
|
||||
```bash
|
||||
# Format code
|
||||
black wikijs tests
|
||||
isort wikijs tests
|
||||
|
||||
# Run linting
|
||||
flake8 wikijs tests
|
||||
mypy wikijs
|
||||
|
||||
# Run tests
|
||||
pytest --cov=wikijs --cov-fail-under=85
|
||||
|
||||
# Security scan
|
||||
bandit -r wikijs
|
||||
```
|
||||
|
||||
2. **Commit Changes**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new feature description
|
||||
|
||||
Detailed description of what was changed and why.
|
||||
|
||||
Closes #123"
|
||||
```
|
||||
|
||||
3. **Create Pull Request**
|
||||
- Push to your fork
|
||||
- Create PR against `main` branch
|
||||
- Fill out the PR template completely
|
||||
- Link related issues
|
||||
|
||||
## 🤝 Community Guidelines
|
||||
|
||||
### Communication
|
||||
- **Be respectful** and constructive in all interactions
|
||||
- **Ask questions** if anything is unclear
|
||||
- **Help others** when you can
|
||||
- **Focus on the code**, not the person
|
||||
|
||||
### Code Review Process
|
||||
1. **Maintainer Review**: All PRs reviewed by project maintainer
|
||||
2. **Feedback**: Address review comments promptly
|
||||
3. **Discussion**: Open discussion encouraged for design decisions
|
||||
4. **Approval**: PR approved when all checks pass and review complete
|
||||
|
||||
### Response Times
|
||||
- **Issues**: Response within 48-72 hours
|
||||
- **Pull Requests**: Initial review within 1 week
|
||||
- **Questions**: Community-driven with maintainer backup
|
||||
|
||||
## 🏗️ Architecture & Patterns
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
wikijs/
|
||||
├── __init__.py # Package entry point
|
||||
├── client.py # Main client class
|
||||
├── exceptions.py # Exception hierarchy
|
||||
├── models/ # Data models (Pydantic)
|
||||
├── auth/ # Authentication handlers
|
||||
├── endpoints/ # API endpoint implementations
|
||||
└── utils/ # Utility functions
|
||||
```
|
||||
|
||||
### Key Patterns
|
||||
- **Dependency Injection**: Use abstract interfaces
|
||||
- **Type Safety**: Full type hints and validation
|
||||
- **Error Handling**: Comprehensive exception hierarchy
|
||||
- **Testing**: Mock external dependencies
|
||||
- **Documentation**: Example-driven docstrings
|
||||
|
||||
## 🧪 Testing Guidelines
|
||||
|
||||
### Test Categories
|
||||
- **Unit Tests**: Test individual components in isolation
|
||||
- **Integration Tests**: Test component interactions
|
||||
- **End-to-End**: Test with real Wiki.js instance (CI only)
|
||||
|
||||
### Test Organization
|
||||
```
|
||||
tests/
|
||||
├── unit/
|
||||
│ ├── test_client.py
|
||||
│ ├── test_models.py
|
||||
│ └── test_auth.py
|
||||
├── integration/
|
||||
│ └── test_api_endpoints.py
|
||||
└── conftest.py # Shared fixtures
|
||||
```
|
||||
|
||||
### Writing Good Tests
|
||||
```python
|
||||
def test_specific_behavior_with_expected_outcome():
|
||||
"""Test description should be clear and specific."""
|
||||
# Arrange
|
||||
client = WikiJSClient("https://example.com", "key")
|
||||
|
||||
# Act
|
||||
result = client.some_method()
|
||||
|
||||
# Assert
|
||||
assert result.expected_property == "expected_value"
|
||||
```
|
||||
|
||||
## 🐛 Bug Reports
|
||||
|
||||
### Before Reporting
|
||||
1. Check existing issues
|
||||
2. Test with latest version
|
||||
3. Provide minimal reproduction case
|
||||
|
||||
### Bug Report Checklist
|
||||
- [ ] Clear description of the problem
|
||||
- [ ] Steps to reproduce
|
||||
- [ ] Expected vs actual behavior
|
||||
- [ ] Environment details
|
||||
- [ ] Error messages/stack traces
|
||||
- [ ] Minimal code example
|
||||
|
||||
## ✨ Feature Requests
|
||||
|
||||
### Before Requesting
|
||||
1. Check if feature already exists
|
||||
2. Search existing feature requests
|
||||
3. Consider if it fits project scope
|
||||
|
||||
### Feature Request Checklist
|
||||
- [ ] Clear use case description
|
||||
- [ ] Proposed API design
|
||||
- [ ] Implementation considerations
|
||||
- [ ] Breaking change analysis
|
||||
|
||||
## 🚢 Release Process
|
||||
|
||||
Releases are managed by maintainers:
|
||||
|
||||
1. **Version Bump**: Update version in `wikijs/version.py`
|
||||
2. **Changelog**: Update `CHANGELOG.md` with changes
|
||||
3. **Tag Release**: Create git tag `v0.1.0`
|
||||
4. **Automated**: GitHub Actions handles building and PyPI publishing
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Types of Documentation
|
||||
- **API Reference**: Auto-generated from docstrings
|
||||
- **User Guides**: How-to guides and tutorials
|
||||
- **Examples**: Real-world usage examples
|
||||
- **Architecture**: Technical design decisions
|
||||
|
||||
### Documentation Standards
|
||||
- Write for your audience (users vs contributors)
|
||||
- Include practical examples
|
||||
- Keep it up-to-date with code changes
|
||||
- Use clear, concise language
|
||||
|
||||
## 🤖 AI Development Context
|
||||
|
||||
This project uses Claude AI for development coordination. If you're interested in the AI-assisted development process:
|
||||
|
||||
- See [CLAUDE.md](CLAUDE.md) for AI coordination details
|
||||
- Development tasks are tracked and managed through AI sessions
|
||||
- Quality standards are maintained through automated tooling
|
||||
- Community contributions are integrated with AI-assisted development
|
||||
|
||||
## ❓ Getting Help
|
||||
|
||||
### Questions and Support
|
||||
- **GitHub Discussions**: General questions and community chat
|
||||
- **GitHub Issues**: Bug reports and feature requests
|
||||
- **Documentation**: Check docs for existing answers
|
||||
- **Code Review**: Learn through the review process
|
||||
|
||||
### Common Questions
|
||||
|
||||
**Q: How do I set up a test Wiki.js instance?**
|
||||
A: Check the testing documentation for local setup instructions.
|
||||
|
||||
**Q: What should I work on first?**
|
||||
A: Look for `good first issue` labels or check CLAUDE.md for current priorities.
|
||||
|
||||
**Q: How do I add a new API endpoint?**
|
||||
A: Follow the existing patterns in `wikijs/endpoints/` and add corresponding tests.
|
||||
|
||||
## 🙏 Recognition
|
||||
|
||||
All contributors are recognized in:
|
||||
- `CONTRIBUTORS.md` file
|
||||
- Release notes for significant contributions
|
||||
- GitHub contributors page
|
||||
|
||||
Significant contributors may be invited to become maintainers.
|
||||
|
||||
---
|
||||
|
||||
**Ready to contribute?**
|
||||
|
||||
1. Read our [Governance](docs/GOVERNANCE.md) guidelines
|
||||
2. Check the [current development status](CLAUDE.md)
|
||||
3. Look for [good first issues](https://github.com/yourusername/wikijs-python-sdk/labels/good%20first%20issue)
|
||||
4. Join the discussion!
|
||||
|
||||
**Questions?** Don't hesitate to ask in [GitHub Discussions](https://github.com/yourusername/wikijs-python-sdk/discussions) or create an issue.
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Wiki.js Python SDK Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
162
README.md
162
README.md
@@ -1,2 +1,160 @@
|
||||
# wikijs-sdk-python
|
||||
A comprehensive, Python SDK for Wiki.js
|
||||
# Wiki.js Python SDK
|
||||
|
||||
[](https://badge.fury.io/py/wikijs-python-sdk)
|
||||
[](https://pypi.org/project/wikijs-python-sdk/)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://github.com/yourusername/wikijs-python-sdk/actions)
|
||||
[](https://codecov.io/gh/yourusername/wikijs-python-sdk)
|
||||
|
||||
**A professional Python SDK for Wiki.js API integration, developed entirely with AI assistance.**
|
||||
|
||||
> **🚧 Status**: Currently in Phase 1 - MVP Development (0% complete)
|
||||
> **Next Milestone**: v0.1.0 with basic Wiki.js integration and Pages API
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Installation
|
||||
```bash
|
||||
# Coming soon - not yet published
|
||||
pip install wikijs-python-sdk
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
```python
|
||||
from wikijs import WikiJSClient
|
||||
|
||||
# Initialize client
|
||||
client = WikiJSClient('https://wiki.example.com', auth='your-api-key')
|
||||
|
||||
# List pages
|
||||
pages = client.pages.list()
|
||||
|
||||
# Get a specific page
|
||||
page = client.pages.get(123)
|
||||
|
||||
# Create a new page
|
||||
from wikijs.models import PageCreate
|
||||
new_page = client.pages.create(PageCreate(
|
||||
title="Getting Started",
|
||||
path="getting-started",
|
||||
content="# Welcome\n\nThis is your first page!"
|
||||
))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Current Development Status
|
||||
|
||||
### **Phase 1: MVP Development** (Target: 2 weeks)
|
||||
- 🔄 **In Progress**: Project foundation setup
|
||||
- 🎯 **Goal**: Basic Wiki.js integration with Pages API
|
||||
- 📦 **Deliverable**: Installable package with core functionality
|
||||
|
||||
| Component | Status | Description |
|
||||
|-----------|--------|-------------|
|
||||
| **Project Setup** | 🔄 In Progress | Repository structure, packaging, CI/CD |
|
||||
| **Core Client** | ⏳ Pending | HTTP client with authentication |
|
||||
| **Pages API** | ⏳ Pending | CRUD operations for wiki pages |
|
||||
| **Testing** | ⏳ Pending | Comprehensive test suite |
|
||||
| **Documentation** | ⏳ Pending | API reference and examples |
|
||||
|
||||
### **Planned Features**
|
||||
- **v0.2.0**: Complete API coverage (Users, Groups, Assets)
|
||||
- **v0.3.0**: Production features (retry logic, caching, monitoring)
|
||||
- **v1.0.0**: Enterprise features (async support, plugins, advanced CLI)
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### **For Users**
|
||||
- **[Quick Start](#quick-start)**: Basic setup and usage
|
||||
- **[API Reference](docs/api_reference.md)**: Complete SDK documentation *(Coming soon)*
|
||||
- **[Examples](examples/)**: Real-world usage examples *(Coming soon)*
|
||||
|
||||
### **For Contributors**
|
||||
- **[Contributing Guide](CONTRIBUTING.md)**: How to contribute *(Coming soon)*
|
||||
- **[Development Setup](docs/development.md)**: Local development guide *(Coming soon)*
|
||||
|
||||
### **For Maintainers**
|
||||
- **[Architecture](docs/wikijs_sdk_architecture.md)**: Technical design and patterns
|
||||
- **[Development Plan](docs/wikijs_sdk_release_plan.md)**: Complete roadmap and milestones
|
||||
- **[AI Coordination](CLAUDE.md)**: AI-assisted development workflow
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome contributions! This project showcases AI-powered development with professional standards.
|
||||
|
||||
**Getting Started:**
|
||||
1. Check our [Development Plan](docs/wikijs_sdk_release_plan.md) for current priorities
|
||||
2. Review the [Architecture](docs/wikijs_sdk_architecture.md) for technical context
|
||||
3. See [AI Coordination](CLAUDE.md) for development workflow
|
||||
4. Start with issues labeled `good first issue` *(Coming soon)*
|
||||
|
||||
**Community:**
|
||||
- 💬 **GitHub Discussions**: Questions and community chat *(Coming soon)*
|
||||
- 🐛 **GitHub Issues**: Bug reports and feature requests *(Coming soon)*
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Development Setup
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.8+
|
||||
- Git
|
||||
- Wiki.js instance for testing
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Clone and setup (when repository is published)
|
||||
git clone https://github.com/yourusername/wikijs-python-sdk
|
||||
cd wikijs-python-sdk
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# Run tests
|
||||
pytest
|
||||
|
||||
# Run quality checks
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏆 Project Features
|
||||
|
||||
### **Current (MVP in development)**
|
||||
- 🔄 Synchronous HTTP client
|
||||
- 🔄 API key authentication
|
||||
- 🔄 Pages CRUD operations
|
||||
- 🔄 Comprehensive error handling
|
||||
- 🔄 Type-safe models with validation
|
||||
|
||||
### **Planned Enhancements**
|
||||
- ⚡ Async/await support
|
||||
- 💾 Intelligent caching
|
||||
- 🔄 Retry logic with backoff
|
||||
- 💻 CLI tools
|
||||
- 🔧 Plugin system
|
||||
- 🛡️ Advanced security features
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
---
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
- **Wiki.js**: The excellent knowledge management platform this SDK supports
|
||||
- **Claude (Anthropic)**: AI assistant powering the complete development process
|
||||
- **Python Community**: For exceptional tools and development standards
|
||||
|
||||
---
|
||||
|
||||
**Ready to contribute?** Check out our [development documentation](docs/) or explore the [AI coordination workflow](CLAUDE.md) to see how this project is built!
|
||||
187
docs/GOVERNANCE.md
Normal file
187
docs/GOVERNANCE.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# Wiki.js Python SDK - Community Governance
|
||||
|
||||
**Project**: wikijs-python-sdk
|
||||
**Stage**: MVP Development
|
||||
**Version**: 1.0
|
||||
**Last Updated**: July 2025
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Mission Statement
|
||||
|
||||
Create a high-quality Python SDK for Wiki.js that serves developers' needs while fostering an inclusive, collaborative community.
|
||||
|
||||
**Core Values:**
|
||||
- **Quality**: Prioritize working code and user experience
|
||||
- **Simplicity**: Keep processes lightweight and focused
|
||||
- **Community**: Welcome contributors of all experience levels
|
||||
- **Transparency**: Open development with clear communication
|
||||
|
||||
---
|
||||
|
||||
## 👥 Project Roles
|
||||
|
||||
### **Maintainer**
|
||||
**Current**: Project Lead
|
||||
**Responsibilities:**
|
||||
- Project direction and roadmap decisions
|
||||
- Code review and merge approval
|
||||
- Release management
|
||||
- Community support and issue triage
|
||||
|
||||
**Authority:**
|
||||
- Final decision on feature additions
|
||||
- Merge rights to main branch
|
||||
- Create releases and manage PyPI publishing
|
||||
|
||||
### **Contributors**
|
||||
**Anyone participating in the project**
|
||||
**How to Contribute:**
|
||||
- Report bugs with clear reproduction steps
|
||||
- Suggest features with use cases
|
||||
- Submit pull requests following our standards
|
||||
- Help answer questions in discussions
|
||||
- Improve documentation and examples
|
||||
|
||||
**Recognition:**
|
||||
- All contributors listed in CONTRIBUTORS.md
|
||||
- Significant contributors highlighted in releases
|
||||
- Path to maintainer role for consistent contributors
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Development Process
|
||||
|
||||
### **Issue Management**
|
||||
1. **Bug Reports**: Use issue templates with reproduction steps
|
||||
2. **Feature Requests**: Describe use case and expected behavior
|
||||
3. **Questions**: Use GitHub Discussions for general help
|
||||
4. **Priority**: Focus on MVP completion, then community feedback
|
||||
|
||||
### **Pull Request Process**
|
||||
1. **Fork & Branch**: Create feature branch from `main`
|
||||
2. **Develop**: Follow coding standards and write tests
|
||||
3. **Test**: Ensure all tests pass and coverage maintained
|
||||
4. **Review**: Maintainer reviews and provides feedback
|
||||
5. **Merge**: Approved changes merged to main
|
||||
|
||||
### **Release Process**
|
||||
- **Version**: Semantic versioning (MAJOR.MINOR.PATCH)
|
||||
- **Frequency**: Regular releases based on feature completion
|
||||
- **Testing**: All quality gates must pass before release
|
||||
- **Communication**: Release notes published with each version
|
||||
|
||||
---
|
||||
|
||||
## 📋 Quality Standards
|
||||
|
||||
### **Code Requirements**
|
||||
- **Tests**: All new features must include tests
|
||||
- **Coverage**: Maintain >85% test coverage
|
||||
- **Types**: Type hints required for public APIs
|
||||
- **Style**: Follow black, isort, flake8 formatting
|
||||
- **Documentation**: Docstrings for all public methods
|
||||
|
||||
### **Review Criteria**
|
||||
- [ ] Code follows established patterns
|
||||
- [ ] Tests cover new functionality
|
||||
- [ ] Documentation updated if needed
|
||||
- [ ] No breaking changes without discussion
|
||||
- [ ] Performance impact considered
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Community Guidelines
|
||||
|
||||
### **Expected Behavior**
|
||||
- Be respectful and constructive in all interactions
|
||||
- Focus on the code and ideas, not the person
|
||||
- Welcome newcomers and help them get started
|
||||
- Share knowledge and learn from others
|
||||
- Assume good intentions in communications
|
||||
|
||||
### **Unacceptable Behavior**
|
||||
- Personal attacks or harassment
|
||||
- Discriminatory language or behavior
|
||||
- Trolling or intentionally disruptive behavior
|
||||
- Sharing private information without consent
|
||||
|
||||
### **Enforcement**
|
||||
- **Level 1**: Private discussion with maintainer
|
||||
- **Level 2**: Public warning and guidance
|
||||
- **Level 3**: Temporary restriction from participation
|
||||
- **Level 4**: Permanent ban (only for severe violations)
|
||||
|
||||
Report issues to: [Maintainer Contact] - all reports handled confidentially.
|
||||
|
||||
---
|
||||
|
||||
## 📞 Communication Channels
|
||||
|
||||
### **GitHub Issues**
|
||||
- Bug reports and feature requests
|
||||
- Project planning and roadmap discussions
|
||||
- Technical questions about implementation
|
||||
|
||||
### **GitHub Discussions** *(Coming Soon)*
|
||||
- General help and usage questions
|
||||
- Community showcase and success stories
|
||||
- Brainstorming new ideas and improvements
|
||||
|
||||
### **Response Expectations**
|
||||
- **Issues**: Response within 48-72 hours
|
||||
- **Pull Requests**: Initial review within 1 week
|
||||
- **Discussions**: Community-driven with maintainer backup
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Decision Making
|
||||
|
||||
### **For MVP Development**
|
||||
- **Maintainer Authority**: Final decisions on scope and implementation
|
||||
- **Community Input**: Gathered through issues and discussions
|
||||
- **Focus**: Complete MVP first, then expand based on feedback
|
||||
|
||||
### **Post-MVP Development**
|
||||
- **Feature Requests**: Community voting and discussion
|
||||
- **Breaking Changes**: Require community discussion period
|
||||
- **Major Decisions**: Seek consensus among active contributors
|
||||
|
||||
---
|
||||
|
||||
## 📈 Growth & Evolution
|
||||
|
||||
### **Path to Contributor Recognition**
|
||||
1. **First-time Contributors**: Welcomed and guided through process
|
||||
2. **Regular Contributors**: Recognized in releases and documentation
|
||||
3. **Core Contributors**: Trusted with triage and review responsibilities
|
||||
4. **Maintainers**: Full project authority for proven long-term contributors
|
||||
|
||||
### **Governance Evolution**
|
||||
This lightweight governance will evolve as the community grows:
|
||||
- **10+ Contributors**: Add formal contributor guidelines
|
||||
- **Community Growth**: Implement more structured decision processes
|
||||
- **Multiple Maintainers**: Establish maintainer team processes
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### **New Contributors**
|
||||
1. **Read** this governance and project README
|
||||
2. **Browse** open issues labeled `good first issue`
|
||||
3. **Ask Questions** in GitHub Discussions
|
||||
4. **Start Small** with documentation or test improvements
|
||||
5. **Follow** the pull request process
|
||||
|
||||
### **Quick Links**
|
||||
- **[Development Plan](wikijs_sdk_release_plan.md)**: Current roadmap and priorities
|
||||
- **[Architecture](wikijs_sdk_architecture.md)**: Technical design overview
|
||||
- **[CLAUDE.md](../CLAUDE.md)**: AI-assisted development workflow
|
||||
- **[Contributing Guide](../CONTRIBUTING.md)**: Detailed contribution process *(Coming Soon)*
|
||||
|
||||
---
|
||||
|
||||
**Questions about governance?** Start a discussion or reach out to the maintainer directly. We're here to help and always open to improving our processes!
|
||||
|
||||
**Ready to contribute?** Check out our [current development priorities](wikijs_sdk_release_plan.md) and jump in!
|
||||
237
docs/RISK_MANAGEMENT.md
Normal file
237
docs/RISK_MANAGEMENT.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Wiki.js Python SDK - Risk Management
|
||||
|
||||
**Project**: wikijs-python-sdk
|
||||
**Stage**: MVP Development
|
||||
**Version**: 1.0
|
||||
**Last Updated**: July 2025
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
This document identifies and addresses key risks for the MVP development phase. As an AI-assisted project in early development, we focus on the most critical risks that could impact successful delivery.
|
||||
|
||||
### **Risk Management Approach**
|
||||
- **Proactive Identification**: Anticipate issues before they occur
|
||||
- **Practical Mitigation**: Focus on actionable solutions
|
||||
- **Regular Review**: Assess risks weekly during development
|
||||
- **Continuous Learning**: Update strategies based on experience
|
||||
|
||||
---
|
||||
|
||||
## 🔴 High Priority Risks
|
||||
|
||||
### **R1: Development Timeline Delays**
|
||||
**Risk**: MVP development takes longer than 2-week target
|
||||
**Probability**: Medium | **Impact**: High | **Level**: 🔴 HIGH
|
||||
|
||||
**Causes:**
|
||||
- Underestimated task complexity
|
||||
- Scope creep during development
|
||||
- Technical challenges with Wiki.js API integration
|
||||
- AI session limitations affecting development flow
|
||||
|
||||
**Mitigation Strategies:**
|
||||
- ✅ **Strict Scope Control**: No feature additions during MVP development
|
||||
- ✅ **Daily Progress Tracking**: Update completion status in CLAUDE.md
|
||||
- ✅ **Buffer Time**: Built-in 20% buffer for unexpected issues
|
||||
- ✅ **Fallback Plan**: Reduce MVP scope if timeline at risk
|
||||
|
||||
**Monitoring:**
|
||||
- Track actual vs. estimated time for each task
|
||||
- Weekly milestone reviews
|
||||
- Early warning if >20% behind schedule
|
||||
|
||||
---
|
||||
|
||||
### **R2: Wiki.js API Compatibility Issues**
|
||||
**Risk**: Changes in Wiki.js API break SDK functionality
|
||||
**Probability**: Medium | **Impact**: High | **Level**: 🔴 HIGH
|
||||
|
||||
**Causes:**
|
||||
- Wiki.js API changes without notice
|
||||
- Undocumented API behavior
|
||||
- Version compatibility issues
|
||||
- Authentication method changes
|
||||
|
||||
**Mitigation Strategies:**
|
||||
- ✅ **Version Pinning**: Test against specific Wiki.js versions
|
||||
- ✅ **Graceful Degradation**: Handle API errors without complete failure
|
||||
- ✅ **Documentation**: Clear supported version requirements
|
||||
- ✅ **Testing**: Comprehensive integration tests with real Wiki.js instance
|
||||
|
||||
**Monitoring:**
|
||||
- Test against latest Wiki.js releases
|
||||
- Monitor Wiki.js changelog and releases
|
||||
- Community feedback on compatibility issues
|
||||
|
||||
---
|
||||
|
||||
### **R3: Quality Standards Not Met**
|
||||
**Risk**: Code quality falls below professional standards
|
||||
**Probability**: Low | **Impact**: High | **Level**: 🔴 HIGH
|
||||
|
||||
**Causes:**
|
||||
- Rushing to meet timeline
|
||||
- Skipping tests or documentation
|
||||
- Inconsistent code style
|
||||
- Insufficient error handling
|
||||
|
||||
**Mitigation Strategies:**
|
||||
- ✅ **Automated Checks**: CI/CD pipeline with quality gates
|
||||
- ✅ **Test Coverage**: Maintain >85% coverage requirement
|
||||
- ✅ **Code Review**: All changes reviewed before merge
|
||||
- ✅ **Documentation**: API docs required for all public methods
|
||||
|
||||
**Quality Gates:**
|
||||
- [ ] Tests: 100% pass rate
|
||||
- [ ] Coverage: >85% line coverage
|
||||
- [ ] Types: 100% mypy compliance
|
||||
- [ ] Lint: 0 flake8 errors
|
||||
- [ ] Format: 100% black compliance
|
||||
|
||||
---
|
||||
|
||||
## 🟡 Medium Priority Risks
|
||||
|
||||
### **R4: Package Distribution Issues**
|
||||
**Risk**: Problems publishing to PyPI or package installation
|
||||
**Probability**: Medium | **Impact**: Medium | **Level**: 🟡 MEDIUM
|
||||
|
||||
**Mitigation:**
|
||||
- Test packaging and installation locally
|
||||
- Use automated publishing workflow
|
||||
- Validate package metadata and dependencies
|
||||
|
||||
### **R5: Documentation Gaps**
|
||||
**Risk**: Incomplete or unclear documentation affects adoption
|
||||
**Probability**: High | **Impact**: Medium | **Level**: 🟡 MEDIUM
|
||||
|
||||
**Mitigation:**
|
||||
- Write documentation alongside code
|
||||
- Include practical examples for all features
|
||||
- Test documentation with fresh install
|
||||
|
||||
### **R6: Community Reception Issues**
|
||||
**Risk**: Negative feedback or low adoption
|
||||
**Probability**: Low | **Impact**: Medium | **Level**: 🟡 MEDIUM
|
||||
|
||||
**Mitigation:**
|
||||
- Focus on solving real developer problems
|
||||
- Engage with Wiki.js community early
|
||||
- Gather feedback and iterate quickly
|
||||
|
||||
---
|
||||
|
||||
## 🟢 Low Priority Risks
|
||||
|
||||
### **R7: Performance Issues**
|
||||
**Risk**: SDK performance doesn't meet expectations
|
||||
**Probability**: Low | **Impact**: Low | **Level**: 🟢 LOW
|
||||
|
||||
**Note**: Performance optimization planned for Phase 3, not critical for MVP
|
||||
|
||||
### **R8: Security Vulnerabilities**
|
||||
**Risk**: Security issues in dependencies or code
|
||||
**Probability**: Low | **Impact**: Medium | **Level**: 🟢 LOW
|
||||
|
||||
**Mitigation**: Automated security scanning in CI/CD pipeline
|
||||
|
||||
---
|
||||
|
||||
## 📊 Risk Monitoring
|
||||
|
||||
### **Weekly Risk Review**
|
||||
Every week during MVP development:
|
||||
1. **Assess Current Risks**: Review probability and impact
|
||||
2. **Check Mitigation Status**: Ensure strategies are working
|
||||
3. **Identify New Risks**: Add emerging risks to list
|
||||
4. **Update Action Plans**: Adjust strategies as needed
|
||||
|
||||
### **Risk Indicators**
|
||||
**Red Flags** (Immediate attention required):
|
||||
- >1 day behind schedule on critical path
|
||||
- Test coverage drops below 80%
|
||||
- Major Wiki.js compatibility issue discovered
|
||||
- Critical bug discovered in core functionality
|
||||
|
||||
**Yellow Flags** (Monitor closely):
|
||||
- Minor delays in non-critical tasks
|
||||
- Documentation feedback indicates confusion
|
||||
- Community engagement lower than expected
|
||||
|
||||
### **Escalation Process**
|
||||
1. **🟢 Low Risk**: Handle in normal development process
|
||||
2. **🟡 Medium Risk**: Discuss in weekly reviews
|
||||
3. **🔴 High Risk**: Immediate mitigation action required
|
||||
4. **🚨 Critical Risk**: Consider scope reduction or timeline adjustment
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Contingency Plans
|
||||
|
||||
### **Timeline Recovery Plan**
|
||||
**If >20% behind schedule:**
|
||||
1. **Assess**: Identify specific blockers and time needed
|
||||
2. **Prioritize**: Focus only on core MVP features
|
||||
3. **Reduce Scope**: Remove non-essential features
|
||||
4. **Communicate**: Update timeline expectations
|
||||
|
||||
**Minimum Viable Features** (Cannot be removed):
|
||||
- Basic HTTP client with Wiki.js integration
|
||||
- API key authentication
|
||||
- Pages CRUD operations (list, get, create)
|
||||
- Basic error handling
|
||||
- Package installation via pip
|
||||
|
||||
### **API Compatibility Failure Plan**
|
||||
**If Wiki.js API breaks compatibility:**
|
||||
1. **Document**: Clearly specify supported Wiki.js versions
|
||||
2. **Workaround**: Implement fallback behavior where possible
|
||||
3. **Communicate**: Notify users of compatibility limitations
|
||||
4. **Update**: Plan fix for next release
|
||||
|
||||
### **Quality Failure Plan**
|
||||
**If quality standards not met:**
|
||||
1. **Stop**: Halt new feature development
|
||||
2. **Fix**: Address quality issues first
|
||||
3. **Review**: Identify process improvements
|
||||
4. **Resume**: Continue with improved practices
|
||||
|
||||
---
|
||||
|
||||
## 📈 Risk Learning & Improvement
|
||||
|
||||
### **Post-MVP Risk Review**
|
||||
After MVP completion, conduct comprehensive review:
|
||||
- **What Risks Materialized**: Which predictions were accurate
|
||||
- **What We Missed**: Risks that weren't anticipated
|
||||
- **Mitigation Effectiveness**: Which strategies worked best
|
||||
- **Process Improvements**: How to improve risk management
|
||||
|
||||
### **Future Phase Risk Planning**
|
||||
Use MVP experience to improve risk management for:
|
||||
- **Phase 2**: Essential features and community feedback
|
||||
- **Phase 3**: Production readiness and performance
|
||||
- **Phase 4**: Enterprise features and scaling
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Success Criteria
|
||||
|
||||
**MVP Risk Management Success:**
|
||||
- [ ] MVP delivered within 2-week timeline (±20%)
|
||||
- [ ] All quality gates passed before release
|
||||
- [ ] No critical bugs discovered in first week after release
|
||||
- [ ] Package successfully installed by early users
|
||||
- [ ] Documentation sufficient for basic usage
|
||||
|
||||
**Risk Management Process Success:**
|
||||
- [ ] All high-priority risks actively monitored
|
||||
- [ ] Mitigation strategies effectively implemented
|
||||
- [ ] Early warning systems prevented major issues
|
||||
- [ ] Lessons learned documented for future phases
|
||||
|
||||
---
|
||||
|
||||
*This risk management plan focuses on MVP development. A comprehensive risk framework will be developed for later phases based on lessons learned and project growth.*
|
||||
374
docs/wikijs_sdk_architecture.md
Normal file
374
docs/wikijs_sdk_architecture.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# Wiki.js Python SDK - Architecture Overview
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Status:** MVP Design Phase
|
||||
**Date:** July 2025
|
||||
|
||||
---
|
||||
|
||||
## 📋 Executive Summary
|
||||
|
||||
### Project Vision
|
||||
Create a professional Python SDK for Wiki.js that provides intuitive API access, robust error handling, and enterprise-grade features through a clean, extensible architecture.
|
||||
|
||||
### Core Objectives
|
||||
- **Developer Experience**: Intuitive, well-documented API
|
||||
- **Reliability**: Built-in retry logic and graceful error handling
|
||||
- **Performance**: Efficient resource management and caching
|
||||
- **Maintainability**: Clean architecture with comprehensive testing
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ High-Level Architecture
|
||||
|
||||
### System Overview
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Client Applications"
|
||||
A[Python Scripts]
|
||||
B[Web Applications]
|
||||
C[CLI Tools]
|
||||
end
|
||||
|
||||
subgraph "SDK Core"
|
||||
D[WikiJS Client]
|
||||
E[Authentication]
|
||||
F[Configuration]
|
||||
end
|
||||
|
||||
subgraph "API Endpoints"
|
||||
G[Pages API]
|
||||
H[Users API]
|
||||
I[Groups API]
|
||||
J[Assets API]
|
||||
end
|
||||
|
||||
subgraph "Infrastructure"
|
||||
K[HTTP Client]
|
||||
L[Error Handling]
|
||||
M[Caching Layer]
|
||||
end
|
||||
|
||||
subgraph "External"
|
||||
N[Wiki.js Server]
|
||||
end
|
||||
|
||||
A --> D
|
||||
B --> D
|
||||
C --> D
|
||||
D --> E
|
||||
D --> F
|
||||
D --> G
|
||||
D --> H
|
||||
D --> I
|
||||
D --> J
|
||||
G --> K
|
||||
H --> K
|
||||
I --> K
|
||||
J --> K
|
||||
K --> L
|
||||
K --> M
|
||||
K --> N
|
||||
```
|
||||
|
||||
### Architecture Principles
|
||||
|
||||
#### **1. Separation of Concerns**
|
||||
- Authentication isolated from API communication
|
||||
- Clear boundaries between endpoint handlers and HTTP transport
|
||||
- Modular design allowing independent testing
|
||||
|
||||
#### **2. Dependency Inversion**
|
||||
- Abstract interfaces for HTTP clients and authentication
|
||||
- Pluggable components for caching and configuration
|
||||
- Easily mockable dependencies for testing
|
||||
|
||||
#### **3. Fail-Fast & Graceful Degradation**
|
||||
- Early validation of inputs and configuration
|
||||
- Comprehensive error handling with meaningful messages
|
||||
- Graceful handling of network failures
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Core Components
|
||||
|
||||
### **WikiJS Client**
|
||||
```python
|
||||
class WikiJSClient:
|
||||
"""Main client for Wiki.js API interactions"""
|
||||
|
||||
def __init__(self, base_url: str, auth: AuthHandler, config: ClientConfig = None)
|
||||
|
||||
# Properties
|
||||
.pages # Pages API endpoint
|
||||
.users # Users API endpoint
|
||||
.groups # Groups API endpoint
|
||||
.assets # Assets API endpoint
|
||||
```
|
||||
|
||||
**Responsibilities:**
|
||||
- Central coordination of all API operations
|
||||
- Authentication and configuration management
|
||||
- HTTP request/response handling
|
||||
- Error propagation and logging
|
||||
|
||||
### **Authentication System**
|
||||
```python
|
||||
class AuthHandler(ABC):
|
||||
"""Abstract authentication interface"""
|
||||
def get_headers(self) -> Dict[str, str]
|
||||
def is_valid(self) -> bool
|
||||
def refresh(self) -> None
|
||||
|
||||
class APIKeyAuth(AuthHandler):
|
||||
"""API key authentication implementation"""
|
||||
|
||||
class JWTAuth(AuthHandler): # Future
|
||||
"""JWT token authentication implementation"""
|
||||
```
|
||||
|
||||
**Design Features:**
|
||||
- Pluggable authentication strategies
|
||||
- Automatic token refresh for JWT
|
||||
- Header management abstraction
|
||||
|
||||
### **API Endpoints**
|
||||
```python
|
||||
class BaseEndpoint:
|
||||
"""Base functionality for all API endpoints"""
|
||||
|
||||
class PagesEndpoint(BaseEndpoint):
|
||||
"""Pages API operations"""
|
||||
def list(self, limit: int = 50) -> List[Page]
|
||||
def get(self, page_id: int) -> Page
|
||||
def create(self, page_data: PageCreate) -> Page
|
||||
def update(self, page_id: int, **kwargs) -> Page
|
||||
def delete(self, page_id: int) -> bool
|
||||
```
|
||||
|
||||
**Design Features:**
|
||||
- Consistent interface across all endpoints
|
||||
- Type-safe request/response models
|
||||
- Built-in validation and error handling
|
||||
|
||||
### **Data Models**
|
||||
```python
|
||||
class BaseModel(Pydantic.BaseModel):
|
||||
"""Base model with validation and serialization"""
|
||||
|
||||
class Page(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
path: str
|
||||
content: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
# Business logic methods
|
||||
@property
|
||||
def word_count(self) -> int
|
||||
def to_markdown(self) -> str
|
||||
```
|
||||
|
||||
**Design Features:**
|
||||
- Pydantic-based validation
|
||||
- Rich domain models with business logic
|
||||
- Automatic serialization/deserialization
|
||||
|
||||
---
|
||||
|
||||
## 📊 Data Flow
|
||||
|
||||
### Request Flow
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as Application
|
||||
participant Client as WikiJS Client
|
||||
participant Auth as Auth Handler
|
||||
participant HTTP as HTTP Client
|
||||
participant API as Wiki.js API
|
||||
|
||||
App->>Client: pages.get(123)
|
||||
Client->>Auth: get_headers()
|
||||
Auth-->>Client: {"Authorization": "Bearer..."}
|
||||
Client->>HTTP: request(GET, /api/pages/123)
|
||||
HTTP->>API: HTTP Request
|
||||
API-->>HTTP: 200 OK + Data
|
||||
HTTP-->>Client: Response Data
|
||||
Client-->>App: Page Object
|
||||
```
|
||||
|
||||
### Error Handling Flow
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[API Request] --> B{HTTP Status}
|
||||
B -->|200-299| C[Success Response]
|
||||
B -->|400-499| D[Client Error]
|
||||
B -->|500-599| E[Server Error]
|
||||
B -->|Timeout| F[Network Error]
|
||||
|
||||
D --> G[ValidationError]
|
||||
E --> H[APIError]
|
||||
F --> I[ConnectionError]
|
||||
|
||||
G --> J[Log & Return Error]
|
||||
H --> J
|
||||
I --> J
|
||||
|
||||
C --> K[Parse & Return Data]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Project Structure
|
||||
|
||||
### Directory Layout
|
||||
```
|
||||
wikijs-python-sdk/
|
||||
├── wikijs/ # Main package
|
||||
│ ├── __init__.py # Package entry point
|
||||
│ ├── client.py # Main client class
|
||||
│ ├── exceptions.py # Exception hierarchy
|
||||
│ ├── models/ # Data models
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── base.py # Base model
|
||||
│ │ └── page.py # Page model
|
||||
│ ├── auth/ # Authentication
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── base.py # Auth interface
|
||||
│ │ └── api_key.py # API key auth
|
||||
│ ├── endpoints/ # API endpoints
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── base.py # Base endpoint
|
||||
│ │ └── pages.py # Pages API
|
||||
│ └── utils/ # Utilities
|
||||
│ ├── __init__.py
|
||||
│ └── helpers.py # Helper functions
|
||||
├── tests/ # Test suite
|
||||
├── docs/ # Documentation
|
||||
└── examples/ # Usage examples
|
||||
```
|
||||
|
||||
### Module Responsibilities
|
||||
|
||||
| Module | Purpose | Key Classes |
|
||||
|--------|---------|-------------|
|
||||
| `client.py` | Main SDK interface | `WikiJSClient` |
|
||||
| `exceptions.py` | Error handling | `WikiJSException`, `APIError` |
|
||||
| `models/` | Data structures | `Page`, `User`, `Group` |
|
||||
| `auth/` | Authentication | `AuthHandler`, `APIKeyAuth` |
|
||||
| `endpoints/` | API operations | `PagesEndpoint`, `UsersEndpoint` |
|
||||
| `utils/` | Helper functions | Validation, serialization |
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Extensibility Design
|
||||
|
||||
### Plugin Architecture (Future)
|
||||
```python
|
||||
class Plugin(ABC):
|
||||
"""Plugin interface for SDK extensions"""
|
||||
def before_request(self, request: Request) -> Request
|
||||
def after_response(self, response: Response) -> Response
|
||||
|
||||
class CachePlugin(Plugin):
|
||||
"""Caching functionality as a plugin"""
|
||||
|
||||
class MetricsPlugin(Plugin):
|
||||
"""Metrics collection as a plugin"""
|
||||
```
|
||||
|
||||
### Configuration System
|
||||
```python
|
||||
@dataclass
|
||||
class ClientConfig:
|
||||
# Connection settings
|
||||
base_url: str
|
||||
timeout: int = 30
|
||||
verify_ssl: bool = True
|
||||
|
||||
# Features
|
||||
cache_enabled: bool = False
|
||||
retry_enabled: bool = True
|
||||
|
||||
# Advanced
|
||||
plugins: List[Plugin] = field(default_factory=list)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Development Phases
|
||||
|
||||
### **Phase 1: MVP (Current)**
|
||||
- ✅ Core client with HTTP transport
|
||||
- ✅ API key authentication
|
||||
- ✅ Pages API with full CRUD
|
||||
- ✅ Basic error handling
|
||||
- ✅ Type-safe models
|
||||
|
||||
### **Phase 2: Essential Features**
|
||||
- Users, Groups, Assets APIs
|
||||
- Enhanced error handling with context
|
||||
- Configuration management system
|
||||
- Basic CLI interface
|
||||
|
||||
### **Phase 3: Production Ready**
|
||||
- Retry logic with exponential backoff
|
||||
- Caching system with multiple backends
|
||||
- Rate limiting and circuit breaker
|
||||
- Performance monitoring
|
||||
|
||||
### **Phase 4: Enterprise Grade**
|
||||
- Async support with asyncio
|
||||
- Plugin architecture
|
||||
- Advanced authentication (JWT, OAuth2)
|
||||
- Comprehensive CLI with interactive mode
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Design Decisions
|
||||
|
||||
### **Technology Choices**
|
||||
|
||||
| Component | Technology | Rationale |
|
||||
|-----------|------------|-----------|
|
||||
| **HTTP Client** | `requests` | Industry standard, reliable, well-documented |
|
||||
| **Validation** | `pydantic` | Type safety, automatic validation, great DX |
|
||||
| **Testing** | `pytest` | Powerful, flexible, extensive plugin ecosystem |
|
||||
| **CLI** | `click` + `rich` | User-friendly, feature-rich, beautiful output |
|
||||
| **Async** | `aiohttp` | Native asyncio support, high performance |
|
||||
|
||||
### **Key Architectural Decisions**
|
||||
|
||||
1. **Synchronous First**: Start with sync API, add async later
|
||||
2. **Type Safety**: Full type hints and runtime validation
|
||||
3. **Modular Design**: Clear separation of concerns
|
||||
4. **Configuration**: Support both programmatic and file-based config
|
||||
5. **Error Handling**: Comprehensive hierarchy with actionable messages
|
||||
|
||||
---
|
||||
|
||||
## 📈 Quality Standards
|
||||
|
||||
### **Code Quality**
|
||||
- **Type Coverage**: 100% type hints on public APIs
|
||||
- **Test Coverage**: >90% line coverage maintained
|
||||
- **Documentation**: All public methods documented
|
||||
- **Code Style**: Black + isort + flake8 compliance
|
||||
|
||||
### **Performance Targets**
|
||||
- **Cold Start**: <100ms import time
|
||||
- **Request Latency**: <50ms overhead per request
|
||||
- **Memory Usage**: <50MB for typical workloads
|
||||
- **Throughput**: >1000 req/s with connection pooling
|
||||
|
||||
### **Security**
|
||||
- No hardcoded credentials or secrets
|
||||
- Input validation on all user data
|
||||
- Secure defaults for all configuration
|
||||
- Regular dependency security scanning
|
||||
|
||||
---
|
||||
|
||||
*For detailed implementation specifications, see [Technical Specifications](technical/)*
|
||||
*For development tasks and coordination, see [CLAUDE.md](../CLAUDE.md)*
|
||||
204
docs/wikijs_sdk_release_plan.md
Normal file
204
docs/wikijs_sdk_release_plan.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Wiki.js Python SDK - Release Plan
|
||||
|
||||
**Project Name:** `wikijs-python-sdk`
|
||||
**Repository:** `https://github.com/yourusername/wikijs-python-sdk`
|
||||
**License:** MIT
|
||||
**Target Audience:** Python developers, DevOps engineers, Data scientists
|
||||
|
||||
---
|
||||
|
||||
## 📋 Project Overview
|
||||
|
||||
### Vision Statement
|
||||
Develop a production-ready Python SDK for Wiki.js that evolves from a simple, functional MVP to a comprehensive enterprise-grade solution through incremental releases.
|
||||
|
||||
### Release Philosophy
|
||||
- **MVP First**: Ship a working, useful product quickly
|
||||
- **Incremental Value**: Each release adds meaningful functionality
|
||||
- **Backward Compatibility**: Maintain API stability across releases
|
||||
- **Community Driven**: Gather feedback and iterate
|
||||
|
||||
### Success Metrics
|
||||
- **Adoption**: >100 PyPI downloads in first month
|
||||
- **Quality**: >90% test coverage maintained
|
||||
- **Community**: >10 GitHub stars, >3 contributors
|
||||
- **Stability**: <1% error rate in production usage
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Release Timeline
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Wiki.js SDK Development Timeline
|
||||
dateFormat YYYY-MM-DD
|
||||
section Phase 1: MVP
|
||||
Project Setup :p1-setup, 2025-07-29, 3d
|
||||
Core Implementation :p1-core, after p1-setup, 8d
|
||||
Release v0.1.0 :milestone, p1-release, after p1-core, 1d
|
||||
|
||||
section Phase 2: Essential Features
|
||||
API Expansion :p2-features, after p1-release, 10d
|
||||
Release v0.2.0 :milestone, p2-release, after p2-features, 1d
|
||||
|
||||
section Phase 3: Production Ready
|
||||
Reliability Features :p3-reliability, after p2-release, 15d
|
||||
Release v0.3.0 :milestone, p3-release, after p3-reliability, 1d
|
||||
|
||||
section Phase 4: Enterprise
|
||||
Advanced Features :p4-advanced, after p3-release, 20d
|
||||
Release v1.0.0 :milestone, p4-release, after p4-advanced, 1d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Phase 1: MVP Release (v0.1.0)
|
||||
|
||||
**Target:** 2 weeks from start
|
||||
**Goal:** Basic, functional Wiki.js integration
|
||||
|
||||
### Core Features
|
||||
- **HTTP Client**: Synchronous requests with basic error handling
|
||||
- **Authentication**: API key authentication
|
||||
- **Pages API**: Complete CRUD operations (list, get, create, update, delete)
|
||||
- **Models**: Type-safe data models with validation
|
||||
- **Testing**: Comprehensive test suite with >85% coverage
|
||||
- **Documentation**: API documentation and usage examples
|
||||
|
||||
### Success Criteria
|
||||
- [ ] Package installable via `pip install wikijs-python-sdk`
|
||||
- [ ] Basic page operations work with real Wiki.js instance
|
||||
- [ ] >85% test coverage with passing CI/CD
|
||||
- [ ] Complete API documentation
|
||||
|
||||
*Detailed task breakdown available in [CLAUDE.md](../CLAUDE.md)*
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Phase 2: Essential Features (v0.2.0)
|
||||
|
||||
**Target:** 4 weeks from start
|
||||
**Goal:** Complete API coverage and enhanced usability
|
||||
|
||||
### Key Features
|
||||
- **Complete API Coverage**: Users, Groups, Assets, System APIs
|
||||
- **Enhanced Error Handling**: Detailed error context and recovery suggestions
|
||||
- **Configuration System**: File-based and environment variable configuration
|
||||
- **Basic CLI**: Command-line interface for common operations
|
||||
- **Improved Documentation**: Comprehensive guides and examples
|
||||
|
||||
### Success Criteria
|
||||
- [ ] All major Wiki.js APIs covered
|
||||
- [ ] Configuration via files and environment variables
|
||||
- [ ] Basic CLI functionality working
|
||||
- [ ] >90% test coverage
|
||||
- [ ] Performance benchmarks established
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Phase 3: Production Ready (v0.3.0)
|
||||
|
||||
**Target:** 7 weeks from start
|
||||
**Goal:** Enterprise-grade reliability and performance
|
||||
|
||||
### Key Features
|
||||
- **Retry Logic**: Exponential backoff with jitter for failed requests
|
||||
- **Circuit Breaker**: Fault tolerance for unreliable connections
|
||||
- **Intelligent Caching**: Multi-backend caching with smart invalidation
|
||||
- **Rate Limiting**: Respect API limits and prevent abuse
|
||||
- **Monitoring**: Performance metrics and health monitoring
|
||||
- **Bulk Operations**: Efficient batch processing capabilities
|
||||
|
||||
### Success Criteria
|
||||
- [ ] Production-ready reliability features
|
||||
- [ ] Performance benchmarks show >50% improvement
|
||||
- [ ] Cache hit ratio >80% in typical usage
|
||||
- [ ] Zero-downtime error handling
|
||||
- [ ] Comprehensive monitoring and logging
|
||||
|
||||
---
|
||||
|
||||
## 🌟 Phase 4: Enterprise Grade (v1.0.0)
|
||||
|
||||
**Target:** 11 weeks from start
|
||||
**Goal:** Full-featured enterprise SDK
|
||||
|
||||
### Key Features
|
||||
- **Async Support**: Complete asyncio integration with aiohttp
|
||||
- **Advanced CLI**: Interactive mode, progress bars, bulk operations
|
||||
- **Plugin Architecture**: Extensible middleware and custom auth providers
|
||||
- **Advanced Security**: JWT rotation, OAuth2, audit logging
|
||||
- **Enterprise Features**: Multi-tenancy, custom headers, webhooks
|
||||
- **Performance Optimizations**: Connection pooling, request batching
|
||||
|
||||
### Success Criteria
|
||||
- [ ] Feature parity with official SDKs
|
||||
- [ ] Async performance >3x sync performance
|
||||
- [ ] Plugin ecosystem established
|
||||
- [ ] Enterprise security features complete
|
||||
- [ ] Comprehensive documentation and tutorials
|
||||
|
||||
---
|
||||
|
||||
## 📦 Deployment & Distribution
|
||||
|
||||
### Release Process
|
||||
1. **Automated Testing**: All tests pass with quality gates
|
||||
2. **Security Scanning**: Dependency and code security validation
|
||||
3. **Performance Benchmarking**: Regression testing
|
||||
4. **Documentation Update**: Synchronized with code changes
|
||||
5. **PyPI Publishing**: Automated package distribution
|
||||
6. **GitHub Release**: Tagged release with changelog
|
||||
|
||||
### Version Management
|
||||
- **Semantic Versioning**: MAJOR.MINOR.PATCH
|
||||
- **MAJOR**: Breaking changes
|
||||
- **MINOR**: New features, backward compatible
|
||||
- **PATCH**: Bug fixes, backward compatible
|
||||
|
||||
### Quality Gates
|
||||
| Check | Tool | Threshold |
|
||||
|-------|------|-----------|
|
||||
| Tests | pytest | 100% pass |
|
||||
| Coverage | pytest-cov | >90% |
|
||||
| Types | mypy | 100% pass |
|
||||
| Lint | flake8 | 0 errors |
|
||||
| Security | bandit | 0 issues |
|
||||
| Format | black | 100% formatted |
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Community & Maintenance
|
||||
|
||||
### Community Building
|
||||
- **Documentation First**: Comprehensive guides and examples
|
||||
- **Issue Templates**: Structured bug reports and feature requests
|
||||
- **Contributing Guidelines**: Clear onboarding for new contributors
|
||||
- **Code of Conduct**: Inclusive community standards
|
||||
|
||||
### Long-term Maintenance
|
||||
- **Regular Updates**: Monthly releases with improvements
|
||||
- **Security Patches**: Rapid response to security issues
|
||||
- **Compatibility**: Support for new Wiki.js versions
|
||||
- **Performance**: Continuous optimization and monitoring
|
||||
|
||||
---
|
||||
|
||||
## 📈 Success Tracking
|
||||
|
||||
### Key Metrics
|
||||
- **PyPI Downloads**: Measure adoption growth
|
||||
- **GitHub Engagement**: Stars, forks, issues, PRs
|
||||
- **Test Coverage**: Maintain >90% throughout development
|
||||
- **Performance**: Response time and throughput benchmarks
|
||||
- **Community**: Contributors, issue resolution time
|
||||
|
||||
### Milestone Reviews
|
||||
- **After Each Phase**: Comprehensive retrospective
|
||||
- **Process Optimization**: Improve development efficiency
|
||||
- **Community Feedback**: Incorporate user suggestions
|
||||
- **Technical Debt**: Address accumulated debt
|
||||
|
||||
---
|
||||
|
||||
*For detailed development tasks and AI coordination, see [CLAUDE.md](../CLAUDE.md)*
|
||||
124
pyproject.toml
Normal file
124
pyproject.toml
Normal file
@@ -0,0 +1,124 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
dynamic = ["version"]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "wikijs.version.__version__"}
|
||||
|
||||
[tool.black]
|
||||
line-length = 88
|
||||
target-version = ['py38']
|
||||
include = '\.pyi?$'
|
||||
extend-exclude = '''
|
||||
/(
|
||||
# directories
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| build
|
||||
| dist
|
||||
)/
|
||||
'''
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
multi_line_output = 3
|
||||
line_length = 88
|
||||
known_first_party = ["wikijs"]
|
||||
known_third_party = ["pytest", "requests", "pydantic"]
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.8"
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
check_untyped_defs = true
|
||||
disallow_untyped_decorators = true
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
warn_no_return = true
|
||||
warn_unreachable = true
|
||||
strict_equality = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"requests.*",
|
||||
"aiohttp.*",
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
addopts = [
|
||||
"--strict-markers",
|
||||
"--strict-config",
|
||||
"--cov=wikijs",
|
||||
"--cov-report=term-missing",
|
||||
"--cov-report=html",
|
||||
"--cov-report=xml",
|
||||
"--cov-fail-under=85",
|
||||
]
|
||||
markers = [
|
||||
"unit: Unit tests",
|
||||
"integration: Integration tests",
|
||||
"slow: Slow tests",
|
||||
"network: Tests requiring network access",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["wikijs"]
|
||||
omit = [
|
||||
"*/tests/*",
|
||||
"*/test_*",
|
||||
"wikijs/cli/*", # CLI tested separately initially
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
"if __name__ == .__main__.:",
|
||||
"if TYPE_CHECKING:",
|
||||
]
|
||||
|
||||
[tool.bandit]
|
||||
exclude_dirs = ["tests"]
|
||||
skips = ["B101"] # Skip assert_used test
|
||||
|
||||
[tool.flake8]
|
||||
max-line-length = 88
|
||||
select = ["E", "W", "F", "C", "N"]
|
||||
ignore = [
|
||||
"E203", # whitespace before ':' (conflicts with black)
|
||||
"E501", # line too long (handled by black)
|
||||
"W503", # line break before binary operator (conflicts with black)
|
||||
]
|
||||
exclude = [
|
||||
".git",
|
||||
"__pycache__",
|
||||
"build",
|
||||
"dist",
|
||||
".eggs",
|
||||
"*.egg-info",
|
||||
".venv",
|
||||
"venv",
|
||||
".tox"
|
||||
]
|
||||
per-file-ignores = [
|
||||
"tests/*:F401,F811", # Allow unused imports in tests
|
||||
"__init__.py:F401", # Allow unused imports in __init__.py
|
||||
]
|
||||
max-complexity = 10
|
||||
26
requirements-dev.txt
Normal file
26
requirements-dev.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
# Development dependencies for Wiki.js Python SDK
|
||||
-r requirements.txt
|
||||
|
||||
# Testing
|
||||
pytest>=7.0.0
|
||||
pytest-cov>=4.0.0
|
||||
pytest-asyncio>=0.21.0
|
||||
responses>=0.20.0
|
||||
|
||||
# Code quality
|
||||
black>=22.0.0
|
||||
isort>=5.10.0
|
||||
flake8>=5.0.0
|
||||
mypy>=0.991
|
||||
bandit[toml]>=1.7.0
|
||||
|
||||
# Pre-commit hooks
|
||||
pre-commit>=2.20.0
|
||||
|
||||
# Development tools
|
||||
ipython>=8.0.0
|
||||
twine>=4.0.0
|
||||
build>=0.8.0
|
||||
|
||||
# Optional async support (for future phases)
|
||||
aiohttp>=3.8.0
|
||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# Core dependencies for Wiki.js Python SDK
|
||||
requests>=2.28.0
|
||||
pydantic>=1.10.0
|
||||
typing-extensions>=4.0.0
|
||||
106
setup.py
Normal file
106
setup.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""Setup configuration for wikijs-python-sdk."""
|
||||
|
||||
import os
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# Read version from file
|
||||
def get_version():
|
||||
version_file = os.path.join(os.path.dirname(__file__), "wikijs", "version.py")
|
||||
if os.path.exists(version_file):
|
||||
with open(version_file) as f:
|
||||
for line in f:
|
||||
if line.startswith("__version__"):
|
||||
return line.split("=")[1].strip().strip('"').strip("'")
|
||||
return "0.1.0" # Fallback version
|
||||
|
||||
# Read long description from README
|
||||
def get_long_description():
|
||||
readme_path = os.path.join(os.path.dirname(__file__), "README.md")
|
||||
if os.path.exists(readme_path):
|
||||
with open(readme_path, "r", encoding="utf-8") as fh:
|
||||
return fh.read()
|
||||
return "A professional Python SDK for Wiki.js API integration"
|
||||
|
||||
# Read requirements
|
||||
def get_requirements():
|
||||
req_path = os.path.join(os.path.dirname(__file__), "requirements.txt")
|
||||
if os.path.exists(req_path):
|
||||
with open(req_path) as f:
|
||||
return [
|
||||
line.strip()
|
||||
for line in f
|
||||
if line.strip() and not line.startswith("#")
|
||||
]
|
||||
return ["requests>=2.28.0", "pydantic>=1.10.0"]
|
||||
|
||||
setup(
|
||||
name="wikijs-python-sdk",
|
||||
version=get_version(),
|
||||
author="Wiki.js SDK Contributors",
|
||||
author_email="",
|
||||
description="A professional Python SDK for Wiki.js API integration",
|
||||
long_description=get_long_description(),
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/yourusername/wikijs-python-sdk",
|
||||
project_urls={
|
||||
"Bug Reports": "https://github.com/yourusername/wikijs-python-sdk/issues",
|
||||
"Source": "https://github.com/yourusername/wikijs-python-sdk",
|
||||
"Documentation": "https://github.com/yourusername/wikijs-python-sdk/docs",
|
||||
},
|
||||
packages=find_packages(exclude=["tests*", "docs*", "examples*"]),
|
||||
classifiers=[
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
||||
"Topic :: Documentation",
|
||||
"Typing :: Typed",
|
||||
],
|
||||
python_requires=">=3.8",
|
||||
install_requires=get_requirements(),
|
||||
extras_require={
|
||||
"dev": [
|
||||
"pytest>=7.0.0",
|
||||
"pytest-cov>=4.0.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
"black>=22.0.0",
|
||||
"isort>=5.10.0",
|
||||
"flake8>=5.0.0",
|
||||
"mypy>=0.991",
|
||||
"pre-commit>=2.20.0",
|
||||
"bandit[toml]>=1.7.0",
|
||||
"responses>=0.20.0",
|
||||
],
|
||||
"async": [
|
||||
"aiohttp>=3.8.0",
|
||||
],
|
||||
"cli": [
|
||||
"click>=8.0.0",
|
||||
"rich>=12.0.0",
|
||||
],
|
||||
"all": [
|
||||
"aiohttp>=3.8.0",
|
||||
"click>=8.0.0",
|
||||
"rich>=12.0.0",
|
||||
],
|
||||
},
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"wikijs=wikijs.cli.main:main [cli]",
|
||||
],
|
||||
},
|
||||
include_package_data=True,
|
||||
package_data={
|
||||
"wikijs": ["py.typed"],
|
||||
},
|
||||
keywords="wiki wikijs api sdk client http rest",
|
||||
zip_safe=False,
|
||||
)
|
||||
77
wikijs/__init__.py
Normal file
77
wikijs/__init__.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""Wiki.js Python SDK - Professional SDK for Wiki.js API integration.
|
||||
|
||||
This package provides a comprehensive Python SDK for interacting with Wiki.js
|
||||
instances, including support for pages, users, groups, and system management.
|
||||
|
||||
Example:
|
||||
Basic usage:
|
||||
|
||||
>>> from wikijs import WikiJSClient
|
||||
>>> client = WikiJSClient('https://wiki.example.com', auth='your-api-key')
|
||||
>>> # API endpoints will be available as development progresses
|
||||
|
||||
Features:
|
||||
- Type-safe data models with validation
|
||||
- Comprehensive error handling
|
||||
- Automatic retry logic with exponential backoff
|
||||
- Professional logging and debugging support
|
||||
- Context manager support for resource cleanup
|
||||
"""
|
||||
|
||||
from .client import WikiJSClient
|
||||
from .exceptions import (
|
||||
WikiJSException,
|
||||
APIError,
|
||||
AuthenticationError,
|
||||
ConfigurationError,
|
||||
ValidationError,
|
||||
ClientError,
|
||||
ServerError,
|
||||
NotFoundError,
|
||||
PermissionError,
|
||||
RateLimitError,
|
||||
ConnectionError,
|
||||
TimeoutError,
|
||||
)
|
||||
from .models import BaseModel, Page, PageCreate, PageUpdate
|
||||
from .version import __version__, __version_info__
|
||||
|
||||
# Public API
|
||||
__all__ = [
|
||||
# Main client
|
||||
"WikiJSClient",
|
||||
|
||||
# Data models
|
||||
"BaseModel",
|
||||
"Page",
|
||||
"PageCreate",
|
||||
"PageUpdate",
|
||||
|
||||
# Exceptions
|
||||
"WikiJSException",
|
||||
"APIError",
|
||||
"AuthenticationError",
|
||||
"ConfigurationError",
|
||||
"ValidationError",
|
||||
"ClientError",
|
||||
"ServerError",
|
||||
"NotFoundError",
|
||||
"PermissionError",
|
||||
"RateLimitError",
|
||||
"ConnectionError",
|
||||
"TimeoutError",
|
||||
|
||||
# Version info
|
||||
"__version__",
|
||||
"__version_info__",
|
||||
]
|
||||
|
||||
# Package metadata
|
||||
__author__ = "Wiki.js SDK Contributors"
|
||||
__email__ = ""
|
||||
__license__ = "MIT"
|
||||
__description__ = "Professional Python SDK for Wiki.js API integration"
|
||||
__url__ = "https://github.com/yourusername/wikijs-python-sdk"
|
||||
|
||||
# For type checking
|
||||
__all__ += ["__author__", "__email__", "__license__", "__description__", "__url__"]
|
||||
19
wikijs/auth/__init__.py
Normal file
19
wikijs/auth/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Authentication module for wikijs-python-sdk.
|
||||
|
||||
This module will contain authentication handlers for different
|
||||
authentication methods supported by Wiki.js.
|
||||
|
||||
Future implementations:
|
||||
- API key authentication
|
||||
- JWT token authentication
|
||||
- OAuth2 authentication
|
||||
"""
|
||||
|
||||
# Placeholder for future authentication implementations
|
||||
# from .base import AuthHandler
|
||||
# from .api_key import APIKeyAuth
|
||||
# from .jwt import JWTAuth
|
||||
|
||||
__all__ = [
|
||||
# Will be implemented in Task 1.3
|
||||
]
|
||||
261
wikijs/client.py
Normal file
261
wikijs/client.py
Normal file
@@ -0,0 +1,261 @@
|
||||
"""Main WikiJS client for wikijs-python-sdk."""
|
||||
|
||||
import json
|
||||
from typing import Any, Dict, Optional, Union
|
||||
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
|
||||
from .exceptions import (
|
||||
APIError,
|
||||
AuthenticationError,
|
||||
ConfigurationError,
|
||||
ConnectionError,
|
||||
TimeoutError,
|
||||
create_api_error,
|
||||
)
|
||||
from .utils import normalize_url, build_api_url, parse_wiki_response, extract_error_message
|
||||
|
||||
|
||||
class WikiJSClient:
|
||||
"""Main client for interacting with Wiki.js API.
|
||||
|
||||
This client provides a high-level interface for all Wiki.js API operations
|
||||
including pages, users, groups, and system management. It handles authentication,
|
||||
error handling, and response parsing automatically.
|
||||
|
||||
Args:
|
||||
base_url: The base URL of your Wiki.js instance
|
||||
auth: Authentication (API key string or auth handler)
|
||||
timeout: Request timeout in seconds (default: 30)
|
||||
verify_ssl: Whether to verify SSL certificates (default: True)
|
||||
user_agent: Custom User-Agent header
|
||||
|
||||
Example:
|
||||
Basic usage with API key:
|
||||
|
||||
>>> client = WikiJSClient('https://wiki.example.com', auth='your-api-key')
|
||||
>>> # Will be available after endpoints are implemented:
|
||||
>>> # pages = client.pages.list()
|
||||
|
||||
Attributes:
|
||||
base_url: The normalized base URL
|
||||
timeout: Request timeout setting
|
||||
verify_ssl: SSL verification setting
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str,
|
||||
auth: Union[str, "AuthHandler"],
|
||||
timeout: int = 30,
|
||||
verify_ssl: bool = True,
|
||||
user_agent: Optional[str] = None,
|
||||
):
|
||||
# Validate and normalize base URL
|
||||
self.base_url = normalize_url(base_url)
|
||||
|
||||
# Store authentication
|
||||
if isinstance(auth, str):
|
||||
# Simple API key - will be handled by auth module later
|
||||
self._api_key = auth
|
||||
self._auth_handler = None
|
||||
else:
|
||||
# Auth handler (for future implementation)
|
||||
self._api_key = None
|
||||
self._auth_handler = auth
|
||||
|
||||
# Request configuration
|
||||
self.timeout = timeout
|
||||
self.verify_ssl = verify_ssl
|
||||
self.user_agent = user_agent or f"wikijs-python-sdk/0.1.0"
|
||||
|
||||
# Initialize HTTP session
|
||||
self._session = self._create_session()
|
||||
|
||||
# Endpoint handlers (will be initialized as we implement them)
|
||||
# self.pages = PagesEndpoint(self)
|
||||
# self.users = UsersEndpoint(self)
|
||||
# self.groups = GroupsEndpoint(self)
|
||||
|
||||
def _create_session(self) -> requests.Session:
|
||||
"""Create configured HTTP session with retry strategy.
|
||||
|
||||
Returns:
|
||||
Configured requests session
|
||||
"""
|
||||
session = requests.Session()
|
||||
|
||||
# Configure retry strategy
|
||||
retry_strategy = Retry(
|
||||
total=3,
|
||||
backoff_factor=1,
|
||||
status_forcelist=[429, 500, 502, 503, 504],
|
||||
allowed_methods=["HEAD", "GET", "OPTIONS", "POST", "PUT", "DELETE"],
|
||||
)
|
||||
|
||||
adapter = HTTPAdapter(max_retries=retry_strategy)
|
||||
session.mount("http://", adapter)
|
||||
session.mount("https://", adapter)
|
||||
|
||||
# Set default headers
|
||||
session.headers.update({
|
||||
"User-Agent": self.user_agent,
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
})
|
||||
|
||||
# Set authentication headers
|
||||
if self._api_key:
|
||||
session.headers["Authorization"] = f"Bearer {self._api_key}"
|
||||
elif self._auth_handler:
|
||||
auth_headers = self._auth_handler.get_headers()
|
||||
session.headers.update(auth_headers)
|
||||
|
||||
return session
|
||||
|
||||
def _request(
|
||||
self,
|
||||
method: str,
|
||||
endpoint: str,
|
||||
params: Optional[Dict[str, Any]] = None,
|
||||
json_data: Optional[Dict[str, Any]] = None,
|
||||
**kwargs
|
||||
) -> Dict[str, Any]:
|
||||
"""Make HTTP request to Wiki.js API.
|
||||
|
||||
Args:
|
||||
method: HTTP method (GET, POST, PUT, DELETE)
|
||||
endpoint: API endpoint path
|
||||
params: Query parameters
|
||||
json_data: JSON data for request body
|
||||
**kwargs: Additional request parameters
|
||||
|
||||
Returns:
|
||||
Parsed response data
|
||||
|
||||
Raises:
|
||||
AuthenticationError: If authentication fails
|
||||
APIError: If API returns an error
|
||||
ConnectionError: If connection fails
|
||||
TimeoutError: If request times out
|
||||
"""
|
||||
# Build full URL
|
||||
url = build_api_url(self.base_url, endpoint)
|
||||
|
||||
# Prepare request arguments
|
||||
request_kwargs = {
|
||||
"timeout": self.timeout,
|
||||
"verify": self.verify_ssl,
|
||||
"params": params,
|
||||
**kwargs
|
||||
}
|
||||
|
||||
# Add JSON data if provided
|
||||
if json_data is not None:
|
||||
request_kwargs["json"] = json_data
|
||||
|
||||
try:
|
||||
# Make request
|
||||
response = self._session.request(method, url, **request_kwargs)
|
||||
|
||||
# Handle response
|
||||
return self._handle_response(response)
|
||||
|
||||
except requests.exceptions.Timeout as e:
|
||||
raise TimeoutError(f"Request timed out after {self.timeout} seconds") from e
|
||||
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
raise ConnectionError(f"Failed to connect to {self.base_url}") from e
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
raise APIError(f"Request failed: {str(e)}") from e
|
||||
|
||||
def _handle_response(self, response: requests.Response) -> Dict[str, Any]:
|
||||
"""Handle HTTP response and extract data.
|
||||
|
||||
Args:
|
||||
response: HTTP response object
|
||||
|
||||
Returns:
|
||||
Parsed response data
|
||||
|
||||
Raises:
|
||||
AuthenticationError: If authentication fails (401)
|
||||
APIError: If API returns an error
|
||||
"""
|
||||
# Handle authentication errors
|
||||
if response.status_code == 401:
|
||||
raise AuthenticationError("Authentication failed - check your API key")
|
||||
|
||||
# Handle other HTTP errors
|
||||
if not response.ok:
|
||||
error_message = extract_error_message(response)
|
||||
raise create_api_error(
|
||||
response.status_code,
|
||||
error_message,
|
||||
response
|
||||
)
|
||||
|
||||
# Parse JSON response
|
||||
try:
|
||||
data = response.json()
|
||||
except json.JSONDecodeError as e:
|
||||
raise APIError(f"Invalid JSON response: {str(e)}") from e
|
||||
|
||||
# Parse Wiki.js specific response format
|
||||
return parse_wiki_response(data)
|
||||
|
||||
def test_connection(self) -> bool:
|
||||
"""Test connection to Wiki.js instance.
|
||||
|
||||
Returns:
|
||||
True if connection successful
|
||||
|
||||
Raises:
|
||||
ConfigurationError: If client is not properly configured
|
||||
ConnectionError: If cannot connect to server
|
||||
AuthenticationError: If authentication fails
|
||||
"""
|
||||
if not self.base_url:
|
||||
raise ConfigurationError("Base URL not configured")
|
||||
|
||||
if not self._api_key and not self._auth_handler:
|
||||
raise ConfigurationError("Authentication not configured")
|
||||
|
||||
try:
|
||||
# Try to hit a basic endpoint (will implement with actual endpoints)
|
||||
# For now, just test basic connectivity
|
||||
response = self._session.get(
|
||||
self.base_url,
|
||||
timeout=self.timeout,
|
||||
verify=self.verify_ssl
|
||||
)
|
||||
return True
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
raise TimeoutError(f"Connection test timed out after {self.timeout} seconds")
|
||||
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
raise ConnectionError(f"Cannot connect to {self.base_url}: {str(e)}")
|
||||
|
||||
except Exception as e:
|
||||
raise ConnectionError(f"Connection test failed: {str(e)}")
|
||||
|
||||
def __enter__(self):
|
||||
"""Context manager entry."""
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
"""Context manager exit - close session."""
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
"""Close the HTTP session and clean up resources."""
|
||||
if self._session:
|
||||
self._session.close()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""String representation of client."""
|
||||
return f"WikiJSClient(base_url='{self.base_url}')"
|
||||
22
wikijs/endpoints/__init__.py
Normal file
22
wikijs/endpoints/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""API endpoints module for wikijs-python-sdk.
|
||||
|
||||
This module will contain endpoint handlers for different
|
||||
Wiki.js API endpoints.
|
||||
|
||||
Future implementations:
|
||||
- Pages API (CRUD operations)
|
||||
- Users API (user management)
|
||||
- Groups API (group management)
|
||||
- Assets API (file management)
|
||||
- System API (system information)
|
||||
"""
|
||||
|
||||
# Placeholder for future endpoint implementations
|
||||
# from .base import BaseEndpoint
|
||||
# from .pages import PagesEndpoint
|
||||
# from .users import UsersEndpoint
|
||||
# from .groups import GroupsEndpoint
|
||||
|
||||
__all__ = [
|
||||
# Will be implemented in Task 1.4
|
||||
]
|
||||
109
wikijs/exceptions.py
Normal file
109
wikijs/exceptions.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""Exception hierarchy for wikijs-python-sdk."""
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
class WikiJSException(Exception):
|
||||
"""Base exception for all SDK errors."""
|
||||
|
||||
def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(message)
|
||||
self.message = message
|
||||
self.details = details or {}
|
||||
|
||||
|
||||
class ConfigurationError(WikiJSException):
|
||||
"""Raised when there's an issue with SDK configuration."""
|
||||
pass
|
||||
|
||||
|
||||
class AuthenticationError(WikiJSException):
|
||||
"""Raised when authentication fails."""
|
||||
pass
|
||||
|
||||
|
||||
class ValidationError(WikiJSException):
|
||||
"""Raised when input validation fails."""
|
||||
|
||||
def __init__(self, message: str, field: Optional[str] = None, value: Any = None):
|
||||
super().__init__(message)
|
||||
self.field = field
|
||||
self.value = value
|
||||
|
||||
|
||||
class APIError(WikiJSException):
|
||||
"""Base class for API-related errors."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
status_code: Optional[int] = None,
|
||||
response: Optional[Any] = None,
|
||||
details: Optional[Dict[str, Any]] = None
|
||||
):
|
||||
super().__init__(message, details)
|
||||
self.status_code = status_code
|
||||
self.response = response
|
||||
|
||||
|
||||
class ClientError(APIError):
|
||||
"""Raised for 4xx HTTP status codes (client errors)."""
|
||||
pass
|
||||
|
||||
|
||||
class ServerError(APIError):
|
||||
"""Raised for 5xx HTTP status codes (server errors)."""
|
||||
pass
|
||||
|
||||
|
||||
class NotFoundError(ClientError):
|
||||
"""Raised when a requested resource is not found (404)."""
|
||||
pass
|
||||
|
||||
|
||||
class PermissionError(ClientError):
|
||||
"""Raised when access is forbidden (403)."""
|
||||
pass
|
||||
|
||||
|
||||
class RateLimitError(ClientError):
|
||||
"""Raised when rate limit is exceeded (429)."""
|
||||
|
||||
def __init__(self, message: str, retry_after: Optional[int] = None, **kwargs):
|
||||
super().__init__(message, status_code=429, **kwargs)
|
||||
self.retry_after = retry_after
|
||||
|
||||
|
||||
class ConnectionError(WikiJSException):
|
||||
"""Raised when there's a connection issue."""
|
||||
pass
|
||||
|
||||
|
||||
class TimeoutError(WikiJSException):
|
||||
"""Raised when a request times out."""
|
||||
pass
|
||||
|
||||
|
||||
def create_api_error(status_code: int, message: str, response: Any = None) -> APIError:
|
||||
"""Create appropriate API error based on status code.
|
||||
|
||||
Args:
|
||||
status_code: HTTP status code
|
||||
message: Error message
|
||||
response: Raw response object
|
||||
|
||||
Returns:
|
||||
Appropriate APIError subclass instance
|
||||
"""
|
||||
if status_code == 404:
|
||||
return NotFoundError(message, status_code=status_code, response=response)
|
||||
elif status_code == 403:
|
||||
return PermissionError(message, status_code=status_code, response=response)
|
||||
elif status_code == 429:
|
||||
return RateLimitError(message, status_code=status_code, response=response)
|
||||
elif 400 <= status_code < 500:
|
||||
return ClientError(message, status_code=status_code, response=response)
|
||||
elif 500 <= status_code < 600:
|
||||
return ServerError(message, status_code=status_code, response=response)
|
||||
else:
|
||||
return APIError(message, status_code=status_code, response=response)
|
||||
11
wikijs/models/__init__.py
Normal file
11
wikijs/models/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""Data models for wikijs-python-sdk."""
|
||||
|
||||
from .base import BaseModel
|
||||
from .page import Page, PageCreate, PageUpdate
|
||||
|
||||
__all__ = [
|
||||
"BaseModel",
|
||||
"Page",
|
||||
"PageCreate",
|
||||
"PageUpdate",
|
||||
]
|
||||
90
wikijs/models/base.py
Normal file
90
wikijs/models/base.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""Base model functionality for wikijs-python-sdk."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from pydantic import BaseModel as PydanticBaseModel, ConfigDict
|
||||
|
||||
|
||||
class BaseModel(PydanticBaseModel):
|
||||
"""Base model with common functionality for all data models.
|
||||
|
||||
Provides:
|
||||
- Automatic validation via Pydantic
|
||||
- JSON serialization/deserialization
|
||||
- Field aliases for API compatibility
|
||||
- Consistent datetime handling
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
# Allow population by field name or alias
|
||||
populate_by_name=True,
|
||||
# Validate assignment to attributes
|
||||
validate_assignment=True,
|
||||
# Use enum values instead of names
|
||||
use_enum_values=True,
|
||||
# Allow extra fields for forward compatibility
|
||||
extra="ignore",
|
||||
# Serialize datetime as ISO format
|
||||
json_encoders={
|
||||
datetime: lambda v: v.isoformat() if v else None
|
||||
}
|
||||
)
|
||||
|
||||
def to_dict(self, exclude_none: bool = True) -> Dict[str, Any]:
|
||||
"""Convert model to dictionary.
|
||||
|
||||
Args:
|
||||
exclude_none: Whether to exclude None values
|
||||
|
||||
Returns:
|
||||
Dictionary representation of the model
|
||||
"""
|
||||
return self.model_dump(exclude_none=exclude_none, by_alias=True)
|
||||
|
||||
def to_json(self, exclude_none: bool = True) -> str:
|
||||
"""Convert model to JSON string.
|
||||
|
||||
Args:
|
||||
exclude_none: Whether to exclude None values
|
||||
|
||||
Returns:
|
||||
JSON string representation of the model
|
||||
"""
|
||||
return self.model_dump_json(exclude_none=exclude_none, by_alias=True)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "BaseModel":
|
||||
"""Create model instance from dictionary.
|
||||
|
||||
Args:
|
||||
data: Dictionary data
|
||||
|
||||
Returns:
|
||||
Model instance
|
||||
"""
|
||||
return cls(**data)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json_str: str) -> "BaseModel":
|
||||
"""Create model instance from JSON string.
|
||||
|
||||
Args:
|
||||
json_str: JSON string
|
||||
|
||||
Returns:
|
||||
Model instance
|
||||
"""
|
||||
return cls.model_validate_json(json_str)
|
||||
|
||||
|
||||
class TimestampedModel(BaseModel):
|
||||
"""Base model with timestamp fields."""
|
||||
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
@property
|
||||
def is_new(self) -> bool:
|
||||
"""Check if this is a new (unsaved) model."""
|
||||
return self.created_at is None
|
||||
188
wikijs/models/page.py
Normal file
188
wikijs/models/page.py
Normal file
@@ -0,0 +1,188 @@
|
||||
"""Page-related data models for wikijs-python-sdk."""
|
||||
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import Field, validator
|
||||
|
||||
from .base import BaseModel, TimestampedModel
|
||||
|
||||
|
||||
class Page(TimestampedModel):
|
||||
"""Represents a Wiki.js page.
|
||||
|
||||
This model contains all the data for a wiki page including
|
||||
content, metadata, and computed properties.
|
||||
"""
|
||||
|
||||
id: int = Field(..., description="Unique page identifier")
|
||||
title: str = Field(..., description="Page title")
|
||||
path: str = Field(..., description="Page path/slug")
|
||||
content: str = Field(..., description="Page content")
|
||||
|
||||
# Optional fields that may be present
|
||||
description: Optional[str] = Field(None, description="Page description")
|
||||
is_published: bool = Field(True, description="Whether page is published")
|
||||
is_private: bool = Field(False, description="Whether page is private")
|
||||
|
||||
# Metadata
|
||||
tags: List[str] = Field(default_factory=list, description="Page tags")
|
||||
locale: str = Field("en", description="Page locale")
|
||||
|
||||
# Author information
|
||||
author_id: Optional[int] = Field(None, alias="authorId")
|
||||
author_name: Optional[str] = Field(None, alias="authorName")
|
||||
author_email: Optional[str] = Field(None, alias="authorEmail")
|
||||
|
||||
# Editor information
|
||||
editor: Optional[str] = Field(None, description="Editor used")
|
||||
|
||||
@validator("path")
|
||||
def validate_path(cls, v):
|
||||
"""Validate page path format."""
|
||||
if not v:
|
||||
raise ValueError("Path cannot be empty")
|
||||
|
||||
# Remove leading/trailing slashes and normalize
|
||||
v = v.strip("/")
|
||||
|
||||
# Check for valid characters (letters, numbers, hyphens, underscores, slashes)
|
||||
if not re.match(r"^[a-zA-Z0-9\-_/]+$", v):
|
||||
raise ValueError("Path contains invalid characters")
|
||||
|
||||
return v
|
||||
|
||||
@validator("title")
|
||||
def validate_title(cls, v):
|
||||
"""Validate page title."""
|
||||
if not v or not v.strip():
|
||||
raise ValueError("Title cannot be empty")
|
||||
|
||||
# Limit title length
|
||||
if len(v) > 255:
|
||||
raise ValueError("Title cannot exceed 255 characters")
|
||||
|
||||
return v.strip()
|
||||
|
||||
@property
|
||||
def word_count(self) -> int:
|
||||
"""Calculate word count from content."""
|
||||
if not self.content:
|
||||
return 0
|
||||
|
||||
# Simple word count - split on whitespace
|
||||
words = self.content.split()
|
||||
return len(words)
|
||||
|
||||
@property
|
||||
def reading_time(self) -> int:
|
||||
"""Estimate reading time in minutes (assuming 200 words per minute)."""
|
||||
return max(1, self.word_count // 200)
|
||||
|
||||
@property
|
||||
def url_path(self) -> str:
|
||||
"""Get the full URL path for this page."""
|
||||
return f"/{self.path}"
|
||||
|
||||
def extract_headings(self) -> List[str]:
|
||||
"""Extract markdown headings from content.
|
||||
|
||||
Returns:
|
||||
List of heading text (without # markers)
|
||||
"""
|
||||
if not self.content:
|
||||
return []
|
||||
|
||||
headings = []
|
||||
for line in self.content.split("\n"):
|
||||
line = line.strip()
|
||||
if line.startswith("#"):
|
||||
# Remove # markers and whitespace
|
||||
heading = re.sub(r"^#+\s*", "", line).strip()
|
||||
if heading:
|
||||
headings.append(heading)
|
||||
|
||||
return headings
|
||||
|
||||
def has_tag(self, tag: str) -> bool:
|
||||
"""Check if page has a specific tag.
|
||||
|
||||
Args:
|
||||
tag: Tag to check for
|
||||
|
||||
Returns:
|
||||
True if page has the tag
|
||||
"""
|
||||
return tag.lower() in [t.lower() for t in self.tags]
|
||||
|
||||
|
||||
class PageCreate(BaseModel):
|
||||
"""Data model for creating a new page."""
|
||||
|
||||
title: str = Field(..., description="Page title")
|
||||
path: str = Field(..., description="Page path/slug")
|
||||
content: str = Field(..., description="Page content")
|
||||
|
||||
# Optional fields
|
||||
description: Optional[str] = Field(None, description="Page description")
|
||||
is_published: bool = Field(True, description="Whether to publish immediately")
|
||||
is_private: bool = Field(False, description="Whether page should be private")
|
||||
|
||||
tags: List[str] = Field(default_factory=list, description="Page tags")
|
||||
locale: str = Field("en", description="Page locale")
|
||||
editor: str = Field("markdown", description="Editor to use")
|
||||
|
||||
@validator("path")
|
||||
def validate_path(cls, v):
|
||||
"""Validate page path format."""
|
||||
if not v:
|
||||
raise ValueError("Path cannot be empty")
|
||||
|
||||
# Remove leading/trailing slashes and normalize
|
||||
v = v.strip("/")
|
||||
|
||||
# Check for valid characters
|
||||
if not re.match(r"^[a-zA-Z0-9\-_/]+$", v):
|
||||
raise ValueError("Path contains invalid characters")
|
||||
|
||||
return v
|
||||
|
||||
@validator("title")
|
||||
def validate_title(cls, v):
|
||||
"""Validate page title."""
|
||||
if not v or not v.strip():
|
||||
raise ValueError("Title cannot be empty")
|
||||
|
||||
if len(v) > 255:
|
||||
raise ValueError("Title cannot exceed 255 characters")
|
||||
|
||||
return v.strip()
|
||||
|
||||
|
||||
class PageUpdate(BaseModel):
|
||||
"""Data model for updating an existing page."""
|
||||
|
||||
# All fields optional for partial updates
|
||||
title: Optional[str] = Field(None, description="Page title")
|
||||
content: Optional[str] = Field(None, description="Page content")
|
||||
description: Optional[str] = Field(None, description="Page description")
|
||||
|
||||
is_published: Optional[bool] = Field(None, description="Publication status")
|
||||
is_private: Optional[bool] = Field(None, description="Privacy status")
|
||||
|
||||
tags: Optional[List[str]] = Field(None, description="Page tags")
|
||||
|
||||
@validator("title")
|
||||
def validate_title(cls, v):
|
||||
"""Validate page title if provided."""
|
||||
if v is not None:
|
||||
if not v.strip():
|
||||
raise ValueError("Title cannot be empty")
|
||||
|
||||
if len(v) > 255:
|
||||
raise ValueError("Title cannot exceed 255 characters")
|
||||
|
||||
return v.strip()
|
||||
|
||||
return v
|
||||
0
wikijs/py.typed
Normal file
0
wikijs/py.typed
Normal file
15
wikijs/utils/__init__.py
Normal file
15
wikijs/utils/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""Utility functions for wikijs-python-sdk."""
|
||||
|
||||
from .helpers import (
|
||||
normalize_url,
|
||||
sanitize_path,
|
||||
validate_url,
|
||||
parse_wiki_response,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"normalize_url",
|
||||
"sanitize_path",
|
||||
"validate_url",
|
||||
"parse_wiki_response",
|
||||
]
|
||||
209
wikijs/utils/helpers.py
Normal file
209
wikijs/utils/helpers.py
Normal file
@@ -0,0 +1,209 @@
|
||||
"""Helper utilities for wikijs-python-sdk."""
|
||||
|
||||
import re
|
||||
from typing import Any, Dict, Optional
|
||||
from urllib.parse import urljoin, urlparse
|
||||
|
||||
from ..exceptions import APIError, ValidationError
|
||||
|
||||
|
||||
def normalize_url(base_url: str) -> str:
|
||||
"""Normalize a base URL for API usage.
|
||||
|
||||
Args:
|
||||
base_url: Base URL to normalize
|
||||
|
||||
Returns:
|
||||
Normalized URL without trailing slash
|
||||
|
||||
Raises:
|
||||
ValidationError: If URL is invalid
|
||||
"""
|
||||
if not base_url:
|
||||
raise ValidationError("Base URL cannot be empty")
|
||||
|
||||
# Add https:// if no scheme provided
|
||||
if not base_url.startswith(("http://", "https://")):
|
||||
base_url = f"https://{base_url}"
|
||||
|
||||
# Validate URL format
|
||||
if not validate_url(base_url):
|
||||
raise ValidationError(f"Invalid URL format: {base_url}")
|
||||
|
||||
# Remove trailing slash
|
||||
return base_url.rstrip("/")
|
||||
|
||||
|
||||
def validate_url(url: str) -> bool:
|
||||
"""Validate URL format.
|
||||
|
||||
Args:
|
||||
url: URL to validate
|
||||
|
||||
Returns:
|
||||
True if URL is valid
|
||||
"""
|
||||
try:
|
||||
result = urlparse(url)
|
||||
return all([result.scheme, result.netloc])
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def sanitize_path(path: str) -> str:
|
||||
"""Sanitize a wiki page path.
|
||||
|
||||
Args:
|
||||
path: Path to sanitize
|
||||
|
||||
Returns:
|
||||
Sanitized path
|
||||
|
||||
Raises:
|
||||
ValidationError: If path is invalid
|
||||
"""
|
||||
if not path:
|
||||
raise ValidationError("Path cannot be empty")
|
||||
|
||||
# Remove leading/trailing slashes and whitespace
|
||||
path = path.strip().strip("/")
|
||||
|
||||
# Replace spaces with hyphens
|
||||
path = re.sub(r"\s+", "-", path)
|
||||
|
||||
# Remove invalid characters, keep only alphanumeric, hyphens, underscores, slashes
|
||||
path = re.sub(r"[^a-zA-Z0-9\-_/]", "", path)
|
||||
|
||||
# Remove multiple consecutive hyphens or slashes
|
||||
path = re.sub(r"[-/]+", lambda m: m.group(0)[0], path)
|
||||
|
||||
if not path:
|
||||
raise ValidationError("Path contains no valid characters")
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def build_api_url(base_url: str, endpoint: str) -> str:
|
||||
"""Build full API URL from base URL and endpoint.
|
||||
|
||||
Args:
|
||||
base_url: Base URL (already normalized)
|
||||
endpoint: API endpoint path
|
||||
|
||||
Returns:
|
||||
Full API URL
|
||||
"""
|
||||
# Ensure endpoint starts with /
|
||||
if not endpoint.startswith("/"):
|
||||
endpoint = f"/{endpoint}"
|
||||
|
||||
# Wiki.js API is typically at /graphql, but we'll use REST-style for now
|
||||
api_base = f"{base_url}/api"
|
||||
|
||||
return urljoin(api_base, endpoint.lstrip("/"))
|
||||
|
||||
|
||||
def parse_wiki_response(response_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Parse Wiki.js API response data.
|
||||
|
||||
Args:
|
||||
response_data: Raw response data from API
|
||||
|
||||
Returns:
|
||||
Parsed response data
|
||||
|
||||
Raises:
|
||||
APIError: If response indicates an error
|
||||
"""
|
||||
if not isinstance(response_data, dict):
|
||||
return response_data
|
||||
|
||||
# Check for error indicators
|
||||
if "error" in response_data:
|
||||
error_info = response_data["error"]
|
||||
if isinstance(error_info, dict):
|
||||
message = error_info.get("message", "Unknown API error")
|
||||
code = error_info.get("code")
|
||||
else:
|
||||
message = str(error_info)
|
||||
code = None
|
||||
|
||||
raise APIError(f"API Error: {message}", details={"code": code})
|
||||
|
||||
# Handle GraphQL-style errors
|
||||
if "errors" in response_data:
|
||||
errors = response_data["errors"]
|
||||
if errors:
|
||||
first_error = errors[0] if isinstance(errors, list) else errors
|
||||
message = first_error.get("message", "GraphQL error") if isinstance(first_error, dict) else str(first_error)
|
||||
raise APIError(f"GraphQL Error: {message}", details={"errors": errors})
|
||||
|
||||
return response_data
|
||||
|
||||
|
||||
def extract_error_message(response: Any) -> str:
|
||||
"""Extract error message from response.
|
||||
|
||||
Args:
|
||||
response: Response object or data
|
||||
|
||||
Returns:
|
||||
Error message string
|
||||
"""
|
||||
if hasattr(response, "json"):
|
||||
try:
|
||||
data = response.json()
|
||||
if isinstance(data, dict):
|
||||
# Try common error message fields
|
||||
for field in ["message", "error", "detail", "msg"]:
|
||||
if field in data:
|
||||
return str(data[field])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if hasattr(response, "text"):
|
||||
return response.text[:200] + "..." if len(response.text) > 200 else response.text
|
||||
|
||||
return str(response)
|
||||
|
||||
|
||||
def chunk_list(items: list, chunk_size: int) -> list:
|
||||
"""Split list into chunks of specified size.
|
||||
|
||||
Args:
|
||||
items: List to chunk
|
||||
chunk_size: Size of each chunk
|
||||
|
||||
Returns:
|
||||
List of chunks
|
||||
"""
|
||||
if chunk_size <= 0:
|
||||
raise ValueError("Chunk size must be positive")
|
||||
|
||||
return [items[i:i + chunk_size] for i in range(0, len(items), chunk_size)]
|
||||
|
||||
|
||||
def safe_get(data: Dict[str, Any], key: str, default: Any = None) -> Any:
|
||||
"""Safely get value from dictionary with dot notation support.
|
||||
|
||||
Args:
|
||||
data: Dictionary to get value from
|
||||
key: Key (supports dot notation like "user.name")
|
||||
default: Default value if key not found
|
||||
|
||||
Returns:
|
||||
Value or default
|
||||
"""
|
||||
if "." not in key:
|
||||
return data.get(key, default)
|
||||
|
||||
keys = key.split(".")
|
||||
current = data
|
||||
|
||||
for k in keys:
|
||||
if isinstance(current, dict) and k in current:
|
||||
current = current[k]
|
||||
else:
|
||||
return default
|
||||
|
||||
return current
|
||||
7
wikijs/version.py
Normal file
7
wikijs/version.py
Normal file
@@ -0,0 +1,7 @@
|
||||
"""Version information for wikijs-python-sdk."""
|
||||
|
||||
__version__ = "0.1.0"
|
||||
__version_info__ = (0, 1, 0)
|
||||
|
||||
# Version history
|
||||
# 0.1.0 - MVP Release: Basic Wiki.js integration with Pages API
|
||||
Reference in New Issue
Block a user