pyproject.toml
Rama develop · réplica de lectura del repositorio original.
[project]
name = "morsl"
# Build scaffolding only, NOT the shipped version. The Dockerfile does
# `pip install .` in the builder purely to resolve dependencies into the venv,
# and a project table needs a version for that to work — it then deletes the
# package. The version users see is MORSL_VERSION, set from the git tag via
# APP_VERSION at image build time. Do not read this value for anything.
version = "0.0.0"
description = "Autocreate menus from Tandoor API"
requires-python = ">=3.12"
license = "MIT"
authors = [{ name = "Cron", email = "cron@featurecreep.dev" }]
keywords = ["meal-planning", "tandoor", "menu-generator", "docker", "self-hosted"]
dependencies = [
"requests==2.34.2",
"pulp==2.9.0",
"tzlocal==5.4.5",
# zoneinfo reads the system tz database first and falls back to this
# package. Recent Debian/Ubuntu moved legacy names (US/Eastern) into an
# optional tzdata-legacy package, so without it TZ=US/Eastern silently
# resolves to UTC depending on the base image.
"tzdata==2026.6",
"fastapi==0.162.0",
"uvicorn[standard]==0.54.0",
"pydantic-settings==2.16.2",
"python-multipart==0.0.33",
"apscheduler==3.11.3",
"defusedxml==0.7.1",
"Pillow==13.0.0",
"cairosvg==2.9.1",
"python-slugify==9.1.3",
"cachetools==7.2.8",
"py-svg-hush==0.3.0",
"httpx==0.28.1",
]
[project.optional-dependencies]
dev = [
"ruff==0.17.3", # linter, formatter, import sort
"mypy==2.4.1",
"pre-commit==4.7.0",
"colorlog==6.12.0",
"pytest==9.2.0",
"pytest-cov==7.1.0",
"pytest-asyncio==1.4.1.post1",
]
[tool.setuptools.packages.find]
include = ["morsl", "morsl.*"]
[tool.ruff]
fix = true
line-length = 99
target-version = "py312"
# ruff >= 0.16 formats Python blocks inside Markdown. The design docs use
# elided snippets (`...` for omitted bodies), which the formatter rewrites —
# so keep prose out of its reach.
extend-exclude = ["*.md"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
"ANN", # flake8 type annotations
"RUF", # ruff-specific rules
"S", # flake8-bandit (security)
"PT", # flake8-pytest-style
"SIM", # flake8-simplify
]
ignore = [
"ANN001", "ANN002", "ANN003", "ANN201", "ANN204", "ANN202", "ANN401",
"RUF012",
"C901", # complexity — un-suppress after Phase 5 refactoring
"S101", # assert in non-test code — used in solver debug
"S104", # binding to 0.0.0.0 — intentional in Docker
"S311", # random — used for LP variety, not security
]
fixable = ["ALL"]
external = ["broad-except", "direct-service"] # custom architectural lint markers
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["ANN", "S"]
"morsl/app/api/routes/*.py" = ["B008"] # FastAPI Depends() in defaults
"morsl/app/api/dependencies.py" = ["B008"]
"morsl/app/main.py" = ["B008"]
[tool.ruff.lint.flake8-annotations]
suppress-dummy-args = true
mypy-init-return = true
[tool.ruff.format]
quote-style = "double"
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
python_functions = "test_*"
addopts = ["-v", "--strict-markers", "--tb=short"]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"integration: marks tests that require live Tandoor API",
]
[tool.mypy]
python_version = "3.12"
strict = true
ignore_missing_imports = true
[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]
[tool.semantic_release]
# Used only to COMPUTE the next version in push.yml's auto-release job; psr
# never writes, commits or tags here. The tag is created by that job and fed to
# the image build as APP_VERSION, so the git tag stays the single source.
commit_parser = "conventional"
tag_format = "v{version}"
major_on_zero = false
allow_zero_version = true
[tool.semantic_release.commit_parser_options]
minor_tags = ["feat"]
# "deps" is patch-producing: pip, npm and docker updates all reach a user here.
# allowed_tags must be listed explicitly — its default is computed from the
# class-level defaults, so overriding patch_tags alone leaves "deps"
# unrecognised and silently drops every such commit.
patch_tags = ["fix", "perf", "deps"]
allowed_tags = [
"feat", "fix", "perf", "deps",
"build", "chore", "ci", "docs", "style", "refactor", "test",
]
[tool.semantic_release.branches.main]
match = "main"
prerelease = false