mirror of https://github.com/DJ2LS/FreeDATA.git
initial changes to pip releases and dependency cleanup
parent
6835390793
commit
7ea4f0796c
|
|
@ -53,12 +53,11 @@ jobs:
|
|||
sudo apt update
|
||||
sudo apt install -y portaudio19-dev libhamlib-dev libhamlib-utils build-essential cmake patchelf
|
||||
|
||||
- name: Install MacOS pyAudio
|
||||
- name: Install MacOS dependencies
|
||||
if: ${{startsWith(matrix.os, 'macos')}}
|
||||
run: |
|
||||
brew install portaudio
|
||||
python -m pip install --upgrade pip
|
||||
pip3 install pyaudio
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
name: Deploy Python Package
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
|
|
@ -17,16 +20,64 @@ jobs:
|
|||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Install Linux dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y portaudio19-dev libhamlib-dev libhamlib-utils build-essential cmake patchelf
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install .[build]
|
||||
|
||||
- name: Set package version from tag
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
python3 - <<'EOF'
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from packaging.version import InvalidVersion, Version
|
||||
|
||||
tag = os.environ["RELEASE_TAG"]
|
||||
version = tag.removeprefix("v")
|
||||
|
||||
if not re.fullmatch(r"\d+\.\d+\.\d+(-[0-9A-Za-z.]+)?", version):
|
||||
print(
|
||||
f"::error::Tag '{tag}' does not look like a release version. "
|
||||
f"Use e.g. v1.2.3, v1.2.3-beta, v1.2.3-rc1 or v1.2.3-alpha.1."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
Version(version)
|
||||
except InvalidVersion:
|
||||
print(
|
||||
f"::error::Tag '{tag}' has an unrecognized pre-release suffix "
|
||||
f"('{version}' is not valid PEP 440). Use a standard suffix such "
|
||||
f"as -alpha, -alpha.1, -beta, -rc1 or -dev."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Releasing version {version} (from tag {tag})")
|
||||
|
||||
path = "freedata_server/constants.py"
|
||||
with open(path) as f:
|
||||
content = f.read()
|
||||
|
||||
new_content, count = re.subn(
|
||||
r'^MODEM_VERSION = .*$',
|
||||
f'MODEM_VERSION = "{version}"',
|
||||
content,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
if count != 1:
|
||||
print("::error::Could not find MODEM_VERSION in freedata_server/constants.py")
|
||||
sys.exit(1)
|
||||
|
||||
with open(path, "w") as f:
|
||||
f.write(new_content)
|
||||
EOF
|
||||
grep "^MODEM_VERSION" freedata_server/constants.py
|
||||
|
||||
- name: Build GUI
|
||||
working-directory: freedata_gui
|
||||
run: |
|
||||
|
|
@ -39,7 +90,7 @@ jobs:
|
|||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@v1.14.0
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
skip-existing: true
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ ARG HAMLIB_VERSION=4.5.5
|
|||
ENV HAMLIB_VERSION=${HAMLIB_VERSION}
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install --upgrade -y fonts-noto-color-emoji git build-essential cmake portaudio19-dev python3-pyaudio python3-colorama wget && \
|
||||
apt-get install --upgrade -y fonts-noto-color-emoji git build-essential cmake portaudio19-dev python3-colorama wget && \
|
||||
mkdir -p /app/FreeDATA
|
||||
|
||||
WORKDIR /src
|
||||
|
|
|
|||
|
|
@ -1,6 +1,32 @@
|
|||
# Module for saving some constants
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def _default_app_dir() -> str:
|
||||
"""
|
||||
Per-user directory for config, database and log file, following each
|
||||
OS's own convention rather than forcing a single layout everywhere:
|
||||
- Windows: %APPDATA%\\FreeDATA
|
||||
- macOS: ~/Library/Application Support/FreeDATA
|
||||
- Linux: $XDG_CONFIG_HOME/FreeDATA or ~/.config/FreeDATA
|
||||
Used only when FREEDATA_CONFIG / FREEDATA_DATABASE are not set (e.g. a
|
||||
plain `pip install freedata` run). Keeping this outside the installed
|
||||
package directory means it survives package upgrades/reinstalls.
|
||||
"""
|
||||
home = os.path.expanduser("~")
|
||||
if sys.platform == "win32":
|
||||
base = os.getenv("APPDATA") or home
|
||||
elif sys.platform == "darwin":
|
||||
base = os.path.join(home, "Library", "Application Support")
|
||||
else:
|
||||
base = os.getenv("XDG_CONFIG_HOME") or os.path.join(home, ".config")
|
||||
return os.path.join(base, "FreeDATA")
|
||||
|
||||
|
||||
CONFIG_ENV_VAR = "FREEDATA_CONFIG"
|
||||
DEFAULT_CONFIG_FILE = "config.ini"
|
||||
DEFAULT_APP_DIR = _default_app_dir()
|
||||
MODEM_VERSION = "0.18.1"
|
||||
API_VERSION = 4
|
||||
ARQ_PROTOCOL_VERSION = 1
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from freedata_server.message_system_db_model import Base, Config, Station, Statu
|
|||
import structlog
|
||||
from freedata_server import helpers
|
||||
import os
|
||||
from freedata_server.constants import MESSAGE_SYSTEM_DATABASE_VERSION
|
||||
from freedata_server.constants import MESSAGE_SYSTEM_DATABASE_VERSION, DEFAULT_APP_DIR
|
||||
|
||||
|
||||
class DatabaseManager:
|
||||
|
|
@ -42,18 +42,19 @@ class DatabaseManager:
|
|||
This method determines the database file path based on the
|
||||
environment variable `FREEDATA_DATABASE`. If the variable is set,
|
||||
its value is used as the path. Otherwise, it defaults to
|
||||
`freedata-messages.db` in the script directory.
|
||||
`freedata-messages.db` in the per-user app directory
|
||||
(DEFAULT_APP_DIR), so a plain `pip install` keeps the database
|
||||
outside the installed package and it survives upgrades.
|
||||
|
||||
Returns:
|
||||
str: The database file path as a SQLAlchemy URL.
|
||||
"""
|
||||
script_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
if self.DATABASE_ENV_VAR in os.environ:
|
||||
# db_path = os.getenv(self.DATABASE_ENV_VAR, os.path.join(script_directory, self.DEFAULT_DATABASE_FILE))
|
||||
db_path = os.getenv(self.DATABASE_ENV_VAR)
|
||||
else:
|
||||
db_path = os.path.join(script_directory, self.DEFAULT_DATABASE_FILE)
|
||||
db_path = os.path.join(DEFAULT_APP_DIR, self.DEFAULT_DATABASE_FILE)
|
||||
|
||||
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
||||
return "sqlite:///" + db_path
|
||||
|
||||
def initialize_default_values(self):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import threading
|
||||
|
|
@ -10,7 +11,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from freedata_server.log_handler import setup_logging
|
||||
from freedata_server.constants import CONFIG_ENV_VAR, DEFAULT_CONFIG_FILE, API_VERSION
|
||||
from freedata_server.constants import CONFIG_ENV_VAR, DEFAULT_CONFIG_FILE, DEFAULT_APP_DIR, API_VERSION
|
||||
from freedata_server.context import AppContext
|
||||
|
||||
from freedata_server.api.general import router as general_router
|
||||
|
|
@ -27,18 +28,39 @@ import uvicorn
|
|||
# --- Resolve config path FIRST (no logger needed yet) ---
|
||||
def resolve_config_path() -> str:
|
||||
"""
|
||||
Determine the configuration file to use (env var or default next to this file).
|
||||
Exits if not found.
|
||||
Determine the configuration file to use.
|
||||
|
||||
Uses FREEDATA_CONFIG if set, otherwise defaults to a per-user config
|
||||
directory (DEFAULT_APP_DIR). If no config file exists yet at that
|
||||
location, a fresh one is bootstrapped from the bundled
|
||||
config.ini.example template so a plain `pip install freedata` followed
|
||||
by `freedata` works out of the box without any manual setup.
|
||||
"""
|
||||
candidate = os.getenv(
|
||||
CONFIG_ENV_VAR,
|
||||
os.path.join(os.path.dirname(__file__), DEFAULT_CONFIG_FILE),
|
||||
candidate = os.path.abspath(
|
||||
os.getenv(
|
||||
CONFIG_ENV_VAR,
|
||||
os.path.join(DEFAULT_APP_DIR, DEFAULT_CONFIG_FILE),
|
||||
)
|
||||
)
|
||||
|
||||
if not os.path.exists(candidate):
|
||||
# We cannot log to file yet since we don't know the directory; write to stderr.
|
||||
sys.stderr.write(f"[FATAL] Config file not found: {candidate}\n")
|
||||
sys.exit(1)
|
||||
return os.path.abspath(candidate)
|
||||
template = os.path.join(os.path.dirname(__file__), "config.ini.example")
|
||||
try:
|
||||
os.makedirs(os.path.dirname(candidate), exist_ok=True)
|
||||
if os.path.isfile(template):
|
||||
shutil.copyfile(template, candidate)
|
||||
sys.stderr.write(f"[INFO] No config found - created a default one at: {candidate}\n")
|
||||
else:
|
||||
sys.stderr.write(
|
||||
f"[FATAL] Config file not found and no template available to create one: {candidate}\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
except OSError as e:
|
||||
sys.stderr.write(f"[FATAL] Could not create config file at {candidate}: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
return candidate
|
||||
|
||||
|
||||
config_file = resolve_config_path()
|
||||
|
|
@ -95,11 +117,15 @@ async def nocache(request: Request, call_next):
|
|||
|
||||
|
||||
# Static GUI mounting
|
||||
# Order matters: prefer paths anchored to this file's location (work no
|
||||
# matter what the current working directory is) over cwd-relative
|
||||
# fallbacks kept for backwards compatibility with older layouts.
|
||||
potential_gui_dirs = [
|
||||
os.path.join(os.path.dirname(__file__), "gui"), # nuitka standalone build
|
||||
os.path.join(os.path.dirname(os.path.dirname(__file__)), "freedata_gui", "dist"), # pip install (sibling package)
|
||||
"../freedata_gui/dist",
|
||||
"freedata_gui/dist",
|
||||
"FreeDATA/freedata_gui/dist",
|
||||
os.path.join(os.path.dirname(__file__), "gui"),
|
||||
]
|
||||
gui_dir = next((d for d in potential_gui_dirs if os.path.isdir(d)), None)
|
||||
if gui_dir:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ requires-python = ">=3.10"
|
|||
dependencies = [
|
||||
"numpy",
|
||||
"psutil",
|
||||
"PyAudio",
|
||||
"pyserial",
|
||||
"sounddevice",
|
||||
"structlog",
|
||||
|
|
@ -78,12 +77,13 @@ nuitka = [
|
|||
|
||||
[tool.setuptools.packages.find]
|
||||
where = [ "." ]
|
||||
exclude = [
|
||||
"tools*",
|
||||
include = [
|
||||
"freedata_server*",
|
||||
"freedata_gui",
|
||||
]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
freedata_server = [ "lib/**/*" ]
|
||||
freedata_server = [ "lib/**/*", "config.ini.example" ]
|
||||
freedata_gui = [ "dist/**/*" ]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
numpy
|
||||
psutil
|
||||
PyAudio
|
||||
pyserial
|
||||
sounddevice
|
||||
structlog
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@
|
|||
#
|
||||
#
|
||||
# Changelog:
|
||||
# 2.10: 24 Jul 2026
|
||||
# Remove python3-pyaudio (unused dependency, FreeDATA uses sounddevice)
|
||||
#
|
||||
# 2.9: 10 Jan Sep 2026
|
||||
# Add Ubuntu 24.10 and 25.04
|
||||
# Change hamlib default version to 4.6.5
|
||||
|
|
@ -164,7 +167,7 @@ case $osname in
|
|||
"Debian GNU/Linux")
|
||||
case $osversion in
|
||||
"11" | "12" | "13")
|
||||
sudo apt install --upgrade -y fonts-noto-color-emoji git build-essential cmake python3 portaudio19-dev python3-pyaudio python3-pip python3-colorama python3-venv wget python3-dev
|
||||
sudo apt install --upgrade -y fonts-noto-color-emoji git build-essential cmake python3 portaudio19-dev python3-pip python3-colorama python3-venv wget python3-dev
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
@ -182,7 +185,7 @@ case $osname in
|
|||
"Ubuntu" | "Linux Mint")
|
||||
case $osversion in
|
||||
"21.3" | "22.04" | "24.04" | "24.10" | "25.04" )
|
||||
sudo apt install --upgrade -y fonts-noto-color-emoji git build-essential cmake python3 portaudio19-dev python3-pyaudio python3-pip python3-colorama python3-venv wget python3-dev
|
||||
sudo apt install --upgrade -y fonts-noto-color-emoji git build-essential cmake python3 portaudio19-dev python3-pip python3-colorama python3-venv wget python3-dev
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
@ -197,7 +200,7 @@ case $osname in
|
|||
"Fedora Linux")
|
||||
case $osversion in
|
||||
"VERSION_ID=40" | "VERSION_ID=41")
|
||||
sudo dnf install -y git cmake make automake gcc gcc-c++ kernel-devel wget portaudio-devel python3-pyaudio python3-pip python3-colorama python3-virtualenv google-noto-emoji-fonts python3-devel
|
||||
sudo dnf install -y git cmake make automake gcc gcc-c++ kernel-devel wget portaudio-devel python3-pip python3-colorama python3-virtualenv google-noto-emoji-fonts python3-devel
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue