Skip to content

Latest commit

 

History

History
459 lines (318 loc) · 10.2 KB

File metadata and controls

459 lines (318 loc) · 10.2 KB

Development Guide

This guide explains how to set up a local FluxTuner development environment, run the app, execute tests, and validate changes before opening a pull request.

Requirements

FluxTuner is a Python application with CLI, TUI, and optional GTK GUI entry points.

Recommended local tools:

  • Python 3.11 or newer.
  • pip.
  • venv.
  • mpv and/or ffplay for manual playback testing.
  • Git.
  • Optional: Flatpak tooling if you work on packaging.

The CI currently validates supported Python versions, package builds, dependency audits, static security checks, and tests.

Clone the repository

git clone https://github.com/pitill0/fluxtuner.git
cd fluxtuner

Create a virtual environment

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip

On Windows PowerShell:

python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip

Install development dependencies

Install FluxTuner in editable mode with development dependencies:

python -m pip install -e ".[dev]"

If you only want to install runtime dependencies:

python -m pip install -e .

Run FluxTuner locally

Default TUI:

python -m fluxtuner

Legacy CLI:

python -m fluxtuner --cli

Experimental GTK GUI:

python -m fluxtuner --gui

List player backends:

python -m fluxtuner --list-players

List available themes:

python -m fluxtuner --list-themes

Run with debug logging:

python -m fluxtuner --verbose

or:

FLUXTUNER_DEBUG=1 python -m fluxtuner

Debug logs are intended for development and diagnostics. They should not expose stream URLs, station names, full local paths, imported data contents, or unnecessary user data.

Player backends

FluxTuner supports external player backends such as:

  • mpv
  • ffplay

Install at least one backend locally for manual playback testing.

Examples:

sudo apt install mpv

or:

sudo apt install ffmpeg

ffplay is usually provided by FFmpeg packages.

The automated test suite mocks player execution and should not require mpv or ffplay to be installed.

Project structure

Commonly edited areas:

fluxtuner/
  __main__.py              CLI entry point and import/export commands
  config.py                User configuration and playback state
  logging_config.py        Project logging configuration
  paths.py                 XDG/user data path helpers
  theme_runtime.py         Runtime theme application helpers

fluxtuner/core/
  api.py                   Radio Browser API integration
  cache.py                 Search cache
  data_usage.py            Playback data usage tracking
  favorites.py             Favorites persistence and updates
  history.py               Playback history
  importers.py             Import validation for favorites/playlists
  manual_playlists.py      User-managed playlists
  playlists.py             Built-in playlist/tag helpers
  stations.py              Station normalization helpers
  storage.py               Atomic JSON writes
  stream_metadata.py       ICY stream metadata parsing

fluxtuner/players/
  base.py                  Player interface and errors
  ffplay.py                ffplay backend
  mpv.py                   mpv backend
  security.py              Player executable and stream URL validation

fluxtuner/gui/
  app.py                   GTK GUI entry point
  window.py                GTK GUI window

tests/
  test_*.py                Unit and regression tests

Local validation commands

Before opening a pull request, run the same core checks used in CI.

Formatting and linting

ruff check .
ruff format --check .

To apply formatting:

ruff format .

Compile check

python -m compileall fluxtuner tests

Tests

python -m pytest

Run a focused subset while developing:

python -m pytest tests/test_api.py
python -m pytest tests/test_main.py
python -m pytest tests/test_players_mpv.py tests/test_players_ffplay.py

Build package

python -m build

Dependency audit

Run this from a clean virtual environment to avoid auditing unrelated system packages:

python -m pip install pip-audit
pip-audit --local

Expected note for editable local installs:

fluxtuner Dependency not found on PyPI and could not be audited

That is expected because the local project itself is not a published PyPI dependency. The important result is that no known vulnerabilities are found in installed dependencies.

Static security analysis

bandit -r fluxtuner -c pyproject.toml

Bandit scans production code only. Subprocess-related skips are limited to the external player backends, which intentionally launch mpv or ffplay.

Full local check

A useful pre-PR sequence:

ruff check .
ruff format --check .
python -m compileall fluxtuner tests
python -m pytest
python -m build
pip-audit --local
bandit -r fluxtuner -c pyproject.toml

Working with branches and pull requests

Recommended workflow:

git checkout main
git pull
git checkout -b area/short-description

Make focused changes, then run validation.

Commit message examples:

git commit -m "Validate imported favorites and playlists"
git commit -m "Add Bandit security analysis to CI"
git commit -m "Add persistence error logging"

Push and open a PR:

git push -u origin area/short-description

A good PR should include:

  • Summary of what changed.
  • Validation commands run locally.
  • Linked issue, for example Closes #15 or Part of #20.
  • Notes about scope or intentional follow-up work.

Testing guidelines

Prefer small, focused tests that cover behavior rather than implementation details.

Good candidates for tests:

  • URL validation.
  • Import validation.
  • Atomic persistence.
  • Error handling and fallback behavior.
  • Player command construction without requiring real player binaries.
  • Radio Browser API failure handling.
  • ICY metadata parsing limits.
  • Runtime theme parsing and application.

Avoid tests that depend on:

  • A real network call.
  • Installed player binaries.
  • User-specific local paths.
  • A specific terminal size, unless isolated/mocked.
  • GUI availability unless the test is explicitly marked or isolated as a smoke test.

Logging guidelines

FluxTuner uses opt-in debug logging through:

python -m fluxtuner --verbose

or:

FLUXTUNER_DEBUG=1 python -m fluxtuner

When adding logs:

  • Use get_logger(__name__).
  • Prefer debug for diagnostic details.
  • Use warning or error when a fallback or failure matters operationally.
  • Avoid logging stream URLs.
  • Avoid logging station names unless there is a strong reason.
  • Avoid logging full local paths.
  • Avoid logging imported/exported data contents.
  • Use exc_info=True for debugging exceptions when useful.

Example:

from fluxtuner.logging_config import get_logger

logger = get_logger(__name__)

try:
    ...
except OSError:
    logger.warning("Could not read favorites data; returning empty favorites", exc_info=True)
    return []

Security guidelines

Security-sensitive areas include:

  • Player subprocess execution.
  • Stream URL validation.
  • Imported JSON files.
  • Local user data persistence.
  • ICY stream metadata parsing.
  • Dependency updates.
  • Packaging and Flatpak permissions.

When changing these areas:

  • Keep validation explicit.
  • Avoid broad exception swallowing without logs.
  • Avoid shell=True.
  • Do not pass unvalidated URLs to player backends.
  • Keep local writes atomic where possible.
  • Add tests for failure paths.
  • Run Bandit and dependency audit before opening a PR.

See also:

SECURITY.md

Import/export notes

Favorites and playlists can be imported/exported as JSON from the CLI.

Exports should preserve user data.

Imports should validate incoming structures before persisting them. Invalid items should be skipped, and imports with no valid items should fail safely.

Relevant commands:

python -m fluxtuner --export-favs favorites.json
python -m fluxtuner --import-favs favorites.json
python -m fluxtuner --export-playlists playlists.json
python -m fluxtuner --import-playlists playlists.json

Runtime theme notes

FluxTuner themes are TCSS files.

At startup, Textual loads the selected theme directly. At runtime, FluxTuner also supports applying a practical subset of TCSS declarations without relying on Textual development CSS watching.

Runtime theme support intentionally parses only a limited subset:

  • Supported selectors are listed in fluxtuner/theme_runtime.py.
  • Variables such as $surface are ignored at runtime.
  • Unsupported selectors are ignored.
  • Unsupported style properties are logged at debug level and skipped.

Flatpak notes

Flatpak work may require additional local tooling.

The exact Flatpak workflow depends on the manifest and packaging setup. If you work on Flatpak permissions or packaging, validate the package manually in addition to normal Python checks.

Troubleshooting

pip-audit --local reports unrelated system packages

Make sure your virtual environment is active:

which python
which pip
which pip-audit

If the audit reports unrelated packages such as system tools, recreate a clean virtual environment and reinstall the project:

rm -rf .venv
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m pip install pip-audit
pip-audit --local

Player tests fail because mpv or ffplay is missing

Automated tests should mock player executable resolution. If a test requires real player binaries, adjust the test to mock:

monkeypatch.setattr("fluxtuner.players.mpv.resolve_executable", lambda _name: "/usr/bin/mpv")
monkeypatch.setattr("fluxtuner.players.ffplay.resolve_executable", lambda _name: "/usr/bin/ffplay")

Logs are not visible

Enable debug logging:

python -m fluxtuner --verbose

or:

FLUXTUNER_DEBUG=1 python -m fluxtuner

Runtime theme changes do not apply as expected

Check that the selector and property are supported by fluxtuner/theme_runtime.py.

Runtime theme application is intentionally limited and may not support every TCSS feature.