From 9a4ee8e0cf9e9af706ed561e55f9f3d36ce3fe17 Mon Sep 17 00:00:00 2001 From: rpotter6298 Date: Sun, 30 Aug 2026 15:05:17 +0200 Subject: [PATCH] Flatten to a single package directory The checkout is now astrape/astrape-oracle, not astrape/astrape-oracle/. The package contents move to the repository root and pyproject maps the package name to '.' via package-dir, with the subpackages listed explicitly. The systemd units move out to /srv/astrape/deploy/systemd, outside every repository, because they describe this deployment rather than any one component. Verified both install modes: editable, which is how the deployment runs, and a plain wheel install, which is what the container build does. Co-Authored-By: Claude Opus 5 (1M context) --- astrape_oracle/__init__.py => __init__.py | 0 .../classes => classes}/__init__.py | 0 .../classes => classes}/datasets.py | 0 .../classes => classes}/oracle_store.py | 0 .../classes => classes}/weather/__init__.py | 0 .../classes => classes}/weather/ecowitt.py | 0 .../classes => classes}/weather/openmeteo.py | 0 .../classes => classes}/weather/store.py | 0 deploy/systemd/astrape-oracle.service | 25 ----------------- .../astrape-usage-tcn-training.service | 28 ------------------- .../systemd/astrape-usage-tcn-training.timer | 11 -------- .../systemd/astrape-weather-forecast.service | 25 ----------------- .../systemd/astrape-weather-station.service | 26 ----------------- pyproject.toml | 8 ++++-- .../scripts => scripts}/__init__.py | 0 .../scripts => scripts}/daemons/__init__.py | 0 .../daemons/oracle_daemon.py | 0 .../daemons/weather_forecast_daemon.py | 0 .../daemons/weather_station_daemon.py | 0 .../scripts => scripts}/debug/__init__.py | 0 .../debug/debug_duplicates.py | 0 .../debug/debug_energy_forecast.py | 0 .../debug/debug_oracle_evaluations.py | 0 .../scripts => scripts}/evaluator.py | 0 .../scripts => scripts}/tcn/__init__.py | 0 .../scripts => scripts}/tcn/schedule.py | 0 .../scripts => scripts}/tcn/train.py | 0 27 files changed, 6 insertions(+), 117 deletions(-) rename astrape_oracle/__init__.py => __init__.py (100%) rename {astrape_oracle/classes => classes}/__init__.py (100%) rename {astrape_oracle/classes => classes}/datasets.py (100%) rename {astrape_oracle/classes => classes}/oracle_store.py (100%) rename {astrape_oracle/classes => classes}/weather/__init__.py (100%) rename {astrape_oracle/classes => classes}/weather/ecowitt.py (100%) rename {astrape_oracle/classes => classes}/weather/openmeteo.py (100%) rename {astrape_oracle/classes => classes}/weather/store.py (100%) delete mode 100644 deploy/systemd/astrape-oracle.service delete mode 100644 deploy/systemd/astrape-usage-tcn-training.service delete mode 100644 deploy/systemd/astrape-usage-tcn-training.timer delete mode 100644 deploy/systemd/astrape-weather-forecast.service delete mode 100644 deploy/systemd/astrape-weather-station.service rename {astrape_oracle/scripts => scripts}/__init__.py (100%) rename {astrape_oracle/scripts => scripts}/daemons/__init__.py (100%) rename {astrape_oracle/scripts => scripts}/daemons/oracle_daemon.py (100%) rename {astrape_oracle/scripts => scripts}/daemons/weather_forecast_daemon.py (100%) rename {astrape_oracle/scripts => scripts}/daemons/weather_station_daemon.py (100%) rename {astrape_oracle/scripts => scripts}/debug/__init__.py (100%) rename {astrape_oracle/scripts => scripts}/debug/debug_duplicates.py (100%) rename {astrape_oracle/scripts => scripts}/debug/debug_energy_forecast.py (100%) rename {astrape_oracle/scripts => scripts}/debug/debug_oracle_evaluations.py (100%) rename {astrape_oracle/scripts => scripts}/evaluator.py (100%) rename {astrape_oracle/scripts => scripts}/tcn/__init__.py (100%) rename {astrape_oracle/scripts => scripts}/tcn/schedule.py (100%) rename {astrape_oracle/scripts => scripts}/tcn/train.py (100%) diff --git a/astrape_oracle/__init__.py b/__init__.py similarity index 100% rename from astrape_oracle/__init__.py rename to __init__.py diff --git a/astrape_oracle/classes/__init__.py b/classes/__init__.py similarity index 100% rename from astrape_oracle/classes/__init__.py rename to classes/__init__.py diff --git a/astrape_oracle/classes/datasets.py b/classes/datasets.py similarity index 100% rename from astrape_oracle/classes/datasets.py rename to classes/datasets.py diff --git a/astrape_oracle/classes/oracle_store.py b/classes/oracle_store.py similarity index 100% rename from astrape_oracle/classes/oracle_store.py rename to classes/oracle_store.py diff --git a/astrape_oracle/classes/weather/__init__.py b/classes/weather/__init__.py similarity index 100% rename from astrape_oracle/classes/weather/__init__.py rename to classes/weather/__init__.py diff --git a/astrape_oracle/classes/weather/ecowitt.py b/classes/weather/ecowitt.py similarity index 100% rename from astrape_oracle/classes/weather/ecowitt.py rename to classes/weather/ecowitt.py diff --git a/astrape_oracle/classes/weather/openmeteo.py b/classes/weather/openmeteo.py similarity index 100% rename from astrape_oracle/classes/weather/openmeteo.py rename to classes/weather/openmeteo.py diff --git a/astrape_oracle/classes/weather/store.py b/classes/weather/store.py similarity index 100% rename from astrape_oracle/classes/weather/store.py rename to classes/weather/store.py diff --git a/deploy/systemd/astrape-oracle.service b/deploy/systemd/astrape-oracle.service deleted file mode 100644 index 7692a2e..0000000 --- a/deploy/systemd/astrape-oracle.service +++ /dev/null @@ -1,25 +0,0 @@ -[Unit] -Description=Astrape Energy Oracle Forecast Snapshots -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -User=gibil -Group=gibil -WorkingDirectory=/srv/astrape -Environment=PYTHONUNBUFFERED=1 -Environment=PYTHONDONTWRITEBYTECODE=1 -# WorkingDirectory is /srv/astrape, which also holds the gibil checkout. Without -# this, Python prepends the working directory to sys.path and the repo root -# /srv/astrape/gibil shadows the installed package as a namespace portion -- -# gibil.__file__ becomes None and imports work only by accident. All code is -# installed into the venv, so nothing needs the working directory on sys.path. -Environment=PYTHONSAFEPATH=1 -Environment=ASTRAPE_ORACLE_POLL_SECONDS=300 -ExecStart=/srv/astrape/.venv/bin/python -m astrape_oracle.scripts.daemons.oracle_daemon -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target diff --git a/deploy/systemd/astrape-usage-tcn-training.service b/deploy/systemd/astrape-usage-tcn-training.service deleted file mode 100644 index f6acd4a..0000000 --- a/deploy/systemd/astrape-usage-tcn-training.service +++ /dev/null @@ -1,28 +0,0 @@ -[Unit] -Description=Astrape Usage TCN Adaptive Training -After=network-online.target -Wants=network-online.target - -[Service] -Type=oneshot -User=gibil -Group=gibil -WorkingDirectory=/srv/astrape -Environment=PYTHONUNBUFFERED=1 -Environment=PYTHONDONTWRITEBYTECODE=1 -# WorkingDirectory is /srv/astrape, which also holds the gibil checkout. Without -# this, Python prepends the working directory to sys.path and the repo root -# /srv/astrape/gibil shadows the installed package as a namespace portion -- -# gibil.__file__ becomes None and imports work only by accident. All code is -# installed into the venv, so nothing needs the working directory on sys.path. -Environment=PYTHONSAFEPATH=1 -# This host is a Xeon E5-2650 v2: no AVX2, no FMA. Torch dispatches kernels it -# cannot execute and dies with SIGILL inside Adam, so force the scalar path. -# The real fix is external_tcn on a GPU host; this keeps the local run alive -# until the scheduler is pointed at it. -Environment=ATEN_CPU_CAPABILITY=default -# Training competes with a 5-second Modbus poll on 8 cores. Leave headroom. -Environment=OMP_NUM_THREADS=4 -Environment=MKL_NUM_THREADS=4 -Nice=10 -ExecStart=/srv/astrape/.venv/bin/python -m astrape_oracle.scripts.tcn.schedule diff --git a/deploy/systemd/astrape-usage-tcn-training.timer b/deploy/systemd/astrape-usage-tcn-training.timer deleted file mode 100644 index 9babec2..0000000 --- a/deploy/systemd/astrape-usage-tcn-training.timer +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Run Astrape Usage TCN Adaptive Training Nightly - -[Timer] -OnCalendar=*-*-* 03:20:00 -Persistent=true -RandomizedDelaySec=20m -Unit=astrape-usage-tcn-training.service - -[Install] -WantedBy=timers.target diff --git a/deploy/systemd/astrape-weather-forecast.service b/deploy/systemd/astrape-weather-forecast.service deleted file mode 100644 index 606010b..0000000 --- a/deploy/systemd/astrape-weather-forecast.service +++ /dev/null @@ -1,25 +0,0 @@ -[Unit] -Description=Astrape Weather Forecast Ingest -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -User=gibil -Group=gibil -WorkingDirectory=/srv/astrape -Environment=PYTHONUNBUFFERED=1 -Environment=PYTHONDONTWRITEBYTECODE=1 -# WorkingDirectory is /srv/astrape, which also holds the gibil checkout. Without -# this, Python prepends the working directory to sys.path and the repo root -# /srv/astrape/gibil shadows the installed package as a namespace portion -- -# gibil.__file__ becomes None and imports work only by accident. All code is -# installed into the venv, so nothing needs the working directory on sys.path. -Environment=PYTHONSAFEPATH=1 - -ExecStart=/srv/astrape/.venv/bin/python -m astrape_oracle.scripts.daemons.weather_forecast_daemon -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target diff --git a/deploy/systemd/astrape-weather-station.service b/deploy/systemd/astrape-weather-station.service deleted file mode 100644 index 43bb67d..0000000 --- a/deploy/systemd/astrape-weather-station.service +++ /dev/null @@ -1,26 +0,0 @@ -[Unit] -Description=Astrape Local Weather Station Ingest -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -User=gibil -Group=gibil -WorkingDirectory=/srv/astrape -Environment=PYTHONUNBUFFERED=1 -Environment=PYTHONDONTWRITEBYTECODE=1 -# WorkingDirectory is /srv/astrape, which also holds the gibil checkout. Without -# this, Python prepends the working directory to sys.path and the repo root -# /srv/astrape/gibil shadows the installed package as a namespace portion -- -# gibil.__file__ becomes None and imports work only by accident. All code is -# installed into the venv, so nothing needs the working directory on sys.path. -Environment=PYTHONSAFEPATH=1 -Environment=ECOWITT_GW3000_HOST=10.24.88.176 -Environment=ECOWITT_GW3000_POLL_SECONDS=60 -ExecStart=/srv/astrape/.venv/bin/python -m astrape_oracle.scripts.daemons.weather_station_daemon -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target diff --git a/pyproject.toml b/pyproject.toml index ebd30f3..d454987 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,5 +9,9 @@ description = "Forecasting runtime: weather ingest, oracle snapshots, TCN traini requires-python = ">=3.12" dependencies = ["gibil", "astrape-ems", "psycopg[binary]>=3.2,<4"] -[tool.setuptools.packages.find] -include = ["astrape_oracle*"] +# Flat layout: this repository *is* the package. package-dir maps astrape_oracle to the +# repository root rather than to a nested astrape_oracle/ directory, so the checkout is +# astrape/astrape-oracle and not astrape/astrape-oracle/astrape_oracle. +[tool.setuptools] +packages = ["astrape_oracle", "astrape_oracle.classes", "astrape_oracle.classes.weather", "astrape_oracle.scripts", "astrape_oracle.scripts.daemons", "astrape_oracle.scripts.debug", "astrape_oracle.scripts.tcn"] +package-dir = {"astrape_oracle" = "."} diff --git a/astrape_oracle/scripts/__init__.py b/scripts/__init__.py similarity index 100% rename from astrape_oracle/scripts/__init__.py rename to scripts/__init__.py diff --git a/astrape_oracle/scripts/daemons/__init__.py b/scripts/daemons/__init__.py similarity index 100% rename from astrape_oracle/scripts/daemons/__init__.py rename to scripts/daemons/__init__.py diff --git a/astrape_oracle/scripts/daemons/oracle_daemon.py b/scripts/daemons/oracle_daemon.py similarity index 100% rename from astrape_oracle/scripts/daemons/oracle_daemon.py rename to scripts/daemons/oracle_daemon.py diff --git a/astrape_oracle/scripts/daemons/weather_forecast_daemon.py b/scripts/daemons/weather_forecast_daemon.py similarity index 100% rename from astrape_oracle/scripts/daemons/weather_forecast_daemon.py rename to scripts/daemons/weather_forecast_daemon.py diff --git a/astrape_oracle/scripts/daemons/weather_station_daemon.py b/scripts/daemons/weather_station_daemon.py similarity index 100% rename from astrape_oracle/scripts/daemons/weather_station_daemon.py rename to scripts/daemons/weather_station_daemon.py diff --git a/astrape_oracle/scripts/debug/__init__.py b/scripts/debug/__init__.py similarity index 100% rename from astrape_oracle/scripts/debug/__init__.py rename to scripts/debug/__init__.py diff --git a/astrape_oracle/scripts/debug/debug_duplicates.py b/scripts/debug/debug_duplicates.py similarity index 100% rename from astrape_oracle/scripts/debug/debug_duplicates.py rename to scripts/debug/debug_duplicates.py diff --git a/astrape_oracle/scripts/debug/debug_energy_forecast.py b/scripts/debug/debug_energy_forecast.py similarity index 100% rename from astrape_oracle/scripts/debug/debug_energy_forecast.py rename to scripts/debug/debug_energy_forecast.py diff --git a/astrape_oracle/scripts/debug/debug_oracle_evaluations.py b/scripts/debug/debug_oracle_evaluations.py similarity index 100% rename from astrape_oracle/scripts/debug/debug_oracle_evaluations.py rename to scripts/debug/debug_oracle_evaluations.py diff --git a/astrape_oracle/scripts/evaluator.py b/scripts/evaluator.py similarity index 100% rename from astrape_oracle/scripts/evaluator.py rename to scripts/evaluator.py diff --git a/astrape_oracle/scripts/tcn/__init__.py b/scripts/tcn/__init__.py similarity index 100% rename from astrape_oracle/scripts/tcn/__init__.py rename to scripts/tcn/__init__.py diff --git a/astrape_oracle/scripts/tcn/schedule.py b/scripts/tcn/schedule.py similarity index 100% rename from astrape_oracle/scripts/tcn/schedule.py rename to scripts/tcn/schedule.py diff --git a/astrape_oracle/scripts/tcn/train.py b/scripts/tcn/train.py similarity index 100% rename from astrape_oracle/scripts/tcn/train.py rename to scripts/tcn/train.py