Skip to content

Commit 3cebcee

Browse files
author
Moderyo
committed
Initial release: moderyo v2.0.7
- Sync client (Moderyo) and async client (AsyncModeryo) - Full Pydantic v2 models with 27-category support - Policy decision, detected phrases, long-text analysis - Automatic retry with exponential backoff - httpx-based HTTP client, Python 3.8+ - CI/CD workflows for GitHub Actions
0 parents  commit 3cebcee

File tree

13 files changed

+2087
-0
lines changed

13 files changed

+2087
-0
lines changed

.github/workflows/ci.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install poetry
28+
poetry install
29+
30+
- name: Lint with ruff
31+
run: poetry run ruff check .
32+
33+
- name: Type check with mypy
34+
run: poetry run mypy moderyo/
35+
36+
- name: Run tests
37+
run: poetry run pytest -v
38+
env:
39+
MODERYO_API_KEY: ${{ secrets.MODERYO_API_KEY }}

.github/workflows/pypi-publish.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
publish:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
id-token: write
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.12"
20+
21+
- name: Install build tools
22+
run: pip install build twine
23+
24+
- name: Build package
25+
run: python -m build
26+
27+
- name: Publish to PyPI
28+
run: twine upload dist/*
29+
env:
30+
TWINE_USERNAME: __token__
31+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}

.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Byte-compiled / optimized
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
7+
# Distribution / packaging
8+
dist/
9+
build/
10+
*.egg-info/
11+
*.egg
12+
13+
# Virtual environments
14+
.venv/
15+
venv/
16+
env/
17+
18+
# IDE
19+
.vscode/
20+
.idea/
21+
*.swp
22+
*.swo
23+
24+
# OS
25+
.DS_Store
26+
Thumbs.db
27+
28+
# Environment
29+
.env
30+
.env.*
31+
32+
# Testing
33+
.pytest_cache/
34+
.coverage
35+
htmlcov/
36+
.mypy_cache/
37+
.ruff_cache/

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Changelog
2+
3+
All notable changes to the Moderyo Python SDK will be documented in this file.
4+
5+
## [2.0.7] - 2026-02-17
6+
7+
### Added
8+
- Initial public release on PyPI
9+
- Synchronous client (`Moderyo`) and async client (`AsyncModeryo`)
10+
- Full Pydantic v2 models with 27-category support
11+
- Policy decision support (ALLOW / FLAG / BLOCK)
12+
- Score breakdown: toxicity, hate, harassment, scam, violence, fraud
13+
- Category detection (30+ categories including child safety, extremism)
14+
- Detected phrases with labels
15+
- Batch processing support (`moderate_batch`)
16+
- Long-text analysis with sentence-level scoring
17+
- Automatic retry with exponential backoff
18+
- Rate limiting handling
19+
- Configurable options: mode, risk level, player_id
20+
- Content options: skip_profanity, skip_threat, skip_masked_word, long_text_mode
21+
- Comprehensive exception hierarchy (AuthenticationError, RateLimitError, etc.)
22+
23+
### Technical
24+
- Python 3.8+ support
25+
- httpx for HTTP client
26+
- Pydantic v2 for data models
27+
- Typed (PEP 561 compatible)
28+
- Zero extra dependencies beyond httpx and pydantic

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025-2026 Moderyo
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Moderyo Python SDK
2+
3+
Official Python client library for the Moderyo Content Moderation API.
4+
5+
[![PyPI version](https://badge.fury.io/py/moderyo.svg)](https://badge.fury.io/py/moderyo)
6+
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
7+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8+
9+
## Installation
10+
11+
```bash
12+
pip install moderyo
13+
```
14+
15+
Or with Poetry:
16+
17+
```bash
18+
poetry add moderyo
19+
```
20+
21+
## Quick Start
22+
23+
```python
24+
from moderyo import Moderyo
25+
26+
# Initialize client
27+
client = Moderyo(api_key="sk_live_xxxxx")
28+
29+
# Moderate content
30+
result = client.moderate("Hello, this is a test message")
31+
32+
print(result.flagged) # True/False
33+
print(result.action) # 'allow', 'flag', 'block'
34+
print(result.categories) # Category breakdown
35+
print(result.explanation) # Human-readable explanation
36+
```
37+
38+
## Async Support
39+
40+
```python
41+
import asyncio
42+
from moderyo import AsyncModeryo
43+
44+
async def main():
45+
client = AsyncModeryo(api_key="sk_live_xxxxx")
46+
47+
result = await client.moderate("Check this content")
48+
print(result.action)
49+
50+
asyncio.run(main())
51+
```
52+
53+
## Batch Processing
54+
55+
```python
56+
# Moderate multiple items efficiently
57+
results = client.moderate_batch([
58+
"First message",
59+
"Second message",
60+
"Third message"
61+
])
62+
63+
for result in results:
64+
print(f"{result.id}: {result.action}")
65+
```
66+
67+
## Configuration Options
68+
69+
```python
70+
client = Moderyo(
71+
api_key="sk_live_xxxxx",
72+
73+
# Optional settings
74+
base_url="https://api.moderyo.com", # Custom API endpoint
75+
timeout=30, # Request timeout in seconds
76+
max_retries=3, # Retry count on failure
77+
78+
# Callbacks
79+
on_error=lambda e: print(f"Error: {e}"),
80+
on_rate_limit=lambda info: print(f"Rate limited: {info}")
81+
)
82+
```
83+
84+
## Error Handling
85+
86+
```python
87+
from moderyo import Moderyo
88+
from moderyo.exceptions import (
89+
ModeryoError,
90+
AuthenticationError,
91+
RateLimitError,
92+
ValidationError,
93+
APIError
94+
)
95+
96+
client = Moderyo(api_key="sk_live_xxxxx")
97+
98+
try:
99+
result = client.moderate("Some content")
100+
except AuthenticationError:
101+
print("Invalid API key")
102+
except RateLimitError as e:
103+
print(f"Rate limited. Retry after {e.retry_after} seconds")
104+
except ValidationError as e:
105+
print(f"Invalid request: {e.message}")
106+
except APIError as e:
107+
print(f"API error: {e.status_code} - {e.message}")
108+
except ModeryoError as e:
109+
print(f"General error: {e}")
110+
```
111+
112+
## Context & Metadata
113+
114+
```python
115+
result = client.moderate(
116+
content="User message here",
117+
context={
118+
"user_id": "user_123",
119+
"content_type": "chat",
120+
"platform": "mobile",
121+
"language": "en"
122+
}
123+
)
124+
```
125+
126+
## Response Structure
127+
128+
```python
129+
result = client.moderate("Some content")
130+
131+
# Core fields
132+
result.id # Unique request ID
133+
result.flagged # bool - Any category triggered?
134+
result.action # 'allow' | 'flag' | 'block'
135+
136+
# Detailed scores
137+
result.categories # Dict of category -> bool
138+
result.scores # Dict of category -> float (0-1)
139+
140+
# Explanation (Explainability 2.0)
141+
result.explanation # Human-readable explanation
142+
143+
# Policy info
144+
result.policy_decision # Policy engine result
145+
result.safety_score # 0-100 safety score
146+
```
147+
148+
## Framework Integrations
149+
150+
### FastAPI
151+
152+
```python
153+
from fastapi import FastAPI, HTTPException, Depends
154+
from moderyo.integrations.fastapi import ModeryoDep
155+
156+
app = FastAPI()
157+
158+
@app.post("/messages")
159+
async def create_message(
160+
content: str,
161+
moderation = Depends(ModeryoDep(api_key="sk_live_xxx"))
162+
):
163+
result = await moderation.check(content)
164+
165+
if result.action == "block":
166+
raise HTTPException(400, detail=result.explanation)
167+
168+
return {"status": "ok", "flagged": result.flagged}
169+
```
170+
171+
### Django
172+
173+
```python
174+
from moderyo.integrations.django import moderate_content
175+
176+
@moderate_content(field='message', on_block='reject')
177+
def create_message(request):
178+
# Only reached if content is allowed or flagged
179+
Message.objects.create(content=request.POST['message'])
180+
return JsonResponse({'status': 'ok'})
181+
```
182+
183+
### Flask
184+
185+
```python
186+
from flask import Flask, request, jsonify
187+
from moderyo.integrations.flask import require_moderation
188+
189+
app = Flask(__name__)
190+
191+
@app.route('/messages', methods=['POST'])
192+
@require_moderation(api_key="sk_live_xxx", field='content')
193+
def create_message():
194+
return jsonify({'status': 'ok'})
195+
```
196+
197+
## Development
198+
199+
```bash
200+
# Clone repository
201+
git clone https://github.com/moderyo/moderyo-python.git
202+
cd moderyo-python
203+
204+
# Install dependencies
205+
poetry install
206+
207+
# Run tests
208+
poetry run pytest
209+
210+
# Run linting
211+
poetry run ruff check .
212+
poetry run mypy moderyo
213+
```
214+
215+
## Examples
216+
217+
See the [playground-examples](https://github.com/moderyo/playground-examples/tree/main/python) repository for a complete working FastAPI server example.
218+
219+
## License
220+
221+
MIT License - see [LICENSE](LICENSE) for details.

0 commit comments

Comments
 (0)