diff --git a/docs/HOW_TO_RUN_TESTS.md b/docs/HOW_TO_RUN_TESTS.md index c491e15d..db1cef12 100644 --- a/docs/HOW_TO_RUN_TESTS.md +++ b/docs/HOW_TO_RUN_TESTS.md @@ -10,10 +10,7 @@ Make sure you have the testing packages installed: ```bash # Install all dependencies including test packages -pip install -r requirements.txt - -# Or install just the test dependencies -pip install pytest pytest-cov pytest-mock +pip install -r requirements.txt -r requirements-test.txt ``` ### 2. Set Environment Variables @@ -302,7 +299,7 @@ If tests fail due to missing packages: ```bash # Install all dependencies -pip install -r requirements.txt +pip install -r requirements.txt -r requirements-test.txt # Or install specific missing package pip install diff --git a/first_time_install.sh b/first_time_install.sh index de634ab0..594449bc 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -1189,14 +1189,7 @@ else # real time and in order relative to this script's own echo statements python3 -u "$PROJECT_ROOT_DIR/scripts/install_dependencies_apt.py" else - echo "Using pip to install dependencies..." - if [ -f "$PROJECT_ROOT_DIR/requirements_web_v2.txt" ]; then - # --ignore-installed: see the Step 5 web_interface/requirements.txt - # install above — same apt/pip RECORD-file conflict applies here. - python3 -m pip install --break-system-packages --prefer-binary --ignore-installed -r requirements_web_v2.txt - else - echo "⚠ requirements_web_v2.txt not found; skipping web dependency install" - fi + echo "Web dependencies already installed from web_interface/requirements.txt in Step 5" fi # Create marker file to indicate dependencies are installed diff --git a/requirements-test.txt b/requirements-test.txt index efbbf522..2faccf94 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,10 +1,7 @@ -# Test-only dependencies for the plugin safety harness and pytest suite. +# Test/dev-only dependencies (not needed on a running display). # Install alongside requirements.txt: pip install -r requirements.txt -r requirements-test.txt -# -# pytest, pytest-cov, pytest-mock, and jsonschema are already pinned (with -# major-version caps) in requirements.txt, so they are intentionally NOT -# repeated here — re-pinning pytest to <9 collided with requirements.txt's -# pytest>=9.0.3,<10 and made the two files impossible to install together. -# Only declare what requirements.txt doesn't already provide. +pytest>=9.0.3,<10.0.0 +pytest-cov>=4.1.0,<5.0.0 +pytest-mock>=3.11.0,<4.0.0 freezegun>=1.2,<2 # deterministic time for golden-image tests mypy>=1.5.0,<2.0.0 # static type checking (also pinned in .pre-commit-config.yaml) diff --git a/requirements.txt b/requirements.txt index b673f04e..3709827e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,10 +34,8 @@ jsonschema>=4.20.0,<5.0.0 # Requirement specifier parsing (plugin dependency satisfaction checks) packaging>=23.0,<27.0 -# Testing dependencies -pytest>=9.0.3,<10.0.0 -pytest-cov>=4.1.0,<5.0.0 -pytest-mock>=3.11.0,<4.0.0 +# Testing dependencies live in requirements-test.txt: +# pip install -r requirements.txt -r requirements-test.txt # ─────────────────────────────────────────────────────────────────────── # Optional dependencies — the code imports these inside try/except diff --git a/scripts/add_defaults_to_schemas.py b/scripts/add_defaults_to_schemas.py index c0474530..3ef33e94 100755 --- a/scripts/add_defaults_to_schemas.py +++ b/scripts/add_defaults_to_schemas.py @@ -201,7 +201,7 @@ def process_schema_file(schema_path: Path) -> bool: def main(): """Main entry point.""" project_root = Path(__file__).parent.parent - plugins_dir = project_root / 'plugins' + plugins_dir = project_root / 'plugin-repos' if not plugins_dir.exists(): print(f"Error: Plugins directory not found: {plugins_dir}") diff --git a/scripts/analyze_plugin_schemas.py b/scripts/analyze_plugin_schemas.py index d10a308f..e05f20eb 100755 --- a/scripts/analyze_plugin_schemas.py +++ b/scripts/analyze_plugin_schemas.py @@ -193,7 +193,7 @@ def analyze_schema(schema_path: Path) -> Dict[str, Any]: def main(): """Main analysis function.""" project_root = Path(__file__).parent.parent - plugins_dir = project_root / "plugins" + plugins_dir = project_root / "plugin-repos" if not plugins_dir.exists(): print(f"Plugins directory not found: {plugins_dir}") diff --git a/scripts/remove_plugin_backups.sh b/scripts/remove_plugin_backups.sh deleted file mode 100755 index ab8146b4..00000000 --- a/scripts/remove_plugin_backups.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash - -# Script to safely remove plugin backup directories -# These were created during the plugin-to-submodule conversion - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -PLUGINS_DIR="$PROJECT_ROOT/plugins" - -# Colors -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' - -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Verify submodules are working -verify_submodules() { - log_info "Verifying submodules are working..." - local issues=0 - - for submod in football-scoreboard hockey-scoreboard ledmatrix-flights \ - ledmatrix-leaderboard ledmatrix-stocks ledmatrix-weather \ - mqtt-notifications; do - if [ ! -d "$PLUGINS_DIR/$submod" ]; then - log_error "Submodule directory missing: $submod" - issues=$((issues + 1)) - elif [ ! -f "$PLUGINS_DIR/$submod/.git" ]; then - log_error "Submodule .git file missing: $submod" - issues=$((issues + 1)) - elif [ ! -f "$PLUGINS_DIR/$submod/manifest.json" ]; then - log_warn "Submodule manifest missing: $submod (may be OK)" - fi - done - - if [ $issues -eq 0 ]; then - log_info "All submodules verified ✓" - return 0 - else - log_error "Found $issues issues with submodules" - return 1 - fi -} - -# Remove backup directories -remove_backups() { - log_info "Removing backup directories..." - - local removed=0 - local total_size=0 - - for backup in "$PLUGINS_DIR"/*.backup*; do - if [ -d "$backup" ]; then - local name=$(basename "$backup") - local size=$(du -sb "$backup" 2>/dev/null | awk '{print $1}') - total_size=$((total_size + size)) - - log_info "Removing: $name" - rm -rf "$backup" - removed=$((removed + 1)) - fi - done - - if [ $removed -gt 0 ]; then - log_info "Removed $removed backup directory(ies)" - log_info "Freed approximately $(numfmt --to=iec-i --suffix=B $total_size 2>/dev/null || echo "$total_size bytes")" - else - log_info "No backup directories found" - fi -} - -# Main -main() { - cd "$PROJECT_ROOT" - - echo "=== Plugin Backup Removal Script ===" - echo - - # Verify submodules first - if ! verify_submodules; then - log_error "Submodule verification failed. Not removing backups." - log_warn "Please fix submodule issues before removing backups." - exit 1 - fi - - echo - log_warn "This will permanently delete backup directories:" - ls -1d "$PLUGINS_DIR"/*.backup* 2>/dev/null | sed 's|.*/| - |' || echo " (none found)" - echo - - read -p "Continue? (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - log_info "Aborted" - exit 0 - fi - - remove_backups - - log_info "Done!" -} - -main "$@" - diff --git a/web_interface/static/v3/plugins_manager.js b/web_interface/static/v3/plugins_manager.js index 86257d30..8bca1821 100644 --- a/web_interface/static/v3/plugins_manager.js +++ b/web_interface/static/v3/plugins_manager.js @@ -2299,56 +2299,6 @@ function renderArrayObjectItem(fieldId, fullKey, itemProperties, itemValue, inde // Functions to handle patternProperties key-value pairs -window.addKeyValuePair = function(fieldId, fullKey, maxProperties) { - const pairsContainer = document.getElementById(fieldId + '_pairs'); - if (!pairsContainer) return; - - const currentPairs = pairsContainer.querySelectorAll('.key-value-pair'); - if (currentPairs.length >= maxProperties) { - alert(`Maximum ${maxProperties} entries allowed`); - return; - } - - const newIndex = currentPairs.length; - const valueType = 'string'; // Default to string, could be determined from schema - - const pairHtml = ` -
- - - -
- `; - - pairsContainer.insertAdjacentHTML('beforeend', pairHtml); - updateKeyValuePairData(fieldId, fullKey); - - // Update add button state - const addButton = pairsContainer.nextElementSibling; - if (addButton && currentPairs.length + 1 >= maxProperties) { - addButton.disabled = true; - addButton.style.opacity = '0.5'; - addButton.style.cursor = 'not-allowed'; - } -}; - window.removeKeyValuePair = function(fieldId, index) { const pairsContainer = document.getElementById(fieldId + '_pairs'); if (!pairsContainer) return; @@ -4559,23 +4509,6 @@ function formatDate(dateString) { } } -function formatCommit(commit, branch) { - const shortCommit = commit ? String(commit).substring(0, 7) : ''; - const branchText = branch ? String(branch) : ''; - - if (branchText && shortCommit) { - return `${branchText} · ${shortCommit}`; - } - if (branchText) { - return branchText; - } - if (shortCommit) { - return shortCommit; - } - return 'Latest'; -} - -// Check if plugin is new (updated within last 7 days) function isNewPlugin(lastUpdated) { if (!lastUpdated) return false; @@ -4605,26 +4538,6 @@ function debounce(func, wait) { } // Toggle password visibility for secret fields -function togglePasswordVisibility(fieldId) { - const input = document.getElementById(fieldId); - const icon = document.getElementById(fieldId + '-icon'); - - if (input && icon) { - if (input.type === 'password') { - input.type = 'text'; - icon.classList.remove('fa-eye'); - icon.classList.add('fa-eye-slash'); - } else { - input.type = 'password'; - icon.classList.remove('fa-eye-slash'); - icon.classList.add('fa-eye'); - } - } -} - -// GitHub Token Configuration Functions -// Open GitHub Token Settings panel (only opens, doesn't close) -// Used when user clicks "Configure Token" link window.openGithubTokenSettings = function() { const settings = document.getElementById('github-token-settings'); const warning = document.getElementById('github-auth-warning'); diff --git a/web_interface/templates/v3/base.html b/web_interface/templates/v3/base.html index 3f3edcc1..28ed48b9 100644 --- a/web_interface/templates/v3/base.html +++ b/web_interface/templates/v3/base.html @@ -1013,7 +1013,11 @@ - +