A modern, production-ready CRUD REST API built with Python 3.12 and FastAPI for managing Widget resources.
- Full CRUD Operations - Create, Read, Update, Delete widgets
- FastAPI Framework - High-performance, modern Python web framework
- Async Database Operations - SQLAlchemy 2.0 with async SQLite
- Data Validation - Pydantic models for request/response validation
- Automatic Documentation - OpenAPI/Swagger docs generated automatically
- Database Migrations - Alembic for schema versioning
- Comprehensive Testing - Unit and integration tests with high coverage
- Code Quality Tools - Linting, formatting, security analysis
- Type Safety - Full type annotations with mypy checking
- Python 3.12+
- Poetry (for dependency management) - Note: Poetry needs to be installed globally first
NOTE: Poetry is recommended, but not required. All commands in this README include non-poetry alternatives.
Poetry is a modern dependency management tool for Python. Unlike traditional packages, Poetry should be installed globally on your system (not as a project dependency) to bootstrap the project setup. See installation instructions below.
Modern Poetry Usage: Since Poetry 2.0, poetry shell was moved to a plugin. The current best practices are:
poetry run <command>- For individual commands (most reliable)poetry env activate- Outputs activation command for shell integrationpoetry-plugin-shell- Optional plugin to restorepoetry shellcommand
The poetry run approach is preferred as it's more reliable and works consistently across different environments and CI/CD systems.
git clone <repository-url>
cd aweberOption A: Official installer (recommended)
curl -sSL https://install.python-poetry.org | python3 -Option B: Via pip (global installation)
pip install poetryOption C: Via pipx (isolated installation)
pipx install poetryFor more installation options, see: https://python-poetry.org/docs/#installation
poetry installPoetry 2.0+ Options:
# Option 1: Use poetry run for individual commands (recommended)
poetry run python --version
poetry run pytest
# Option 2: Get activation command (Poetry 2.0+)
poetry env activate
# This outputs: source /path/to/venv/bin/activate
# You can use it like: $(poetry env activate)
# Option 3: Install the shell plugin (if you prefer the old poetry shell)
poetry self add poetry-plugin-shell
poetry shellNote: Since Poetry 2.0, poetry shell was removed from core and is now a plugin. The recommended approaches are poetry run for individual commands or poetry env activate to get the activation command.
pre-commit installalembic upgrade headIf you prefer not to use Poetry, you can use Python's built-in venv and pip:
# Create virtual environment
python3 -m venv aweberenv
# Activate virtual environment
source aweberenv/bin/activate # On Windows: aweberenv\Scripts\activate
# Install core dependencies
pip install -r requirements.txt
# Install development dependencies (for testing, linting, etc.)
pip install -r requirements-dev.txt
# Set up pre-commit hooks
pre-commit install
# Run database migrations
alembic upgrade headNote: The Poetry approach is recommended as it provides better dependency resolution and lock file management.
# Activate virtual environment first (if not already activated)
poetry shell
# Default (secure localhost binding)
poetry run python src/main.py
# Or with uvicorn directly
poetry run uvicorn src.app.main:app --reload
# For network access (Docker, external devices)
HOST=0.0.0.0 PORT=8000 poetry run python src/main.py# Assuming active virtual env
python src/main.py
# Or direct uvicorn
python -m uvicorn src.app.main:app --reloadThe API will be available at:
- Application: http://localhost:8000
- Interactive Documentation: http://localhost:8000/docs
- ReDoc Documentation: http://localhost:8000/redoc
| Variable | Default | Description |
|---|---|---|
HOST |
127.0.0.1 |
Server host binding (use 0.0.0.0 for network access) |
PORT |
8000 |
Server port number |
DATABASE_URL |
sqlite:///./widgets.db |
Database connection URL |
DEBUG |
true |
Enable debug mode |
LOG_LEVEL |
info |
Logging level |
# Activate virtual environment (if not already activated)
poetry shell
# Run all tests
poetry run pytest
# Run tests with coverage
poetry run pytest --cov=src --cov-report=html
# Run specific test files
poetry run pytest tests/test_widget_model.py -v
# View coverage report
open htmlcov/index.html # On macOS# Activate virtual environment (if not already activated)
source aweberenv/bin/activate # On Windows: aweberenv\Scripts\activate
# Run all tests
python -m pytest
# Run tests with coverage
python -m pytest --cov=src --cov-report=html
# Run specific test files
python -m pytest tests/test_widget_model.py -v
# View coverage report
open htmlcov/index.html # On macOSAll code quality tools run automatically on every commit via pre-commit hooks:
# Manual formatting (if needed)
poetry run black src/ tests/
poetry run isort src/ tests/
# Manual checks (if needed)
poetry run flake8 src/ tests/
poetry run mypy src/
poetry run bandit -r src/# Manual formatting (if needed)
black src/ tests/
isort src/ tests/
# Manual checks (if needed)
flake8 src/ tests/
mypy src/
bandit -r src/The pre-commit hooks will automatically:
- Sort imports (isort)
- Format code (black)
- Check style (flake8)
- Analyze security (bandit)
- Verify types (mypy)
| Method | Endpoint | Description | Response |
|---|---|---|---|
GET |
/ |
API information | {"message": "Welcome to Widget CRUD API", "version": "1.0.0", "docs": "/docs"} |
| Method | Endpoint | Description | Response |
|---|---|---|---|
GET |
/health |
Application health status | {"status": "healthy", "service": "Widget CRUD API"} |
| Method | Endpoint | Description |
|---|---|---|
POST |
/widgets/ |
Create a new widget |
GET |
/widgets/ |
List all widgets (with pagination) |
GET |
/widgets/{widget_id} |
Get widget by ID |
PUT |
/widgets/{widget_id} |
Update widget by ID |
DELETE |
/widgets/{widget_id} |
Delete widget by ID |
curl -X POST http://localhost:8000/widgets/ \
-H "Content-Type: application/json" \
-d '{
"name": "Super Widget",
"number_of_parts": 42
}'curl http://localhost:8000/widgets/curl http://localhost:8000/widgets/1curl -X PUT http://localhost:8000/widgets/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Widget",
"number_of_parts": 50
}'curl -X DELETE http://localhost:8000/widgets/1curl http://localhost:8000/health{
"id": 1,
"name": "Super Widget",
"number_of_parts": 42,
"created_at": "2024-01-01T12:00:00Z",
"updated_at": "2024-01-01T12:00:00Z"
}- id: Auto-generated primary key (integer)
- name: Widget name (string, max 64 characters, required)
- number_of_parts: Number of parts (positive integer, required)
- created_at: Creation timestamp (auto-generated)
- updated_at: Last update timestamp (auto-updated)
aweber/
βββ src/
β βββ app/
β β βββ __init__.py
β β βββ main.py # FastAPI application setup
β β βββ config.py # Configuration management
β β βββ database.py # Database connection and session management
β β βββ exception_handlers.py # Global exception handling
β β βββ exceptions.py # Custom exceptions
β β βββ logging_config.py # Logging configuration
β β βββ middleware.py # Custom middleware
β β βββ models/
β β β βββ __init__.py
β β β βββ widget.py # Widget SQLAlchemy model
β β βββ repositories/ # Data access layer
β β βββ routers/ # API route handlers
β β βββ schemas/ # Pydantic models
β βββ main.py # Application entry point
β βββ __init__.py
βββ tests/ # Test files
βββ alembic/ # Database migration files
βββ docs/ # Documentation files
βββ pyproject.toml # Poetry dependencies and project config
βββ poetry.lock # Poetry lock file
βββ .flake8 # Flake8 configuration
βββ bandit.yaml # Bandit security configuration
βββ .pre-commit-config.yaml # Pre-commit hooks configuration
βββ pytest.ini # Pytest configuration
βββ README.md # This file
- Set
DEBUG=falsein environment - Configure production database URL
- Set up proper logging
- Use production ASGI server (Gunicorn + Uvicorn recommended)
DATABASE_URL=postgresql://user:password@localhost/widgets
DEBUG=false
LOG_LEVEL=warning
HOST=0.0.0.0
PORT=8000- Run commands with Poetry:
poetry run python --version(recommended) - Create feature branch:
git checkout -b feature/your-feature - Make changes and write tests
- Run tests:
poetry run pytest - Check code quality:
pre-commit run --all-files - Commit changes:
git commit -m "feat: your feature" - Push branch:
git push origin feature/your-feature - Create Pull Request
Note: Use poetry run <command> instead of activating the shell. This is more reliable and avoids shell state issues.
- Activate virtual environment:
source aweberenv/bin/activate(Windows:aweberenv\Scripts\activate) - Create feature branch:
git checkout -b feature/your-feature - Make changes and write tests
- Run tests:
python -m pytest - Check code quality:
pre-commit run --all-files - Commit changes:
git commit -m "feat: your feature" - Push branch:
git push origin feature/your-feature - Create Pull Request
Problem: Virtual environment not found or activation fails
# Solution: Recreate virtual environment with Poetry
poetry env remove python
poetry install
# Test the environment
poetry run python --version
# If you need shell activation:
$(poetry env activate) # Activates the environment
# OR install the shell plugin:
poetry self add poetry-plugin-shell
poetry shell# Solution: Recreate virtual environment manually
rm -rf aweberenv
python3 -m venv aweberenv
source aweberenv/bin/activate # On Windows: aweberenv\Scripts\activate
pip install -r requirements.txt
pip install -r requirements-dev.txtProblem: Dependencies not installing
# Solution: Check Python version and clear Poetry cache
python --version # Should be 3.12+
poetry cache clear pypi --all
poetry install# Solution: Check Python version and reinstall dependencies
python --version # Should be 3.12+
pip cache purge
pip install -r requirements.txt -r requirements-dev.txt --force-reinstallProblem: Database connection errors
# Solution: Run migrations (works with both Poetry and non-Poetry)
alembic upgrade head
# If database is corrupted, reset it
rm widgets.db test_widgets.db
alembic upgrade headProblem: Migration conflicts
# Solution: Reset migration history (works with both Poetry and non-Poetry)
alembic stamp head
alembic revision --autogenerate -m "reset migration"
alembic upgrade headProblem: Server won't start or port conflicts
# Solution: Check if port is in use
lsof -i :8000
# Kill existing process
kill -9 <PID># Or use different port
PORT=8080 poetry run python src/main.py# Or use different port
PORT=8080 python src/main.pyProblem: Import errors
# Solution: Check virtual environment and reinstall
poetry shell
poetry install
poetry run python src/main.py# Solution: Check virtual environment and reinstall
source aweberenv/bin/activate # On Windows: aweberenv\Scripts\activate
pip install -r requirements.txt -r requirements-dev.txt
python src/main.pyProblem: Tests failing due to database
# Solution: Clean test database
rm test_widgets.dbpoetry run pytest
# Or run tests with verbose output
poetry run pytest -v -spython -m pytest
# Or run tests with verbose output
python -m pytest -v -sProblem: Pre-commit hooks failing
# Solution: Run hooks manually and fix issues (works with both Poetry and non-Poetry)
pre-commit run --all-files
# Update pre-commit hooks
pre-commit autoupdateProblem: Linting errors
# Solution: Auto-format code
poetry run black src/ tests/
poetry run isort src/ tests/
poetry run flake8 src/ tests/ # Check remaining issues# Solution: Auto-format code
black src/ tests/
isort src/ tests/
flake8 src/ tests/ # Check remaining issuesProblem: Type checking errors
# Solution: Check mypy output and add type annotations
poetry run mypy src/# Solution: Check mypy output and add type annotations
mypy src/- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Install dependencies (
poetry install) - Set up pre-commit hooks (
poetry run pre-commit install) - Make your changes and add tests
- Run tests and quality checks (
poetry run pytest && pre-commit run --all-files) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Note: Use poetry run <command> for all commands instead of activating the shell with poetry shell.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Create and activate virtual environment (
python3 -m venv aweberenv && source aweberenv/bin/activate) - Install dependencies (
pip install -r requirements.txt -r requirements-dev.txt) - Set up pre-commit hooks (
pre-commit install) - Make your changes and add tests
- Run tests and quality checks (
python -m pytest && pre-commit run --all-files) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For support and questions, please open an issue in the GitHub repository.