🔑 Simple, Pythonic license management for AI tools and indie projects
Project description
Licenzy provides a clean, minimal API for adding license validation to your Python projects. Perfect for independent developers and small teams building AI tools who need secure but lightweight licensing.
✨ Features
- 🎨 @licensed decorator - Protect functions with a simple, elegant decorator
- 🔍 Simple API -
check_license()for manual validation - 📁 Flexible Storage - Environment variables, home directory, or project files
- 🔒 HMAC Security - Cryptographically secure license validation
- 🖥️ CLI Tools - Easy license management from command line
- 🐍 Zero Dependencies - Core functionality works standalone (Click only for CLI)
- 🚀 Startup-Friendly - Designed for indie developers and small teams
🚀 Quick Start
Installation
pip install licenzy
Basic Usage
from licenzy import licensed, check_license
# Protect premium features with a decorator
@licensed
def premium_ai_model():
return "🤖 Running advanced AI model!"
# Manual license checking
if check_license():
print("✅ All features unlocked!")
else:
print("❌ License required for premium features")
Activate a License
# Via CLI
licenzy activate your-license-key-here
# Via environment variable
export LICENZY_LICENSE_KEY=your-license-key-here
# Check status
licenzy status
📋 API Reference
Core Functions
@licensed
The main decorator for protecting functions that require a valid license.
from licenzy import licensed
@licensed
def premium_feature():
return "This requires a license!"
# With custom error message
@licensed(message="Pro plan required")
def pro_feature():
return "Pro-only functionality"
check_license()
Simple function to check if a license is valid.
from licenzy import check_license
if check_license():
# License is valid
enable_premium_features()
else:
# No valid license
show_upgrade_prompt()
Decorator Aliases
Licenzy provides friendly aliases for different use cases:
from licenzy import unlock, require_key
@unlock # Same as @licensed
def feature_one():
return "Unlocked!"
@require_key # Same as @licensed
def feature_two():
return "Key required!"
Function Aliases
from licenzy import access_granted
# Same as check_license() but more expressive
if access_granted():
print("Welcome to premium features!")
🖥️ CLI Commands
Activate License
licenzy activate your-license-key
Check Status
licenzy status
Quick Validation
licenzy check # Returns exit code 0 if valid, 1 if invalid
Deactivate License
licenzy deactivate
Show Help
licenzy info # Shows integration examples and usage
⚙️ Configuration
License Storage Locations
Licenzy checks for licenses in this order:
- Environment Variable:
LICENZY_LICENSE_KEY - User Directory:
~/.licenzy/license.key - Project Directory:
.licenzy_license
Development Mode
Bypass license checks during development:
export LICENZY_DEV_MODE=true
License Key Format
License keys follow this format:
user_id:plan:expires_timestamp:signature
Example:
john123:pro:1735689600:a1b2c3d4e5f6
🔧 Integration Examples
FastAPI Integration
from fastapi import FastAPI, HTTPException
from licenzy import licensed, LicenseError
app = FastAPI()
@app.get("/premium-endpoint")
@licensed
def premium_endpoint():
return {"message": "Premium feature accessed!"}
# Global error handler
@app.exception_handler(LicenseError)
async def license_error_handler(request, exc):
raise HTTPException(status_code=402, detail=str(exc))
Flask Integration
from flask import Flask, jsonify
from licenzy import licensed, LicenseError
app = Flask(__name__)
@app.route('/premium')
@licensed
def premium_route():
return jsonify({"message": "Premium content!"})
@app.errorhandler(LicenseError)
def handle_license_error(e):
return jsonify({"error": str(e)}), 402
Class Method Protection
from licenzy import licensed
class AIService:
@licensed
def premium_analysis(self, data):
return "Advanced analysis results"
@licensed(message="Enterprise plan required")
def enterprise_feature(self):
return "Enterprise-only functionality"
🧪 Testing
Licenzy makes testing easy with development mode:
import os
from licenzy import check_license
def test_premium_feature():
# Enable dev mode for testing
os.environ['LICENZY_DEV_MODE'] = 'true'
assert check_license() == True
# Your test code here
🏗️ Building and Development
Local Development Setup
git clone https://github.com/yourusername/licenzy
cd licenzy
pip install -e ".[dev]"
Running Tests
pytest tests/ -v
Code Formatting
black licenzy/
Type Checking
mypy licenzy/
📄 License
MIT License - see LICENSE file for details.
🤝 Contributing
Contributions welcome! Please read our contributing guidelines and submit pull requests to our GitHub repository.
🆘 Support
- 📖 Documentation: licenzy.readthedocs.io
- 🐛 Bug Reports: GitHub Issues
- 💬 Discussions: GitHub Discussions
Built with ❤️ for the indie developer community. Perfect for AI tools, SaaS products, and any Python project that needs simple, secure licensing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file licenzy-1.0.0.tar.gz.
File metadata
- Download URL: licenzy-1.0.0.tar.gz
- Upload date:
- Size: 87.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
504e710649692ae57282371b91d0567ab501520dd2777b5d305ed0d398586bc5
|
|
| MD5 |
f1b8d4de53fc6e8dd9602a028fa3a0f6
|
|
| BLAKE2b-256 |
bab19ce901cbdb152715ce1e708c5e1cfe46b82bae1f6ef3009862b2d2715f6d
|
File details
Details for the file licenzy-1.0.0-py3-none-any.whl.
File metadata
- Download URL: licenzy-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0cfc6f762fceba6e84627c5d3e7973f6a1400a3cb9a36e5f3762d27be2ca370
|
|
| MD5 |
15dbcbe9aa949b0d7d8279c99b195fa8
|
|
| BLAKE2b-256 |
2c68b0b05d6623ef548baba68418abc3f018925e27bd5cf38c1d72bd6a92e44b
|