From 64947deeb14b9d3a49cf8db8b7b7a0a40ad7e44f Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Mon, 11 May 2026 22:08:57 +0200 Subject: [PATCH] fix: use append (>>) instead of overwrite (>) for cron logs and add missing dependencies - Fixed api/schema.py to generate cron jobs using '>> wecker.log' so logs aren't truncated. - Added test_bugfix_default_command_uses_append_for_logs in tests/test_api.py to prevent regression. - Added RPi.GPIO and pygame to pyproject.toml via 'uv add' to fix ModuleNotFoundError in cron jobs. - Updated README.md to reflect that system python packages are no longer needed. --- README.md | 4 ---- api.pid | 1 - api/schema.py | 2 +- pyproject.toml | 2 ++ tests/test_api.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++ uv.lock | 25 ++++++++++++++++++++++ 6 files changed, 81 insertions(+), 6 deletions(-) delete mode 100644 api.pid diff --git a/README.md b/README.md index d54c46e..b1c82e4 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,6 @@ This project uses Python 3 and `uv` for dependency management. To set up the env uv sync ``` -Note: The system also requires `python3-pygame` and `python3-rpi.gpio` which should be installed via system packages: -```bash -sudo apt-get install python3-pygame python3-rpi.gpio -``` ## Wiring diff --git a/api.pid b/api.pid deleted file mode 100644 index dd41798..0000000 --- a/api.pid +++ /dev/null @@ -1 +0,0 @@ -17958 diff --git a/api/schema.py b/api/schema.py index c05d5f9..e7c311d 100644 --- a/api/schema.py +++ b/api/schema.py @@ -49,7 +49,7 @@ class Mutation: if command is None: project_root = Path(__file__).parent.parent.absolute() python_exec = sys.executable - command = f"cd {project_root} && {python_exec} wecker.py > wecker.log 2>&1" + command = f"cd {project_root} && {python_exec} wecker.py >> wecker.log 2>&1" manager = get_manager() new_id = manager.set_alarm( diff --git a/pyproject.toml b/pyproject.toml index ba8c9ea..317ecf2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,8 +6,10 @@ readme = "README.md" requires-python = ">=3.13" dependencies = [ "fastapi>=0.136.1", + "pygame>=2.6.1", "python-crontab>=3.3.0", "python-dotenv>=1.2.2", + "rpi-gpio>=0.7.1", "strawberry-graphql>=0.315.3", "uvicorn>=0.46.0", ] diff --git a/tests/test_api.py b/tests/test_api.py index 90a0351..7448b4d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -40,6 +40,59 @@ def test_auth_invalid(): assert response.status_code == 401 +def test_bugfix_default_command_uses_append_for_logs(): + """ + Test for bugfix: Ensure the default command appends (>>) to wecker.log + instead of overwriting (>) it. + """ + from api.schema import Mutation + + mutation = Mutation() + # Call the resolver directly without command to trigger default command generation + alarm = mutation.set_alarm(cron_expression="0 9 * * *") + + # Verify the generated command string + command = alarm.command + assert ">> wecker.log 2>&1" in command, ( + f"Command must use append '>>' syntax. Got: {command}" + ) + assert "> wecker.log 2>&1" not in command.replace(">> wecker.log", "REPLACED"), ( + "Command must not use overwrite '>'" + ) + + # Cleanup + mutation.delete_alarm(id=alarm.id) + + +def test_set_alarm_default_command_append(): + headers = {"X-API-Key": "test-secret"} + mutation = """ + mutation { + setAlarm(cronExpression: "0 9 * * *") { + id + command + } + } + """ + res = client.post("/graphql", json={"query": mutation}, headers=headers) + assert res.status_code == 200 + data = res.json()["data"]["setAlarm"] + + # Assert the command contains the correct append syntax (>>) and not just overwrite (>) + command = data["command"] + assert ">> wecker.log 2>&1" in command + assert "> wecker.log 2>&1" not in command.replace(">> wecker.log", "REPLACED") + + # Cleanup so we don't break subsequent tests + alarm_id = data["id"] + mutation_delete = f""" + mutation {{ + deleteAlarm(id: "{alarm_id}") + }} + """ + client.post("/graphql", json={"query": mutation_delete}, headers=headers) + + def test_graphql_workflow(): headers = {"X-API-Key": "test-secret"} diff --git a/uv.lock b/uv.lock index f7eb077..08b20ed 100644 --- a/uv.lock +++ b/uv.lock @@ -243,6 +243,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, ] +[[package]] +name = "pygame" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/cc/08bba60f00541f62aaa252ce0cfbd60aebd04616c0b9574f755b583e45ae/pygame-2.6.1.tar.gz", hash = "sha256:56fb02ead529cee00d415c3e007f75e0780c655909aaa8e8bf616ee09c9feb1f", size = 14808125, upload-time = "2024-09-29T13:41:34.698Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/91/718acf3e2a9d08a6ddcc96bd02a6f63c99ee7ba14afeaff2a51c987df0b9/pygame-2.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6039f3a55d800db80e8010f387557b528d34d534435e0871326804df2a62f2", size = 13090765, upload-time = "2024-09-29T14:27:02.377Z" }, + { url = "https://files.pythonhosted.org/packages/0e/c6/9cb315de851a7682d9c7568a41ea042ee98d668cb8deadc1dafcab6116f0/pygame-2.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2a3a1288e2e9b1e5834e425bedd5ba01a3cd4902b5c2bff8ed4a740ccfe98171", size = 12381704, upload-time = "2024-09-29T14:27:10.228Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8f/617a1196e31ae3b46be6949fbaa95b8c93ce15e0544266198c2266cc1b4d/pygame-2.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27eb17e3dc9640e4b4683074f1890e2e879827447770470c2aba9f125f74510b", size = 13581091, upload-time = "2024-09-29T11:30:27.653Z" }, + { url = "https://files.pythonhosted.org/packages/3b/87/2851a564e40a2dad353f1c6e143465d445dab18a95281f9ea458b94f3608/pygame-2.6.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c1623180e70a03c4a734deb9bac50fc9c82942ae84a3a220779062128e75f3b", size = 14273844, upload-time = "2024-09-29T11:40:04.138Z" }, + { url = "https://files.pythonhosted.org/packages/85/b5/aa23aa2e70bcba42c989c02e7228273c30f3b44b9b264abb93eaeff43ad7/pygame-2.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef07c0103d79492c21fced9ad68c11c32efa6801ca1920ebfd0f15fb46c78b1c", size = 13951197, upload-time = "2024-09-29T11:40:06.785Z" }, + { url = "https://files.pythonhosted.org/packages/a6/06/29e939b34d3f1354738c7d201c51c250ad7abefefaf6f8332d962ff67c4b/pygame-2.6.1-cp313-cp313-win32.whl", hash = "sha256:3acd8c009317190c2bfd81db681ecef47d5eb108c2151d09596d9c7ea9df5c0e", size = 10249309, upload-time = "2024-09-29T11:10:23.329Z" }, + { url = "https://files.pythonhosted.org/packages/7e/11/17f7f319ca91824b86557e9303e3b7a71991ef17fd45286bf47d7f0a38e6/pygame-2.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:813af4fba5d0b2cb8e58f5d95f7910295c34067dcc290d34f1be59c48bd1ea6a", size = 10620084, upload-time = "2024-09-29T11:48:51.587Z" }, +] + [[package]] name = "pygments" version = "2.20.0" @@ -322,6 +337,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "rpi-gpio" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/0f/10b524a12b3445af1c607c27b2f5ed122ef55756e29942900e5c950735f2/RPi.GPIO-0.7.1.tar.gz", hash = "sha256:cd61c4b03c37b62bba4a5acfea9862749c33c618e0295e7e90aa4713fb373b70", size = 29090, upload-time = "2022-02-06T15:15:06.022Z" } + [[package]] name = "ruff" version = "0.15.12" @@ -424,8 +445,10 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "fastapi" }, + { name = "pygame" }, { name = "python-crontab" }, { name = "python-dotenv" }, + { name = "rpi-gpio" }, { name = "strawberry-graphql" }, { name = "uvicorn" }, ] @@ -442,8 +465,10 @@ dev = [ [package.metadata] requires-dist = [ { name = "fastapi", specifier = ">=0.136.1" }, + { name = "pygame", specifier = ">=2.6.1" }, { name = "python-crontab", specifier = ">=3.3.0" }, { name = "python-dotenv", specifier = ">=1.2.2" }, + { name = "rpi-gpio", specifier = ">=0.7.1" }, { name = "strawberry-graphql", specifier = ">=0.315.3" }, { name = "uvicorn", specifier = ">=0.46.0" }, ]