feat(structure): flatten padelnomics to UV workspace monorepo layout

Mirrors the quart_saas_boilerplate template's new web/ workspace structure:
- git mv src/ → web/src/
- git mv tests/ → web/tests/
- git mv scripts/ → web/scripts/
- Split pyproject.toml into workspace root + web/pyproject.toml
- Dockerfile: COPY src/ → web/, update CSS build + output paths,
  add --package padelnomics to uv sync
- Makefile: update CSS input/output paths
- pytest testpaths: tests/ → web/tests/

uv sync passes, 402/403 tests pass (1 pre-existing failure in test_content).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-21 17:51:14 +01:00
parent 7325fc905f
commit 8221174683
204 changed files with 81 additions and 85 deletions

View File

@@ -3,9 +3,9 @@ FROM debian:bookworm-slim AS css-build
ADD https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 /usr/local/bin/tailwindcss ADD https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 /usr/local/bin/tailwindcss
RUN chmod +x /usr/local/bin/tailwindcss RUN chmod +x /usr/local/bin/tailwindcss
WORKDIR /app WORKDIR /app
COPY src/ ./src/ COPY web/src/ ./web/src/
RUN tailwindcss -i ./src/padelnomics/static/css/input.css \ RUN tailwindcss -i ./web/src/padelnomics/static/css/input.css \
-o ./src/padelnomics/static/css/output.css --minify -o ./web/src/padelnomics/static/css/output.css --minify
# Build stage # Build stage
FROM python:3.12-slim AS build FROM python:3.12-slim AS build
@@ -13,9 +13,9 @@ COPY --from=ghcr.io/astral-sh/uv:0.8 /uv /uvx /bin/
WORKDIR /app WORKDIR /app
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
COPY uv.lock pyproject.toml README.md ./ COPY uv.lock pyproject.toml README.md ./
COPY src/ ./src/ COPY web/ ./web/
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --no-dev --frozen uv sync --no-dev --frozen --package padelnomics
# Runtime stage # Runtime stage
FROM python:3.12-slim AS runtime FROM python:3.12-slim AS runtime
@@ -24,7 +24,7 @@ RUN useradd -m -u 1000 appuser
WORKDIR /app WORKDIR /app
RUN mkdir -p /app/data && chown -R appuser:appuser /app RUN mkdir -p /app/data && chown -R appuser:appuser /app
COPY --from=build --chown=appuser:appuser /app . COPY --from=build --chown=appuser:appuser /app .
COPY --from=css-build /app/src/padelnomics/static/css/output.css ./src/padelnomics/static/css/output.css COPY --from=css-build /app/web/src/padelnomics/static/css/output.css ./web/src/padelnomics/static/css/output.css
USER appuser USER appuser
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
ENV DATABASE_PATH=/app/data/app.db ENV DATABASE_PATH=/app/data/app.db

View File

@@ -6,7 +6,7 @@ bin/tailwindcss:
chmod +x bin/tailwindcss chmod +x bin/tailwindcss
css-build: bin/tailwindcss css-build: bin/tailwindcss
$(TAILWIND) -i src/padelnomics/static/css/input.css -o src/padelnomics/static/css/output.css --minify $(TAILWIND) -i web/src/padelnomics/static/css/input.css -o web/src/padelnomics/static/css/output.css --minify
css-watch: bin/tailwindcss css-watch: bin/tailwindcss
$(TAILWIND) -i src/padelnomics/static/css/input.css -o src/padelnomics/static/css/output.css --watch $(TAILWIND) -i web/src/padelnomics/static/css/input.css -o web/src/padelnomics/static/css/output.css --watch

View File

@@ -1,31 +1,10 @@
[project] [tool.uv.workspace]
name = "padelnomics" members = [
version = "0.1.0" "web",
description = "Plan, finance, and build your padel business"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"quart>=0.19.0",
"aiosqlite>=0.19.0",
"python-dotenv>=1.0.0",
"itsdangerous>=2.1.0",
"jinja2>=3.1.0",
"hypercorn>=0.17.0",
"paddle-python-sdk>=1.13.0",
"mistune>=3.0.0",
"resend>=2.22.0",
"weasyprint>=68.1",
] ]
[build-system] [dependency-groups]
requires = ["hatchling"] dev = [
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/padelnomics"]
[tool.uv]
dev-dependencies = [
"hypothesis>=6.151.6", "hypothesis>=6.151.6",
"playwright>=1.58.0", "playwright>=1.58.0",
"pytest>=8.0.0", "pytest>=8.0.0",
@@ -45,6 +24,6 @@ ignore = ["E501"]
[tool.pytest.ini_options] [tool.pytest.ini_options]
asyncio_mode = "auto" asyncio_mode = "auto"
testpaths = ["tests"] testpaths = ["web/tests"]
markers = ["visual: Playwright visual tests (require browser install)"] markers = ["visual: Playwright visual tests (require browser install)"]
addopts = "-m 'not visual'" addopts = "-m 'not visual'"

40
padelnomics/uv.lock generated
View File

@@ -6,6 +6,22 @@ resolution-markers = [
"python_full_version < '3.13'", "python_full_version < '3.13'",
] ]
[manifest]
members = [
"padelnomics",
]
[manifest.dependency-groups]
dev = [
{ name = "hypothesis", specifier = ">=6.151.6" },
{ name = "playwright", specifier = ">=1.58.0" },
{ name = "pytest", specifier = ">=8.0.0" },
{ name = "pytest-asyncio", specifier = ">=0.23.0" },
{ name = "pytest-playwright", specifier = ">=0.7.2" },
{ name = "respx", specifier = ">=0.22.0" },
{ name = "ruff", specifier = ">=0.3.0" },
]
[[package]] [[package]]
name = "aiofiles" name = "aiofiles"
version = "25.1.0" version = "25.1.0"
@@ -667,7 +683,7 @@ wheels = [
[[package]] [[package]]
name = "padelnomics" name = "padelnomics"
version = "0.1.0" version = "0.1.0"
source = { editable = "." } source = { editable = "web" }
dependencies = [ dependencies = [
{ name = "aiosqlite" }, { name = "aiosqlite" },
{ name = "hypercorn" }, { name = "hypercorn" },
@@ -681,17 +697,6 @@ dependencies = [
{ name = "weasyprint" }, { name = "weasyprint" },
] ]
[package.dev-dependencies]
dev = [
{ name = "hypothesis" },
{ name = "playwright" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-playwright" },
{ name = "respx" },
{ name = "ruff" },
]
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "aiosqlite", specifier = ">=0.19.0" }, { name = "aiosqlite", specifier = ">=0.19.0" },
@@ -706,17 +711,6 @@ requires-dist = [
{ name = "weasyprint", specifier = ">=68.1" }, { name = "weasyprint", specifier = ">=68.1" },
] ]
[package.metadata.requires-dev]
dev = [
{ name = "hypothesis", specifier = ">=6.151.6" },
{ name = "playwright", specifier = ">=1.58.0" },
{ name = "pytest", specifier = ">=8.0.0" },
{ name = "pytest-asyncio", specifier = ">=0.23.0" },
{ name = "pytest-playwright", specifier = ">=0.7.2" },
{ name = "respx", specifier = ">=0.22.0" },
{ name = "ruff", specifier = ">=0.3.0" },
]
[[package]] [[package]]
name = "pillow" name = "pillow"
version = "12.1.1" version = "12.1.1"

View File

@@ -0,0 +1,25 @@
[project]
name = "padelnomics"
version = "0.1.0"
description = "Plan, finance, and build your padel business"
readme = "../README.md"
requires-python = ">=3.11"
dependencies = [
"quart>=0.19.0",
"aiosqlite>=0.19.0",
"python-dotenv>=1.0.0",
"itsdangerous>=2.1.0",
"jinja2>=3.1.0",
"hypercorn>=0.17.0",
"paddle-python-sdk>=1.13.0",
"mistune>=3.0.0",
"resend>=2.22.0",
"weasyprint>=68.1",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/padelnomics"]

View File

@@ -8,7 +8,15 @@ from pathlib import Path
from quart import Blueprint, flash, g, redirect, render_template, request, session, url_for from quart import Blueprint, flash, g, redirect, render_template, request, session, url_for
from ..core import capture_waitlist_email, config, csrf_protect, execute, fetch_one, is_disposable_email, waitlist_gate from ..core import (
capture_waitlist_email,
config,
csrf_protect,
execute,
fetch_one,
is_disposable_email,
waitlist_gate,
)
from ..i18n import SUPPORTED_LANGS, get_translations from ..i18n import SUPPORTED_LANGS, get_translations
# Blueprint with its own template folder # Blueprint with its own template folder

View File

@@ -18,7 +18,15 @@ from ..auth.routes import (
mark_token_used, mark_token_used,
update_user, update_user,
) )
from ..core import config, csrf_protect, execute, fetch_one, is_disposable_email, is_plausible_phone, send_email from ..core import (
config,
csrf_protect,
execute,
fetch_one,
is_disposable_email,
is_plausible_phone,
send_email,
)
from ..i18n import get_translations from ..i18n import get_translations
bp = Blueprint( bp = Blueprint(

Some files were not shown because too many files have changed in this diff Show More