mirror of
https://github.com/Screenly/Anthias.git
synced 2026-06-10 09:08:09 -04:00
* feat(sentry): add Sentry error tracking to the Django services Adds sentry-sdk to the server and viewer dependency groups (plus the mypy group, since that CI job imports settings) and initialises it in the shared Django settings module, so anthias-server, anthias-celery, and the viewer all report crashes. - The DSN can be overridden via the SENTRY_DSN env var (pointing at an operator's own Sentry project), or set to an empty string to disable crash reporting entirely. - environment= mirrors the ENVIRONMENT env var (production default) so dev/CI events are filterable in Sentry. - release= comes from pyproject.toml's [project].version via the existing get_anthias_release() helper. - send_default_pii is gated on the existing analytics_opt_out knob in anthias.conf — opted-out devices still report crashes, but without request headers / IPs / user data. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sentry): don't send events from test runs by default The unit suite is built to run with no external network dependencies (conftest.py force-mocks Redis for the same reason), and exceptions raised on purpose by failing tests must not land in the production Sentry project. Default the DSN to empty under ENVIRONMENT=test or pytest (reusing the existing argv detector, moved up from the DATABASES section); an explicit SENTRY_DSN still wins so the integration stack can opt in deliberately. Addresses the Copilot review comment on the hardcoded default DSN. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(sentry): pin the no-events-under-pytest guarantee Asserts the client has no DSN, builds no transport, and drops capture calls when running under pytest, so a future settings.py refactor can't silently re-enable sending from test runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
254 lines
7.2 KiB
TOML
254 lines
7.2 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=68", "wheel"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "anthias"
|
|
version = "2026.06.1"
|
|
description = "The world's most popular open source digital signage project."
|
|
readme = "README.md"
|
|
requires-python = ">=3.13"
|
|
dependencies = []
|
|
|
|
[project.scripts]
|
|
anthias-manage = "anthias_server.manage:main"
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["src"]
|
|
include = ["anthias_*"]
|
|
namespaces = false
|
|
|
|
[dependency-groups]
|
|
dev-host = [
|
|
"ansible-lint==26.4.0",
|
|
"celery-types==0.26.0",
|
|
"django-stubs==6.0.5",
|
|
"djangorestframework-stubs==3.16.9",
|
|
"mypy==2.1.0",
|
|
"ruff==0.14.10",
|
|
"tenacity==9.1.4",
|
|
"types-gunicorn==26.0.0.20260518",
|
|
"types-netifaces==0.11.0.20260408",
|
|
"types-python-dateutil==2.9.0.20260518",
|
|
"types-pytz==2026.2.0.20260506",
|
|
"types-PyYAML==6.0.12.20260408",
|
|
"types-requests==2.33.0.20260518",
|
|
]
|
|
docker-image-builder = [
|
|
"click==8.1.7",
|
|
"jinja2==3.1.6",
|
|
"pygit2==1.19.2",
|
|
"requests==2.33.1",
|
|
"python-on-whales==0.81.0",
|
|
]
|
|
server = [
|
|
"cec==0.2.8",
|
|
"celery==5.6.3",
|
|
"certifi==2026.5.20",
|
|
"channels==4.3.2",
|
|
"channels-redis==4.3.0",
|
|
"Django==5.2.14",
|
|
"djangorestframework==3.17.1",
|
|
"django-dbbackup==5.3.0",
|
|
"django-stubs-ext==6.0.3",
|
|
"drf-spectacular==0.29.0",
|
|
"Jinja2==3.1.6",
|
|
"netifaces==0.11.0",
|
|
"packaging==26.2",
|
|
# Pillow + pillow-heif power the upload-time image normalisation
|
|
# pipeline (HEIC / HEIF / TIFF → lossless WebP). pillow-heif
|
|
# registers a libheif-backed Pillow plugin at import time; the
|
|
# libheif1 system package is supplied by the base image (see
|
|
# docker/Dockerfile.server.j2). Pillow itself is otherwise unused
|
|
# — adding it here instead of relying on a transitive import keeps
|
|
# the dependency explicit.
|
|
"Pillow==12.2.0",
|
|
"pillow-heif==1.3.0",
|
|
"psutil==7.2.2",
|
|
"pydbus==0.6.0",
|
|
"python-dateutil==2.9.0.post0",
|
|
"pytz==2026.2",
|
|
"PyYAML==6.0.3",
|
|
"redis==7.4.0",
|
|
"requests==2.33.1",
|
|
"sentry-sdk==2.61.1",
|
|
"tenacity==9.1.4",
|
|
"sh==2.2.2",
|
|
"urllib3==2.7.0",
|
|
"uvicorn[standard]==0.49.0",
|
|
"whitenoise==6.12.0",
|
|
"yt-dlp>=2026.3.17",
|
|
]
|
|
viewer = [
|
|
"cec==0.2.8",
|
|
"certifi==2026.5.20",
|
|
"Django==5.2.14",
|
|
"Jinja2==3.1.6",
|
|
"netifaces==0.11.0",
|
|
"pydbus==0.6.0",
|
|
"python-dateutil==2.9.0.post0",
|
|
"pytz==2026.2",
|
|
"redis==7.4.0",
|
|
"requests==2.33.1",
|
|
"sentry-sdk==2.61.1",
|
|
"tenacity==9.1.4",
|
|
"sh==2.2.2",
|
|
"urllib3==2.7.0",
|
|
]
|
|
dev = [
|
|
"pytest==9.0.3",
|
|
"pytest-cov==6.0.0",
|
|
"pytest-django==4.12.0",
|
|
"pytest-mock==3.15.1",
|
|
"pytest-xdist==3.8.0",
|
|
"playwright==1.59.0",
|
|
"pytest-playwright==0.8.0",
|
|
"time-machine==3.2.0",
|
|
]
|
|
host = [
|
|
"ansible-core==2.20.5",
|
|
"netifaces2==0.0.22",
|
|
"redis==7.4.0",
|
|
"requests==2.33.1",
|
|
"tenacity==9.1.4",
|
|
]
|
|
local = [
|
|
"click==8.1.7",
|
|
"requests==2.33.1",
|
|
"tenacity==9.1.4",
|
|
]
|
|
website = [
|
|
"pytest==9.0.3",
|
|
"requests==2.33.1",
|
|
]
|
|
test = [
|
|
{ include-group = "server" },
|
|
{ include-group = "viewer" },
|
|
{ include-group = "dev" },
|
|
]
|
|
# Used by the python-mypy CI job. The django-stubs plugin imports
|
|
# anthias_server.django_project.settings to introspect the app registry, so we need the
|
|
# runtime deps that settings touches — but not the heavy native-extension
|
|
# deps from the server group (cec, netifaces, etc.). We also include
|
|
# docker-image-builder so its tools (pygit2, python_on_whales) resolve.
|
|
mypy = [
|
|
{ include-group = "dev-host" },
|
|
{ include-group = "docker-image-builder" },
|
|
"channels==4.3.2",
|
|
"channels-redis==4.3.0",
|
|
"Django==5.2.14",
|
|
"django-dbbackup==5.3.0",
|
|
"django-stubs-ext==6.0.3",
|
|
"djangorestframework==3.17.1",
|
|
"drf-spectacular==0.29.0",
|
|
# Pillow ships PEP 561 stubs (py.typed). The processing module
|
|
# imports PIL at top level, so mypy needs the package resolvable
|
|
# to type-check the upload-time normalisation pipeline.
|
|
# pillow-heif is intentionally not pinned here — it's listed in
|
|
# tool.mypy.overrides above so its missing-import error is
|
|
# ignored, mirroring the cec / pydbus / sh pattern.
|
|
"Pillow==12.2.0",
|
|
"pytz==2026.2",
|
|
"sentry-sdk==2.61.1",
|
|
"whitenoise==6.12.0",
|
|
]
|
|
|
|
[tool.pytest.ini_options]
|
|
DJANGO_SETTINGS_MODULE = "anthias_server.django_project.settings"
|
|
testpaths = ["tests", "src/anthias_server/api/tests"]
|
|
python_files = ["test_*.py"]
|
|
markers = [
|
|
"integration: marks tests as integration (deselect with '-m \"not integration\"')",
|
|
]
|
|
# pytest-playwright config:
|
|
# --browser chromium - skip firefox/webkit (only chromium is
|
|
# installed in docker/Dockerfile.test).
|
|
# --tracing retain-on-failure
|
|
# - per-test trace; dropped for green tests,
|
|
# drained to test-artifacts/<id>/trace.zip
|
|
# on failure. `playwright show-trace
|
|
# trace.zip` replays.
|
|
# --screenshot only-on-failure
|
|
# - full-page PNG into the same per-test dir.
|
|
# --output test-artifacts - directory the GH Actions upload-artifact
|
|
# step picks up (.gitignored).
|
|
addopts = "--strict-markers --browser chromium --tracing retain-on-failure --screenshot only-on-failure --output test-artifacts"
|
|
|
|
[tool.coverage.run]
|
|
branch = true
|
|
source = [
|
|
"src/anthias_server",
|
|
"src/anthias_common",
|
|
"src/anthias_viewer",
|
|
]
|
|
omit = [
|
|
"*/migrations/*",
|
|
"*/__init__.py",
|
|
"src/anthias_server/django_project/asgi.py",
|
|
"src/anthias_server/django_project/routing.py",
|
|
"src/anthias_server/django_project/urls.py",
|
|
"src/anthias_server/django_project/wsgi.py",
|
|
"src/anthias_server/app/management/*",
|
|
"src/anthias_server/manage.py",
|
|
"src/anthias_host_agent/*",
|
|
"bin/*",
|
|
"tools/raspberry_pi_imager/*",
|
|
"tools/image_builder/*",
|
|
"src/anthias_viewer/__main__.py",
|
|
]
|
|
|
|
[tool.coverage.report]
|
|
fail_under = 80
|
|
show_missing = true
|
|
skip_covered = false
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"raise NotImplementedError",
|
|
"if TYPE_CHECKING:",
|
|
"if __name__ == .__main__.:",
|
|
]
|
|
|
|
[tool.coverage.xml]
|
|
output = "coverage.xml"
|
|
|
|
[tool.mypy]
|
|
python_version = "3.13"
|
|
strict = true
|
|
follow_imports = "normal"
|
|
mypy_path = ["src", "stubs"]
|
|
explicit_package_bases = true
|
|
plugins = ["mypy_django_plugin.main", "mypy_drf_plugin.main"]
|
|
exclude = [
|
|
"^\\.venv/",
|
|
"^node_modules/",
|
|
"/migrations/",
|
|
"/static/",
|
|
"^build/",
|
|
"^dist/",
|
|
# Vendored verbatim from a pinned Yocto/poky upstream commit; see
|
|
# the file header. Adding type annotations would put the file
|
|
# off-pin and silently break the provenance comment.
|
|
"^src/anthias_webview/sysroot-relativelinks\\.py$",
|
|
]
|
|
|
|
[[tool.mypy.overrides]]
|
|
# Third-party libs without type stubs. Listed explicitly so a future stub
|
|
# release is noticed (and the override removed) instead of silently ignored.
|
|
# `channels` itself is covered by partial PEP 561 stubs in stubs/channels-stubs/;
|
|
# only the helpers we actually call are typed there.
|
|
module = [
|
|
"cec",
|
|
"channels_redis.*",
|
|
"gi",
|
|
"gi.*",
|
|
"pillow_heif",
|
|
"pydbus",
|
|
"sh",
|
|
"yt_dlp",
|
|
"yt_dlp.*",
|
|
]
|
|
ignore_missing_imports = true
|
|
|
|
[tool.django-stubs]
|
|
django_settings_module = "anthias_server.django_project.settings"
|