mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-11 05:44:30 +00:00
rename: implement advertised backward-compat + prune dead community plugins
Address gaps where PR #537's "Backward compatibility" section was advertised but not implemented, and clean up the community plugin list. Env vars (FEEDBACK_* canonical, legacy SLOPSMITH_* honoured): - New lib/env_compat.py (getenv_compat / env_flag_compat) + tests. server.py (_env_flag + all FEEDBACK_* reads), diagnostics_hardware, gp2midi and tailwind_rebuild now resolve the legacy alias, so existing SLOPSMITH_UI / SLOPSMITH_PLUGINS_DIR / etc. deployments keep working. - Fix the rename collapsing plugins/__init__.py and minigames/routes.py from `FEEDBACK_PLUGINS_DIR or SLOPSMITH_PLUGINS_DIR` into a redundant `FEEDBACK_ or FEEDBACK_` (the fallback was silently lost). Storage (app.js update-channel): - Read feedBack-update-channel, fall back to legacy slopsmith-update-channel, and clear the legacy key on write — so a user's update-channel preference survives the rename instead of resetting to "stable". Community plugin list (README): the rename rewrote third-party repo URLs we don't own. Probed every one; their owners never renamed, so: - Restore the 13 live community plugins to their real slopsmith-* names. - Prune 6 that are 404 to the public (topkoa splitscreen/stems, OmikronApex tuner, Jafz2001 nam-rig-builder, DeathlySin song-preview, Erikcb91 shuffle). - Fix a pre-existing Guitar Theory clone-command typo (nam-tone -> guitar-theory). Verified: env_compat 7/7, JS 819/819, pytest 1690 collected / 0 import errors, rename-sensitive + startup suites green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1cf3dcba67
commit
932c0b28ac
@@ -15,34 +15,28 @@
|
|||||||
| [MIDI Amp Control](https://github.com/got-feedback/feedBack-plugin-midi) | Auto-switch amp/modeler presets via MIDI on tone changes | `git clone ...feedBack-plugin-midi.git midi_amp` |
|
| [MIDI Amp Control](https://github.com/got-feedback/feedBack-plugin-midi) | Auto-switch amp/modeler presets via MIDI on tone changes | `git clone ...feedBack-plugin-midi.git midi_amp` |
|
||||||
| [Section Map](https://github.com/got-feedback/feedBack-plugin-sectionmap) | Color-coded song structure minimap with clickable navigation | `git clone ...feedBack-plugin-sectionmap.git section_map` |
|
| [Section Map](https://github.com/got-feedback/feedBack-plugin-sectionmap) | Color-coded song structure minimap with clickable navigation | `git clone ...feedBack-plugin-sectionmap.git section_map` |
|
||||||
| [Arrangement Editor](https://github.com/got-feedback/feedBack-plugin-editor) | DAW-like visual editor for creating and editing song note charts | `git clone ...feedBack-plugin-editor.git editor` |
|
| [Arrangement Editor](https://github.com/got-feedback/feedBack-plugin-editor) | DAW-like visual editor for creating and editing song note charts | `git clone ...feedBack-plugin-editor.git editor` |
|
||||||
| [MIDI Capo](https://github.com/masc0t/feedBack-plugin-midi-capo) | MIDI capo control for real-time transposition | `git clone ...feedBack-plugin-midi-capo.git midi_capo` |
|
| [MIDI Capo](https://github.com/masc0t/slopsmith-plugin-midi-capo) | MIDI capo control for real-time transposition | `git clone ...slopsmith-plugin-midi-capo.git midi_capo` |
|
||||||
| [Note Detection](https://github.com/got-feedback/feedBack-plugin-notedetect) | Real-time pitch detection and scoring against highway notes | `git clone ...feedBack-plugin-notedetect.git note_detect` |
|
| [Note Detection](https://github.com/got-feedback/feedBack-plugin-notedetect) | Real-time pitch detection and scoring against highway notes | `git clone ...feedBack-plugin-notedetect.git note_detect` |
|
||||||
| [Find More](https://github.com/masc0t/feedBack-plugin-find-more) | Search for more songs by the same artist | `git clone ...feedBack-plugin-find-more.git find_more` |
|
| [Find More](https://github.com/masc0t/slopsmith-plugin-find-more) | Search for more songs by the same artist | `git clone ...slopsmith-plugin-find-more.git find_more` |
|
||||||
| [Piano Highway](https://github.com/got-feedback/feedBack-plugin-piano) | Scrolling piano/keyboard view for Keys arrangements with MIDI input | `git clone ...feedBack-plugin-piano.git piano` |
|
| [Piano Highway](https://github.com/got-feedback/feedBack-plugin-piano) | Scrolling piano/keyboard view for Keys arrangements with MIDI input | `git clone ...feedBack-plugin-piano.git piano` |
|
||||||
| [Studio](https://github.com/got-feedback/feedBack-plugin-studio) | Collaborative band recording and multi-track mixing | `git clone ...feedBack-plugin-studio.git studio` |
|
| [Studio](https://github.com/got-feedback/feedBack-plugin-studio) | Collaborative band recording and multi-track mixing | `git clone ...feedBack-plugin-studio.git studio` |
|
||||||
| [Drum Highway](https://github.com/got-feedback/feedBack-plugin-drums) | Lane-based drum highway with MIDI drum pad input and built-in sounds | `git clone ...feedBack-plugin-drums.git drums` |
|
| [Drum Highway](https://github.com/got-feedback/feedBack-plugin-drums) | Lane-based drum highway with MIDI drum pad input and built-in sounds | `git clone ...feedBack-plugin-drums.git drums` |
|
||||||
| [Split Screen](https://github.com/topkoa/feedBack-plugin-splitscreen) | 2-4 highway panels side-by-side for multi-arrangement practice | `git clone ...feedBack-plugin-splitscreen.git splitscreen` |
|
| [Invert Highway](https://github.com/masc0t/slopsmith-plugin-invert-highway) | Flip the highway note direction | `git clone ...slopsmith-plugin-invert-highway.git invert_highway` |
|
||||||
| [Stems Mixer](https://github.com/topkoa/feedBack-plugin-stems) | Per-stem mute/volume controls for .sloppak songs | `git clone ...feedBack-plugin-stems.git stems` |
|
| [Jumping Tab](https://github.com/renanboni/slopsmith-plugin-jumpingtab) | Yousician-style 2D horizontal tab with trajectory arcs and hopping ball | `git clone ...slopsmith-plugin-jumpingtab.git jumpingtab` |
|
||||||
| [Invert Highway](https://github.com/masc0t/feedBack-plugin-invert-highway) | Flip the highway note direction | `git clone ...feedBack-plugin-invert-highway.git invert_highway` |
|
|
||||||
| [Jumping Tab](https://github.com/renanboni/feedBack-plugin-jumpingtab) | Yousician-style 2D horizontal tab with trajectory arcs and hopping ball | `git clone ...feedBack-plugin-jumpingtab.git jumpingtab` |
|
|
||||||
| [Step Mode](https://github.com/got-feedback/feedBack-plugin-stepmode) | Step-by-step practice mode — highway freezes at each note until played (via Note Detection) or Space | `git clone ...feedBack-plugin-stepmode.git step_mode` |
|
| [Step Mode](https://github.com/got-feedback/feedBack-plugin-stepmode) | Step-by-step practice mode — highway freezes at each note until played (via Note Detection) or Space | `git clone ...feedBack-plugin-stepmode.git step_mode` |
|
||||||
| [Lyrics Sync](https://github.com/got-feedback/feedBack-plugin-lyrics-sync) | Generate synced LRC lyrics from text + vocals stem via Whisper alignment | `git clone ...feedBack-plugin-lyrics-sync.git lyrics_sync` |
|
| [Lyrics Sync](https://github.com/got-feedback/feedBack-plugin-lyrics-sync) | Generate synced LRC lyrics from text + vocals stem via Whisper alignment | `git clone ...feedBack-plugin-lyrics-sync.git lyrics_sync` |
|
||||||
| [Lyrics Karaoke](https://github.com/got-feedback/feedBack-plugin-lyrics-karaoke) | Per-syllable karaoke pitch ribbon for sloppak songs (Whisper alignment + librosa pYIN) | `git clone ...feedBack-plugin-lyrics-karaoke.git lyrics_karaoke` |
|
| [Lyrics Karaoke](https://github.com/got-feedback/feedBack-plugin-lyrics-karaoke) | Per-syllable karaoke pitch ribbon for sloppak songs (Whisper alignment + librosa pYIN) | `git clone ...feedBack-plugin-lyrics-karaoke.git lyrics_karaoke` |
|
||||||
| [NAM Tone Engine](https://github.com/got-feedback/feedBack-plugin-nam-tone) | In-browser amp modeling with NAM WASM, cabinet IRs, tone auto-switching | `git clone ...feedBack-plugin-nam-tone.git nam_tone` |
|
| [NAM Tone Engine](https://github.com/got-feedback/feedBack-plugin-nam-tone) | In-browser amp modeling with NAM WASM, cabinet IRs, tone auto-switching | `git clone ...feedBack-plugin-nam-tone.git nam_tone` |
|
||||||
| [Guitar Theory Lab](https://github.com/topkoa/feedBack-plugin-guitar-theory) | Explore scales, chords, intervals, tunings, and voicings on a fully interactive fretboard | `git clone ...feedBack-plugin-nam-tone.git guitar-theory-lab` |
|
| [Guitar Theory Lab](https://github.com/topkoa/slopsmith-plugin-guitar-theory) | Explore scales, chords, intervals, tunings, and voicings on a fully interactive fretboard | `git clone ...slopsmith-plugin-guitar-theory.git guitar-theory-lab` |
|
||||||
| [Themes](https://github.com/masc0t/feedBack-plugin-themes) | Offers several basic recolorings of the interface | `git clone ...feedBack-plugin-themes.git themes` |
|
| [Themes](https://github.com/masc0t/slopsmith-plugin-themes) | Offers several basic recolorings of the interface | `git clone ...slopsmith-plugin-themes.git themes` |
|
||||||
| [Update Manager](https://github.com/masc0t/feedBack-update-manager) | Installs, updates, and uninstalls other plugins and the feedBack core itself | `git clone ...feedBack-update-manager.git update_manager` |
|
| [Update Manager](https://github.com/masc0t/slopsmith-update-manager) | Installs, updates, and uninstalls other plugins and the feedBack core itself | `git clone ...slopsmith-update-manager.git update_manager` |
|
||||||
| [Tuner](https://github.com/OmikronApex/feedBack-plugin-tuner) | Floating tuner with customizable tunings | `git clone ...feedBack-plugin-tuner.git tuner` |
|
| [Simplify Chords](https://github.com/bkranendonk/slopsmith-plugin-simplify-chords) | Changes complex chords on the note highway to simpler ones. Inspired by Ultimate Guitar's Simplify button. | `git clone ...slopsmith-plugin-simplify-chords.git simplify-chords` |
|
||||||
| [Simplify Chords](https://github.com/bkranendonk/feedBack-plugin-simplify-chords) | Changes complex chords on the note highway to simpler ones. Inspired by Ultimate Guitar's Simplify button. | `git clone ...feedBack-plugin-simplify-chords.git simplify-chords` |
|
| [Key Bindings](https://github.com/jackipicco/slopsmith-plugin-key-bindings) | Highway key bindings for keyboard and TV remote | `git clone ...slopsmith-plugin-key-bindings.git key_bindings` |
|
||||||
| [Key Bindings](https://github.com/jackipicco/feedBack-plugin-key-bindings) | Highway key bindings for keyboard and TV remote | `git clone ...feedBack-plugin-key-bindings.git key_bindings` |
|
| [Folder Organizer](https://github.com/Elit3d/slopsmith-plugin-folder-organizer) | Organize your sloppak DLC songs into a folder tree view, grouped by subfolder name | `git clone ...slopsmith-plugin-folder-organizer.git folder-organizer` |
|
||||||
| [Folder Organizer](https://github.com/Elit3d/feedBack-plugin-folder-organizer) | Organize your sloppak DLC songs into a folder tree view, grouped by subfolder name | `git clone ...feedBack-plugin-folder-organizer.git folder-organizer` |
|
|
||||||
| [Virtuoso](https://github.com/got-feedback/feedback-plugin-virtuoso) | Practice studio for guitar & bass — scale, technique, and rhythm drills, timed workouts, and jam backing that teach skills you take off the screen. | `git clone ...feedback-plugin-virtuoso.git virtuoso` |
|
| [Virtuoso](https://github.com/got-feedback/feedback-plugin-virtuoso) | Practice studio for guitar & bass — scale, technique, and rhythm drills, timed workouts, and jam backing that teach skills you take off the screen. | `git clone ...feedback-plugin-virtuoso.git virtuoso` |
|
||||||
| [NAM Rig Builder](https://github.com/Jafz2001/feedBack-plugin-nam-rig-builder) | Map tones to chained NAM neural-amp rigs (tone3000 captures + IRs) — full pedal→amp→cab playback, per-stage bypass, and a gear catalog | `git clone ...feedBack-plugin-nam-rig-builder.git nam_rig_builder` |
|
| [Audio Preview](https://github.com/saleemk/slopsmith-plugin-audio-preview) | Quick audio previews from library cards with configurable start time, volume, and duration | `git clone ...slopsmith-plugin-audio-preview.git audio_preview` |
|
||||||
| [Audio Preview](https://github.com/saleemk/feedBack-plugin-audio-preview) | Quick audio previews from library cards with configurable start time, volume, and duration | `git clone ...feedBack-plugin-audio-preview.git audio_preview` |
|
| [Song Mastery](https://github.com/jamesgaiser/slopsmith-plugin-song-mastery) | Auto-adjusts difficulty based on your rolling note accuracy and saves the slider position per song | `git clone ...slopsmith-plugin-song-mastery.git song_mastery` |
|
||||||
| [Song Mastery](https://github.com/jamesgaiser/feedBack-plugin-song-mastery) | Auto-adjusts difficulty based on your rolling note accuracy and saves the slider position per song | `git clone ...feedBack-plugin-song-mastery.git song_mastery` |
|
| [Mobile Note Highway](https://github.com/saleemk/slopsmith-plugin-mobile-note-highway) | Touch-optimized player with collapsible controls, highway gestures, and device-adaptive layouts for phones and tablets | `git clone ...slopsmith-plugin-mobile-note-highway.git mobile_note_highway` |
|
||||||
| [Song Preview](https://github.com/DeathlySin/feedBack-plugin-song-preview) | Quickly hear previews of songs in your library with a clean visual indicator of what's playing. Supports .sloppak and loose folders song formats, with the visual indicator matching up to whatever theme you are using! | `git clone ...feedBack-plugin-song-preview.git song_preview` |
|
|
||||||
| [Mobile Note Highway](https://github.com/saleemk/feedBack-plugin-mobile-note-highway) | Touch-optimized player with collapsible controls, highway gestures, and device-adaptive layouts for phones and tablets | `git clone ...feedBack-plugin-mobile-note-highway.git mobile_note_highway` |
|
|
||||||
| [Shuffle](https://github.com/Erikcb91/FeedBack-Shuffle-Mode) | Random playback from your library — artist & tuning filters, auto-advance with countdown popup, note_detect compatible | `git clone https://github.com/Erikcb91/FeedBack-Shuffle-Mode.git shuffle` |
|
|
||||||
|
|
||||||
Install any plugin by cloning it into your `plugins/` directory and restarting:
|
Install any plugin by cloning it into your `plugins/` directory and restarting:
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import platform
|
|||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from env_compat import getenv_compat
|
||||||
|
|
||||||
SCHEMA = "system.hardware.v1"
|
SCHEMA = "system.hardware.v1"
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ def detect_runtime() -> dict:
|
|||||||
nvidia-smi / psutil CPU probes.
|
nvidia-smi / psutil CPU probes.
|
||||||
"""
|
"""
|
||||||
out: dict = {"kind": "bare", "in_docker": False, "in_kubernetes": False}
|
out: dict = {"kind": "bare", "in_docker": False, "in_kubernetes": False}
|
||||||
env_runtime = os.environ.get("FEEDBACK_RUNTIME", "").strip().lower()
|
env_runtime = (getenv_compat("FEEDBACK_RUNTIME", "") or "").strip().lower()
|
||||||
if env_runtime in ("electron", "docker", "bare"):
|
if env_runtime in ("electron", "docker", "bare"):
|
||||||
out["kind"] = env_runtime
|
out["kind"] = env_runtime
|
||||||
if Path("/.dockerenv").exists():
|
if Path("/.dockerenv").exists():
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"""Backward-compatible environment lookup for the slopsmith -> feedBack rename.
|
||||||
|
|
||||||
|
Canonical configuration variables are now ``FEEDBACK_*``. Deployments that
|
||||||
|
predate the rename may still set the old ``SLOPSMITH_*`` names (docker-compose
|
||||||
|
overrides, shell profiles, CI), so we honour those as a fallback. New code
|
||||||
|
should always read the canonical ``FEEDBACK_*`` name and let this shim resolve
|
||||||
|
the legacy alias.
|
||||||
|
|
||||||
|
Flat-importable, no import-time IO or global state (constitution P-V).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
_CANON_PREFIX = "FEEDBACK_"
|
||||||
|
_LEGACY_PREFIX = "SLOPSMITH_"
|
||||||
|
_TRUE_VALUES = {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
|
|
||||||
|
def getenv_compat(name, default=None):
|
||||||
|
"""``os.environ.get`` with a legacy ``SLOPSMITH_*`` fallback.
|
||||||
|
|
||||||
|
For a canonical ``FEEDBACK_<X>`` name, returns the value of ``FEEDBACK_<X>``
|
||||||
|
if set, else ``SLOPSMITH_<X>`` if set, else ``default``. Names that do not
|
||||||
|
start with ``FEEDBACK_`` behave exactly like ``os.environ.get``.
|
||||||
|
"""
|
||||||
|
value = os.environ.get(name)
|
||||||
|
if value is not None:
|
||||||
|
return value
|
||||||
|
if name.startswith(_CANON_PREFIX):
|
||||||
|
legacy = os.environ.get(_LEGACY_PREFIX + name[len(_CANON_PREFIX):])
|
||||||
|
if legacy is not None:
|
||||||
|
return legacy
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def env_flag_compat(name):
|
||||||
|
"""Parse a conventional boolean env flag, honouring the legacy alias."""
|
||||||
|
return (getenv_compat(name, "") or "").strip().lower() in _TRUE_VALUES
|
||||||
+3
-1
@@ -8,6 +8,8 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from env_compat import getenv_compat
|
||||||
|
|
||||||
log = logging.getLogger("feedBack.lib.gp2midi")
|
log = logging.getLogger("feedBack.lib.gp2midi")
|
||||||
|
|
||||||
import guitarpro
|
import guitarpro
|
||||||
@@ -156,7 +158,7 @@ def _find_soundfont() -> str | None:
|
|||||||
2. Bundled ``<RESOURCESPATH>/soundfonts/*.sf2`` (Electron desktop builds)
|
2. Bundled ``<RESOURCESPATH>/soundfonts/*.sf2`` (Electron desktop builds)
|
||||||
3. Common system locations per OS.
|
3. Common system locations per OS.
|
||||||
"""
|
"""
|
||||||
override = os.environ.get("FEEDBACK_SOUNDFONT")
|
override = getenv_compat("FEEDBACK_SOUNDFONT")
|
||||||
if override:
|
if override:
|
||||||
if os.path.isfile(override):
|
if os.path.isfile(override):
|
||||||
return override
|
return override
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import tempfile
|
|||||||
import threading
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from env_compat import getenv_compat
|
||||||
|
|
||||||
log = logging.getLogger("feedBack.tailwind")
|
log = logging.getLogger("feedBack.tailwind")
|
||||||
|
|
||||||
# Pin matches scripts/build-tailwind.sh and the Dockerfile build stage so every
|
# Pin matches scripts/build-tailwind.sh and the Dockerfile build stage so every
|
||||||
@@ -45,7 +47,7 @@ APP_DIR = Path(__file__).resolve().parent.parent
|
|||||||
|
|
||||||
|
|
||||||
def _user_plugins_dir() -> Path | None:
|
def _user_plugins_dir() -> Path | None:
|
||||||
raw = os.environ.get("FEEDBACK_PLUGINS_DIR", "").strip()
|
raw = (getenv_compat("FEEDBACK_PLUGINS_DIR", "") or "").strip()
|
||||||
if not raw:
|
if not raw:
|
||||||
return None
|
return None
|
||||||
p = Path(raw)
|
p = Path(raw)
|
||||||
|
|||||||
+1
-1
@@ -1118,7 +1118,7 @@ def load_plugins(app: FastAPI, context: dict, progress_cb=None, route_setup_fn=N
|
|||||||
|
|
||||||
# Collect plugin directories — user plugins first so they override built-in
|
# Collect plugin directories — user plugins first so they override built-in
|
||||||
plugin_dirs = []
|
plugin_dirs = []
|
||||||
user_plugins_dir = os.environ.get("FEEDBACK_PLUGINS_DIR") or os.environ.get("FEEDBACK_PLUGINS_DIR")
|
user_plugins_dir = os.environ.get("FEEDBACK_PLUGINS_DIR") or os.environ.get("SLOPSMITH_PLUGINS_DIR")
|
||||||
if user_plugins_dir:
|
if user_plugins_dir:
|
||||||
user_path = Path(user_plugins_dir)
|
user_path = Path(user_plugins_dir)
|
||||||
if user_path.is_dir() and user_path != PLUGINS_DIR:
|
if user_path.is_dir() and user_path != PLUGINS_DIR:
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ def setup(app, context):
|
|||||||
# Duplicates are removed via a seen-set keyed on resolved paths.
|
# Duplicates are removed via a seen-set keyed on resolved paths.
|
||||||
def _resolve_plugin_dirs():
|
def _resolve_plugin_dirs():
|
||||||
roots = []
|
roots = []
|
||||||
env_dir = os.environ.get("FEEDBACK_PLUGINS_DIR") or os.environ.get("FEEDBACK_PLUGINS_DIR")
|
env_dir = os.environ.get("FEEDBACK_PLUGINS_DIR") or os.environ.get("SLOPSMITH_PLUGINS_DIR")
|
||||||
if env_dir:
|
if env_dir:
|
||||||
roots.append(Path(env_dir))
|
roots.append(Path(env_dir))
|
||||||
# Built-in plugins/ next to server.py (one level above this file's
|
# Built-in plugins/ next to server.py (one level above this file's
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from pathlib import Path
|
|||||||
from typing import Any, ClassVar
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
from logging_setup import configure_logging
|
from logging_setup import configure_logging
|
||||||
|
from env_compat import getenv_compat
|
||||||
configure_logging()
|
configure_logging()
|
||||||
|
|
||||||
log = logging.getLogger("feedBack.server")
|
log = logging.getLogger("feedBack.server")
|
||||||
@@ -230,7 +231,7 @@ _DEMO_BLOCKED: list[tuple[str, re.Pattern]] = [
|
|||||||
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def _demo_mode_guard(request: Request, call_next):
|
async def _demo_mode_guard(request: Request, call_next):
|
||||||
if os.environ.get("FEEDBACK_DEMO_MODE") or os.environ.get("FEEDBACK_DEMO_MODE") == "1":
|
if getenv_compat("FEEDBACK_DEMO_MODE") or getenv_compat("FEEDBACK_DEMO_MODE") == "1":
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
for method, pattern in _DEMO_BLOCKED:
|
for method, pattern in _DEMO_BLOCKED:
|
||||||
if request.method == method and pattern.match(path):
|
if request.method == method and pattern.match(path):
|
||||||
@@ -275,8 +276,8 @@ SLOPPAK_CACHE_DIR = CONFIG_DIR / "sloppak_cache"
|
|||||||
|
|
||||||
|
|
||||||
def _env_flag(name: str) -> bool:
|
def _env_flag(name: str) -> bool:
|
||||||
"""Parse a conventional boolean env flag."""
|
"""Parse a conventional boolean env flag (honours legacy SLOPSMITH_* alias)."""
|
||||||
return os.environ.get(name, "").strip().lower() in {"1", "true", "yes", "on"}
|
return (getenv_compat(name, "") or "").strip().lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
|
|
||||||
# Canonical Tuning-filter grouping key (feedBack#867). tuning_name collapses
|
# Canonical Tuning-filter grouping key (feedBack#867). tuning_name collapses
|
||||||
@@ -3040,7 +3041,7 @@ def _make_scan_executor():
|
|||||||
# A malformed override falls back to the core count rather than crashing.
|
# A malformed override falls back to the core count rather than crashing.
|
||||||
try:
|
try:
|
||||||
max_workers = int(
|
max_workers = int(
|
||||||
os.environ.get("FEEDBACK_MAX_SCAN_WORKERS")
|
getenv_compat("FEEDBACK_MAX_SCAN_WORKERS")
|
||||||
or os.environ.get("SCAN_MAX_WORKERS")
|
or os.environ.get("SCAN_MAX_WORKERS")
|
||||||
or (os.cpu_count() or 1)
|
or (os.cpu_count() or 1)
|
||||||
)
|
)
|
||||||
@@ -3090,7 +3091,7 @@ def _get_progression_content() -> dict:
|
|||||||
with _progression_content_lock:
|
with _progression_content_lock:
|
||||||
if _progression_content is None:
|
if _progression_content is None:
|
||||||
import progression as progression_mod
|
import progression as progression_mod
|
||||||
root = os.environ.get("FEEDBACK_PROGRESSION_DATA") or (
|
root = getenv_compat("FEEDBACK_PROGRESSION_DATA") or (
|
||||||
_feedBack_server_root() / "data" / "progression"
|
_feedBack_server_root() / "data" / "progression"
|
||||||
)
|
)
|
||||||
content, warnings = progression_mod.load_content(root)
|
content, warnings = progression_mod.load_content(root)
|
||||||
@@ -3488,7 +3489,7 @@ async def startup_events():
|
|||||||
|
|
||||||
# Load plugins asynchronously so HTTP routes and the desktop window can
|
# Load plugins asynchronously so HTTP routes and the desktop window can
|
||||||
# come up immediately while heavy plugin imports/install steps continue.
|
# come up immediately while heavy plugin imports/install steps continue.
|
||||||
_sync_mode = os.environ.get("FEEDBACK_SYNC_STARTUP", "").lower() in {"1", "true", "yes", "on"}
|
_sync_mode = getenv_compat("FEEDBACK_SYNC_STARTUP", "").lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
def _load_plugins_background():
|
def _load_plugins_background():
|
||||||
try:
|
try:
|
||||||
@@ -3723,7 +3724,7 @@ async def startup_events():
|
|||||||
threading.Thread(target=_load_plugins_background, daemon=True).start()
|
threading.Thread(target=_load_plugins_background, daemon=True).start()
|
||||||
|
|
||||||
global _DEMO_JANITOR_STARTED, _DEMO_JANITOR_THREAD
|
global _DEMO_JANITOR_STARTED, _DEMO_JANITOR_THREAD
|
||||||
if os.environ.get("FEEDBACK_DEMO_MODE") or os.environ.get("FEEDBACK_DEMO_MODE") == "1" and not _DEMO_JANITOR_STARTED:
|
if getenv_compat("FEEDBACK_DEMO_MODE") or getenv_compat("FEEDBACK_DEMO_MODE") == "1" and not _DEMO_JANITOR_STARTED:
|
||||||
_DEMO_JANITOR_STARTED = True
|
_DEMO_JANITOR_STARTED = True
|
||||||
_DEMO_JANITOR_STOP.clear()
|
_DEMO_JANITOR_STOP.clear()
|
||||||
def _janitor():
|
def _janitor():
|
||||||
@@ -6183,7 +6184,7 @@ def _diag_plugins_roots() -> list[Path]:
|
|||||||
orphans in the external dir are reflected in the bundle.
|
orphans in the external dir are reflected in the bundle.
|
||||||
"""
|
"""
|
||||||
roots: list[Path] = []
|
roots: list[Path] = []
|
||||||
user_dir = os.environ.get("FEEDBACK_PLUGINS_DIR", "").strip()
|
user_dir = getenv_compat("FEEDBACK_PLUGINS_DIR", "").strip()
|
||||||
if user_dir:
|
if user_dir:
|
||||||
p = Path(user_dir)
|
p = Path(user_dir)
|
||||||
if p.is_dir():
|
if p.is_dir():
|
||||||
@@ -7683,7 +7684,7 @@ def index():
|
|||||||
# UI remains fully available as a fallback — opt back in with
|
# UI remains fully available as a fallback — opt back in with
|
||||||
# FEEDBACK_UI=v2 (or =legacy), or hit the dedicated /v2 route below (which
|
# FEEDBACK_UI=v2 (or =legacy), or hit the dedicated /v2 route below (which
|
||||||
# serves it regardless of the env var).
|
# serves it regardless of the env var).
|
||||||
if os.environ.get("FEEDBACK_UI") or os.environ.get("FEEDBACK_UI") in ("v2", "legacy"):
|
if getenv_compat("FEEDBACK_UI") or getenv_compat("FEEDBACK_UI") in ("v2", "legacy"):
|
||||||
return FileResponse(str(STATIC_DIR / "index.html"))
|
return FileResponse(str(STATIC_DIR / "index.html"))
|
||||||
return FileResponse(str(STATIC_DIR / "v3" / "index.html"))
|
return FileResponse(str(STATIC_DIR / "v3" / "index.html"))
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -3310,7 +3310,9 @@ function setupAppUpdates() {
|
|||||||
// iframes, privacy modes, etc.); fall back to the default channel so the
|
// iframes, privacy modes, etc.); fall back to the default channel so the
|
||||||
// panel still renders rather than aborting wiring entirely.
|
// panel still renders rather than aborting wiring entirely.
|
||||||
let storedRaw = null;
|
let storedRaw = null;
|
||||||
try { storedRaw = localStorage.getItem('feedBack-update-channel'); } catch (_) { /* fall through */ }
|
// Read the canonical key, falling back to the pre-rename
|
||||||
|
// 'slopsmith-update-channel' so an existing channel preference survives.
|
||||||
|
try { storedRaw = localStorage.getItem('feedBack-update-channel') || localStorage.getItem('slopsmith-update-channel'); } catch (_) { /* fall through */ }
|
||||||
const stored = APP_UPDATE_CHANNELS.includes(storedRaw) ? storedRaw : 'stable';
|
const stored = APP_UPDATE_CHANNELS.includes(storedRaw) ? storedRaw : 'stable';
|
||||||
channelSelect.value = stored;
|
channelSelect.value = stored;
|
||||||
|
|
||||||
@@ -3395,7 +3397,7 @@ function setupAppUpdates() {
|
|||||||
channelSelect.addEventListener('change', async () => {
|
channelSelect.addEventListener('change', async () => {
|
||||||
const val = channelSelect.value;
|
const val = channelSelect.value;
|
||||||
if (!APP_UPDATE_CHANNELS.includes(val)) return;
|
if (!APP_UPDATE_CHANNELS.includes(val)) return;
|
||||||
try { localStorage.setItem('feedBack-update-channel', val); } catch (_) {}
|
try { localStorage.setItem('feedBack-update-channel', val); localStorage.removeItem('slopsmith-update-channel'); } catch (_) {}
|
||||||
try {
|
try {
|
||||||
// Await setChannel so the status line reflects what actually
|
// Await setChannel so the status line reflects what actually
|
||||||
// happened — rendering "Channel set" unconditionally would
|
// happened — rendering "Channel set" unconditionally would
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"""Coverage for the slopsmith -> feedBack env backward-compat shim."""
|
||||||
|
|
||||||
|
from env_compat import getenv_compat, env_flag_compat
|
||||||
|
|
||||||
|
|
||||||
|
def test_canonical_wins_over_legacy(monkeypatch):
|
||||||
|
monkeypatch.setenv("FEEDBACK_UI", "v3")
|
||||||
|
monkeypatch.setenv("SLOPSMITH_UI", "v2")
|
||||||
|
assert getenv_compat("FEEDBACK_UI") == "v3"
|
||||||
|
|
||||||
|
|
||||||
|
def test_legacy_fallback_when_canonical_unset(monkeypatch):
|
||||||
|
monkeypatch.delenv("FEEDBACK_UI", raising=False)
|
||||||
|
monkeypatch.setenv("SLOPSMITH_UI", "v2")
|
||||||
|
assert getenv_compat("FEEDBACK_UI") == "v2"
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_when_neither_set(monkeypatch):
|
||||||
|
monkeypatch.delenv("FEEDBACK_UI", raising=False)
|
||||||
|
monkeypatch.delenv("SLOPSMITH_UI", raising=False)
|
||||||
|
assert getenv_compat("FEEDBACK_UI", "default") == "default"
|
||||||
|
assert getenv_compat("FEEDBACK_UI") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_non_feedback_names_have_no_fallback(monkeypatch):
|
||||||
|
monkeypatch.delenv("CONFIG_DIR", raising=False)
|
||||||
|
monkeypatch.setenv("SLOPSMITH_CONFIG_DIR", "/tmp/x")
|
||||||
|
# A non-FEEDBACK_ name must behave like os.environ.get (no aliasing).
|
||||||
|
assert getenv_compat("CONFIG_DIR") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_canonical_is_respected_not_overridden(monkeypatch):
|
||||||
|
# An explicitly-empty canonical value is still "set" and wins.
|
||||||
|
monkeypatch.setenv("FEEDBACK_UI", "")
|
||||||
|
monkeypatch.setenv("SLOPSMITH_UI", "v2")
|
||||||
|
assert getenv_compat("FEEDBACK_UI") == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_flag_parses_true_values(monkeypatch):
|
||||||
|
for raw in ("1", "true", "YES", " On "):
|
||||||
|
monkeypatch.setenv("FEEDBACK_SYNC_STARTUP", raw)
|
||||||
|
assert env_flag_compat("FEEDBACK_SYNC_STARTUP") is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_flag_false_and_legacy(monkeypatch):
|
||||||
|
monkeypatch.delenv("FEEDBACK_SYNC_STARTUP", raising=False)
|
||||||
|
monkeypatch.setenv("SLOPSMITH_SYNC_STARTUP", "1")
|
||||||
|
assert env_flag_compat("FEEDBACK_SYNC_STARTUP") is True
|
||||||
|
monkeypatch.setenv("FEEDBACK_SYNC_STARTUP", "0")
|
||||||
|
assert env_flag_compat("FEEDBACK_SYNC_STARTUP") is False
|
||||||
Reference in New Issue
Block a user