Skip to content

Commit

Permalink
feat: implement service factory and refactor services (#193)
Browse files Browse the repository at this point in the history
Refactor the repositories and services to use an updated pattern.  It also leverages `to_model` to handle business logic for translating into a SQLAlchemy model.

---------

Co-authored-by: Alc-Alc <[email protected]>
  • Loading branch information
cofin and Alc-Alc authored Jan 14, 2025
1 parent 83ca0bb commit e9c9f79
Show file tree
Hide file tree
Showing 132 changed files with 1,619 additions and 2,712 deletions.
12 changes: 6 additions & 6 deletions .env.docker.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
SECRET_KEY='secret-key'
LITESTAR_DEBUG=true
LITESTAR_HOST=0.0.0.0
LITESTAR_PORT=8000
LITESTAR_PORT=8080
APP_URL=http://localhost:${LITESTAR_PORT}

LOG_LEVEL=10
LOG_LEVEL=20
# Database
DATABASE_ECHO=true
DATABASE_ECHO_POOL=true
DATABASE_ECHO=false
DATABASE_ECHO_POOL=false
DATABASE_POOL_DISABLE=false
DATABASE_POOL_MAX_OVERFLOW=5
DATABASE_POOL_SIZE=5
Expand All @@ -26,5 +26,5 @@ SAQ_CONCURRENCY=1
VITE_HOST=localhost
VITE_PORT=3006
VITE_HOT_RELOAD=True
VITE_DEV_MODE=True
ALLOWED_CORS_ORIGINS=["localhost:3006","localhost:8000"]
VITE_DEV_MODE=False
ALLOWED_CORS_ORIGINS=["localhost:3006","localhost:8080","localhost:8000"]
2 changes: 2 additions & 0 deletions .env.testing
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# App
SECRET_KEY='secret-key'

DATABASE_ECHO=false
DATABASE_ECHO_POOL=false
# Cache
VALKEY_PORT=6308
REDIS_URL=redis://localhost:${VALKEY_PORT}/0
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ jobs:
run: git fetch origin gh-pages --depth=1

- name: Build release docs
run: uv run python scripts/build-docs.py docs-build
run: uv run python tools/build_docs.py docs-build
if: github.event_name == 'release'

- name: Build dev docs
run: uv run python scripts/build-docs.py docs-build
run: uv run python tools/build_docs.py docs-build
if: github.event_name == 'push'

- name: Deploy
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ repos:
rev: v0.19.1
hooks:
- id: slotscheck
exclude: test_*|docs|migrations|scripts
exclude: test_*|docs|src/app/db/migrations|tools|manage.py
entry: env PYTHONPATH=src slotscheck
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
hooks:
- id: mypy
exclude: scripts/
exclude: tools/
additional_dependencies:
- passlib[argon2]
- asyncpg
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2021, 2022, 2023 Litestar Org.
Copyright (c) 2021, 2022, 2023, 2024, 2025 Litestar Org.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
287 changes: 176 additions & 111 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,25 @@ SHELL := /bin/bash

.DEFAULT_GOAL:=help
.ONESHELL:
USING_NPM = $(shell python3 -c "if __import__('pathlib').Path('package-lock.json').exists(): print('yes')")
ENV_PREFIX =.venv/bin/
NODE_MODULES_EXISTS = $(shell python3 -c "if __import__('pathlib').Path('node_modules').exists(): print('yes')")
SRC_DIR =src
BUILD_DIR =dist

.EXPORT_ALL_VARIABLES:

ifndef VERBOSE
.SILENT:
endif

MAKEFLAGS += --no-print-directory

# Define colors and formatting
BLUE := $(shell printf "\033[1;34m")
GREEN := $(shell printf "\033[1;32m")
RED := $(shell printf "\033[1;31m")
YELLOW := $(shell printf "\033[1;33m")
NC := $(shell printf "\033[0m")
INFO := $(shell printf "$(BLUE)$(NC)")
OK := $(shell printf "$(GREEN)$(NC)")
WARN := $(shell printf "$(YELLOW)$(NC)")
ERROR := $(shell printf "$(RED)$(NC)")

.PHONY: help
help: ## Display this help text for Makefile
help: ## Display this help text for Makefile
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)


.PHONY: upgrade
upgrade: ## Upgrade all dependencies to the latest stable versions
@echo "=> Updating all dependencies"
@uv lock --upgrade
@echo "=> Python Dependencies Updated"
@if [ "$(USING_NPM)" ]; then npm upgrade --latest; fi
@echo "=> Node Dependencies Updated"
@$(ENV_PREFIX)pre-commit autoupdate
@echo "=> Updated Pre-commit"

# =============================================================================
# Developer Utils
# =============================================================================
Expand All @@ -43,109 +34,183 @@ install-uv: ## Install latest version of
@uv tool install nodeenv >/dev/null 2>&1
@echo "${OK} UV installed successfully"

install: ## Install the project and
@uv sync
uv run python scripts/pre-build.py --install-packages
@if [ "$(NODE_MODULES_EXISTS)" ]; then echo "=> Removing existing node modules"; fi
if [ "$(NODE_MODULES_EXISTS)" ]; then $(MAKE) destroy-node_modules; fi
@echo "=> Install complete! Note: If you want to re-install re-run 'make install'"


clean: ## Cleanup temporary build artifacts
@echo "=> Cleaning working directory"
@rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ .coverage coverage.xml coverage.json htmlcov/ .mypy_cache
@find . -name '*.egg-info' -exec rm -rf {} +
@find . -name '*.egg' -exec rm -f {} +
@find . -name '*.pyc' -exec rm -f {} +
@find . -name '*.pyo' -exec rm -f {} +
@find . -name '*~' -exec rm -f {} +
@find . -name '__pycache__' -exec rm -rf {} +
@find . -name '.pytest_cache' -exec rm -rf {} +
@find . -name '.ipynb_checkpoints' -exec rm -rf {} +

destroy-venv: ## Destroy the virtual environment
@echo "=> Cleaning Python virtual environment"
@rm -rf .venv

destroy-node_modules: ## Destroy the node environment
@echo "=> Cleaning Node modules"
@rm -rf node_modules

tidy: clean destroy-venv destroy-node_modules ## Clean up everything

migrations: ## Generate database migrations
@echo "ATTENTION: This operation will create a new database migration for any defined models changes."
@while [ -z "$$MIGRATION_MESSAGE" ]; do read -r -p "Migration message: " MIGRATION_MESSAGE; done ;
@$(ENV_PREFIX)app database make-migrations --autogenerate -m "$${MIGRATION_MESSAGE}"
.PHONY: install
install: destroy clean ## Install the project, dependencies, and pre-commit for local development
@echo "${INFO} Starting fresh installation..."
@uv python pin 3.12 >/dev/null 2>&1
@uv venv >/dev/null 2>&1
@uv sync --all-extras --dev
@if ! command -v npm >/dev/null 2>&1; then \
echo "${INFO} Installing Node environment... 📦"; \
uvx nodeenv .venv --force --quiet; \
fi
@NODE_OPTIONS="--no-deprecation --disable-warning=ExperimentalWarning" npm install --no-fund
@echo "${OK} Installation complete! 🎉"

.PHONY: migrate
migrate: ## Generate database migrations
@echo "ATTENTION: Will apply all database migrations."
@$(ENV_PREFIX)app database upgrade

.PHONY: build
build:
@echo "=> Building package..."
uv run python scripts/pre-build.py --build-assets
@uv build
@echo "=> Package build complete..."
.PHONY: upgrade
upgrade: ## Upgrade all dependencies to the latest stable versions
@echo "${INFO} Updating all dependencies... 🔄"
@uv lock --upgrade
@NODE_OPTIONS="--no-deprecation --disable-warning=ExperimentalWarning" uv run npm upgrade --latest
@echo "${OK} Dependencies updated 🔄"
@NODE_OPTIONS="--no-deprecation --disable-warning=ExperimentalWarning" uv run pre-commit autoupdate
@echo "${OK} Updated Pre-commit hooks 🔄"

.PHONY: clean
clean: ## Cleanup temporary build artifacts
@echo "${INFO} Cleaning working directory..."
@rm -rf pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ .coverage coverage.xml coverage.json htmlcov/ .pytest_cache tests/.pytest_cache tests/**/.pytest_cache .mypy_cache .unasyncd_cache/ .auto_pytabs_cache node_modules >/dev/null 2>&1
@find . -name '*.egg-info' -exec rm -rf {} + >/dev/null 2>&1
@find . -type f -name '*.egg' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*.pyc' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*.pyo' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*~' -exec rm -f {} + >/dev/null 2>&1
@find . -name '__pycache__' -exec rm -rf {} + >/dev/null 2>&1
@find . -name '.ipynb_checkpoints' -exec rm -rf {} + >/dev/null 2>&1
@echo "${OK} Working directory cleaned"
$(MAKE) docs-clean

.PHONY: destroy
destroy: ## Destroy the virtual environment
@echo "${INFO} Destroying virtual environment... 🗑️"
@uv run pre-commit clean >/dev/null 2>&1
@rm -rf .venv
@echo "${OK} Virtual environment destroyed 🗑️"

.PHONY: lock
lock: ## Rebuild lockfiles from scratch, updating all dependencies
@uv lock
lock: ## Rebuild lockfiles from scratch, updating all dependencies
@echo "${INFO} Rebuilding lockfiles... 🔄"
@uv lock --upgrade >/dev/null 2>&1
@echo "${OK} Lockfiles updated"

.PHONY: release
release: ## Bump version and create release tag
@echo "${INFO} Preparing for release... 📦"
@make clean
@uv run bump-my-version bump $(bump)
@make build
@echo "${OK} Release complete 🎉"

start-infra:
docker compose -f docker-compose.infra.yml up --force-recreate -d

stop-infra:
docker compose -f docker-compose.infra.yml down --remove-orphans
# =============================================================================
# Tests, Linting, Coverage
# =============================================================================
.PHONY: lint
lint: ## Runs pre-commit hooks; includes ruff linting, codespell, black
@echo "=> Running pre-commit process"
@$(ENV_PREFIX)pre-commit run --all-files
@echo "=> Pre-commit complete"
.PHONY: mypy
mypy: ## Run mypy
@echo "${INFO} Running mypy... 🔍"
@uv run dmypy run
@echo "${OK} Mypy checks passed ✨"

.PHONY: pyright
pyright: ## Run pyright
@echo "${INFO} Running pyright... 🔍"
@uv run pyright
@echo "${OK} Pyright checks passed ✨"

.PHONY: type-check
type-check: mypy pyright ## Run all type checking

.PHONY: pre-commit
pre-commit: ## Runs pre-commit hooks; includes ruff formatting and linting, codespell
@echo "${INFO} Running pre-commit checks... 🔎"
@uv run pre-commit run --color=always --all-files
@echo "${OK} Pre-commit checks passed ✨"

.PHONY: slotscheck
slotscheck: ## Run slotscheck
@echo "${INFO} Running slots check... 🔍"
@uv run slotscheck -m app
@echo "${OK} Slots check passed ✨"

.PHONY: fix
fix: ## Run formatting scripts
@echo "${INFO} Running code formatters... 🔧"
@uv run ruff check --fix --unsafe-fixes
@echo "${OK} Code formatting complete ✨"

.PHONY: format
format: ## Runs code formatting utilities
@echo "=> Running pre-commit process"
@$(ENV_PREFIX)ruff . --fix
@echo "=> Pre-commit complete"
.PHONY: lint
lint: pre-commit type-check slotscheck ## Run all linting

.PHONY: coverage
coverage: ## Run the tests and generate coverage report
@echo "=> Running tests with coverage"
@$(ENV_PREFIX)pytest tests --cov=app
@$(ENV_PREFIX)coverage html
@$(ENV_PREFIX)coverage xml
@echo "=> Coverage report generated"
coverage: ## Run the tests and generate coverage report
@echo "${INFO} Running tests with coverage... 📊"
@uv run pytest tests --cov -n auto --quiet
@uv run coverage html >/dev/null 2>&1
@uv run coverage xml >/dev/null 2>&1
@echo "${OK} Coverage report generated"

.PHONY: test
test: ## Run the tests
@echo "=> Running test cases"
@$(ENV_PREFIX)pytest tests
@echo "=> Tests complete"
test: ## Run the tests
@echo "${INFO} Running test cases... 🧪"
@uv run pytest tests -n 2 --quiet
@echo "${OK} Tests passed ✨"

.PHONY: test-all
test-all: ## Run all tests
@echo "${INFO} Running all test cases... 🧪"
@uv run pytest tests -m '' -n 2 --quiet
@echo "${OK} All tests passed ✨"

.PHONY: check-all
check-all: lint test-all coverage ## Run all linting, tests, and coverage checks


# =============================================================================
# Docs
# =============================================================================
.PHONY: docs-install
docs-install: ## Install docs dependencies
@echo "=> Installing documentation dependencies"
@uv sync --group docs
@echo "=> Installed documentation dependencies"

docs-clean: ## Dump the existing built docs
@echo "=> Cleaning documentation build assets"
@rm -rf docs/_build
@echo "=> Removed existing documentation build assets"

docs-serve: docs-clean ## Serve the docs locally
@echo "=> Serving documentation"
$uv run sphinx-autobuild docs docs/_build/ -j auto --watch src --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002

docs: docs-clean ## Dump the existing built docs and rebuild them
@echo "=> Building documentation"
@uv run sphinx-build -M html docs docs/_build/ -E -a -j auto --keep-going
.PHONY: docs-clean
docs-clean: ## Dump the existing built docs
@echo "${INFO} Cleaning documentation build assets... 🧹"
@rm -rf docs/_build >/dev/null 2>&1
@echo "${OK} Documentation assets cleaned"

.PHONY: docs-serve
docs-serve: docs-clean ## Serve the docs locally
@echo "${INFO} Starting documentation server... 📚"
@uv run sphinx-autobuild docs docs/_build/ -j auto --watch app --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002

.PHONY: docs
docs: docs-clean ## Dump the existing built docs and rebuild them
@echo "${INFO} Building documentation... 📝"
@uv run sphinx-build -M html docs docs/_build/ -E -a -j auto -W --keep-going
@echo "${OK} Documentation built successfully"

.PHONY: docs-linkcheck
docs-linkcheck: ## Run the link check on the docs
@echo "${INFO} Checking documentation links... 🔗"
@uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_ignore='http://.*','https://.*' >/dev/null 2>&1
@echo "${OK} Link check complete"

.PHONY: docs-linkcheck-full
docs-linkcheck-full: ## Run the full link check on the docs
@echo "${INFO} Running full link check... 🔗"
@uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_anchors=0 >/dev/null 2>&1
@echo "${OK} Full link check complete"


# -----------------------------------------------------------------------------
# Local Infrastructure
# -----------------------------------------------------------------------------

.PHONY: start-infra
start-infra: ## Start local containers
@echo "${INFO} Starting local infrastructure... 🚀"
@docker compose -f deploy/docker-compose.infra.yml up -d --force-recreate >/dev/null 2>&1
@echo "${OK} Infrastructure is ready"

.PHONY: stop-infra
stop-infra: ## Stop local containers
@echo "${INFO} Stopping infrastructure... 🛑"
@docker compose -f deploy/docker-compose.infra.yml down >/dev/null 2>&1
@echo "${OK} Infrastructure stopped"

.PHONY: wipe-infra
wipe-infra: ## Remove local container info
@echo "${INFO} Wiping infrastructure... 🧹"
@docker compose -f deploy/docker-compose.infra.yml down -v --remove-orphans >/dev/null 2>&1
@echo "${OK} Infrastructure wiped clean"

.PHONY: infra-logs
infra-logs: ## Tail development infrastructure logs
@echo "${INFO} Tailing infrastructure logs... 📋"
@docker compose -f deploy/docker-compose.infra.yml logs -f
Loading

0 comments on commit e9c9f79

Please sign in to comment.