feat(system): seedgo v2 operational, full system audit, 14/15 branches at 99%
Three days of intensive work bringing seedgo to full operational status and driving all branches through comprehensive standards compliance. Seedgo v2.0.0: - 22 checkers active (up from 20), standards pack fully operational - New introspection standard researched from Dev-Pass, FPLAN-0017 open - Bypass system for false positives (.seedgo config) - Standards query and audit commands fully functional System-wide audit (FPLAN-0016): - All 14 auditable branches at 99%+ compliance - CLI imports standardized across all branches (console from cli.apps.modules) - handle_command(command, args) → bool contract added to all modules - print_help() function naming fixed for checker pattern matching - Handler extraction: large modules split, file I/O moved to handler layer - New handlers created across ai_mail, backup, daemon, flow, skills, spawn, seedgo Branch-specific highlights: - ai_mail: email.py split 840→420 lines, 4 new handlers - flow: dplan_flow.py 688→591 lines, 4 new handlers - seedgo: massive restructure — standards moved to handlers/aipass_standards/, old standards/ tree removed, bypass system added, diagnostics module - commons: database module added, CLI imports fixed - skills: 5 handle_commands added, help function renamed - trigger: error reporter handler, handle_command routing - All branches: consistent architecture, clean drone routing Culture doc (CLAUDE.md) added — documents AIPass philosophy, identity, memory system, and collaboration principles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
09e759a8a4
commit
babedd9c64
+116
-2
@@ -3,13 +3,127 @@
|
||||
**Purpose:** Multi-mode backup with Google Drive integration
|
||||
**Module:** `aipass.backup`
|
||||
**Created:** 2026-03-07
|
||||
**Citizen Class:** birthright
|
||||
**Citizen Class:** builder
|
||||
**Last Updated:** 2026-03-08
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Birthright citizen — minimal presence with identity and memory.
|
||||
Builder citizen — full 3-layer architecture with identity and memory.
|
||||
|
||||
Provides automated file protection through snapshot backups, versioned backups,
|
||||
and Google Drive synchronization. The entry point routes commands to four
|
||||
specialized modules: `backup_core`, `google_drive_sync`, `integrations`, and
|
||||
`reauth_drive`.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
backup/
|
||||
├── __init__.py
|
||||
├── README.md
|
||||
├── apps/
|
||||
│ ├── backup.py # Entry point (CLI) — drone @backup
|
||||
│ ├── modules/
|
||||
│ │ ├── backup_core.py # Core backup operations (snapshot, versioned)
|
||||
│ │ ├── google_drive_sync.py # Google Drive sync orchestration
|
||||
│ │ ├── integrations.py # Cross-module integration commands
|
||||
│ │ └── reauth_drive.py # Google Drive re-authentication
|
||||
│ ├── handlers/
|
||||
│ │ ├── config/
|
||||
│ │ │ └── config_handler.py # Configuration management
|
||||
│ │ ├── diff/
|
||||
│ │ │ ├── diff_generator.py # Diff generation between backups
|
||||
│ │ │ ├── version_manager.py # Version tracking
|
||||
│ │ │ └── vscode_integration.py # VS Code diff viewer integration
|
||||
│ │ ├── json/
|
||||
│ │ │ ├── backup_info_handler.py # Backup info JSON read/write
|
||||
│ │ │ ├── backup_metadata_builder.py # Metadata construction
|
||||
│ │ │ ├── changelog_handler.py # Changelog JSON management
|
||||
│ │ │ ├── drive_sync_json.py # Drive sync state tracking
|
||||
│ │ │ ├── json_handler.py # Generic JSON utilities
|
||||
│ │ │ └── statistics_handler.py # Backup statistics
|
||||
│ │ ├── models/
|
||||
│ │ │ └── backup_models.py # Data models for backup objects
|
||||
│ │ ├── operations/
|
||||
│ │ │ ├── drive_sync_client.py # Google Drive API client
|
||||
│ │ │ ├── drive_sync_ops.py # Drive sync implementation
|
||||
│ │ │ ├── file_cleanup.py # Old backup cleanup
|
||||
│ │ │ ├── file_operations.py # File copy/move operations
|
||||
│ │ │ ├── file_scanner.py # File discovery and filtering
|
||||
│ │ │ ├── integration_ops.py # Integration operation logic
|
||||
│ │ │ └── path_builder.py # Backup path construction
|
||||
│ │ ├── reporting/
|
||||
│ │ │ └── report_formatter.py # Backup report formatting
|
||||
│ │ └── utils/
|
||||
│ │ ├── backup_timestamps.py # Timestamp utilities
|
||||
│ │ ├── reauth_handler.py # Re-auth implementation
|
||||
│ │ └── system_utils.py # System-level utilities
|
||||
│ ├── extensions/ # Extension point (placeholder)
|
||||
│ ├── json_templates/ # JSON template files
|
||||
│ └── plugins/ # Plugin point (placeholder)
|
||||
├── backup_json/ # JSON tracking data
|
||||
├── artifacts/ # Backup artifacts
|
||||
├── docs/ # Documentation
|
||||
├── tests/ # Test suite
|
||||
└── tools/ # Branch verification utilities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commands / Usage
|
||||
|
||||
```bash
|
||||
drone @backup # Introspection — list discovered modules
|
||||
drone @backup --help # Show full help
|
||||
drone @backup --version # Show version
|
||||
drone @backup --all # Full backup cycle: snapshot -> versioned -> drive-sync
|
||||
drone @backup snapshot # Create a system snapshot backup
|
||||
drone @backup versioned # Create a versioned backup
|
||||
drone @backup drive-test # Test Google Drive connectivity
|
||||
drone @backup drive-sync # Sync backups to Google Drive
|
||||
drone @backup drive-sync --test # Run a small test sync to verify integration
|
||||
drone @backup drive-stats # Show Drive file tracker statistics
|
||||
drone @backup drive-clear-tracker # Clear Drive file tracker cache
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--verbose`, `-v` | Extra diagnostic output |
|
||||
| `--dry-run` | Preview what would happen, execute nothing |
|
||||
| `--note NOTE` | Add a backup note/description |
|
||||
| `--project NAME` | Project name for Drive sync (default: AIPass) |
|
||||
| `--force` | Force sync all files (ignore change tracker) |
|
||||
| `--limit N` | Limit drive-sync to first N files |
|
||||
|
||||
---
|
||||
|
||||
## Integration Points
|
||||
|
||||
### Depends On
|
||||
- `rich` — Console output and formatting
|
||||
- Python stdlib (`sys`, `argparse`, `logging`, `pathlib`)
|
||||
|
||||
### Provides To
|
||||
- All modules — automated file protection, snapshot and versioned backups
|
||||
- Google Drive — cloud backup synchronization
|
||||
- Other branches — backup artifacts via `backup_json/` and `artifacts/`
|
||||
|
||||
---
|
||||
|
||||
## Modules
|
||||
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| `backup_core` | Core backup operations — snapshot and versioned backup creation |
|
||||
| `google_drive_sync` | Google Drive synchronization — upload, track, and manage cloud backups |
|
||||
| `integrations` | Cross-module integration commands and coordination |
|
||||
| `reauth_drive` | Google Drive re-authentication when credentials expire |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup.py - Backup System Entry Point
|
||||
# Date: 2025-11-22
|
||||
# Version: 1.3.0
|
||||
# Category: core/backup
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.3.0 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang, sys.path manipulation, prax/cli imports
|
||||
# * Replaced get_modules() with explicit relative imports
|
||||
# * Uses standard logging and rich console
|
||||
# - v1.2.0 (2026-02-22): Seed CLI flags standard: --version, backup all command
|
||||
# - v1.1.0 (2025-11-22): Fixed META header - correct filename, category, and standards
|
||||
# - v1.0.0 (2025-11-08): Initial version - modular architecture
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers implement logic, modules orchestrate
|
||||
# =================== AIPass ====================
|
||||
# Name: backup.py
|
||||
# Description: Entry point CLI for drone @backup
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-08
|
||||
# Modified: 2026-03-08
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -28,14 +16,11 @@ Main handles routing, modules implement functionality.
|
||||
# Standard library imports
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, List
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
console = Console()
|
||||
from aipass.cli.apps.modules import console
|
||||
from aipass.prax import logger
|
||||
|
||||
# Explicit module imports (replaces dynamic discover_modules)
|
||||
from aipass.backup.apps.modules import backup_core, google_drive_sync, integrations, reauth_drive
|
||||
|
||||
@@ -1,29 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: config_handler.py - Backup system configuration and patterns
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: config_handler.py
|
||||
# Description: Backup system configuration and patterns
|
||||
# Version: 2.0.2
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.2 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang and sys.path manipulation
|
||||
# * Cleared CLI_TRACKING_PATTERNS (hardcoded internal paths removed)
|
||||
# - v2.0.1 (2025-11-23): Added ignore patterns for log/data JSON files
|
||||
# * Enabled *_data.json pattern to ignore backup_core_data.json
|
||||
# * Enabled *_log.json pattern to ignore backup_core_log.json, drone_log.json
|
||||
# * Enabled snapshot_backup.json pattern
|
||||
# * Prevents frequent-change files from being backed up every run
|
||||
# - v2.0.0 (2025-11-16): Seed standard extraction from archive
|
||||
# * All configuration constants and patterns
|
||||
# * Helper functions for pattern matching and filtering
|
||||
# * Pure configuration - no complex logic
|
||||
# - v1.0.0 (2025-10-14): Initial extraction from backup.py
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: diff_generator.py - Unified diff generation with binary detection
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: diff_generator.py
|
||||
# Description: Unified diff generation with binary detection
|
||||
# Version: 2.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
|
||||
# * Diff generation functionality
|
||||
# * Binary file detection
|
||||
# * Unified diff content generation
|
||||
# * Updated imports to new handler locations
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: version_manager.py - Version discovery and management
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: version_manager.py
|
||||
# Description: Version discovery and management
|
||||
# Version: 2.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
|
||||
# * Version file discovery functionality
|
||||
# * Versioned file listing
|
||||
# * Support for file-organized structure
|
||||
# * Updated imports to new handler locations
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -30,11 +17,11 @@ Supports version listing and filtering.
|
||||
# IMPORTS
|
||||
# =============================================
|
||||
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# Import from handlers
|
||||
from aipass.backup.apps.handlers.utils.system_utils import safe_print
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: vscode_integration.py - VS Code diff viewer integration
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: vscode_integration.py
|
||||
# Description: VS Code diff viewer integration
|
||||
# Version: 2.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
|
||||
# * VS Code diff viewer integration
|
||||
# * File comparison logic
|
||||
# * Baseline vs current comparison
|
||||
# * Updated imports to new handler locations
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -33,10 +20,10 @@ Supports baseline vs current and version-to-version comparisons.
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# Import from handlers
|
||||
from aipass.backup.apps.handlers.utils.system_utils import safe_print
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup_info_handler.py - Backup state and statistics
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: backup_info_handler.py
|
||||
# Description: Backup state and statistics
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-16): Initial extraction from backup_core.py
|
||||
# * load_backup_info() - Load mode-specific state
|
||||
# * save_backup_info() - Persist backup state
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup_metadata_builder.py - Backup metadata construction
|
||||
# Date: 2025-11-18
|
||||
# =================== AIPass ====================
|
||||
# Name: backup_metadata_builder.py
|
||||
# Description: Backup metadata construction
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted backup_info creation logic
|
||||
# * Handles mode-specific metadata formatting
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-18
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: changelog_handler.py - Backup changelog management
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: changelog_handler.py
|
||||
# Description: Backup changelog management
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-16): Initial extraction from backup_core.py
|
||||
# * load_changelog() - Load persistent changelog
|
||||
# * save_changelog_entry() - Add new entry
|
||||
# * display_previous_comments() - Show history
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -35,17 +23,12 @@ Functions:
|
||||
# =============================================
|
||||
|
||||
import json
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
# Initialize console for output
|
||||
console = Console()
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# =============================================
|
||||
# CHANGELOG OPERATIONS
|
||||
@@ -65,8 +48,7 @@ def load_changelog(changelog_file: Path) -> Dict:
|
||||
with open(changelog_file, 'r', encoding='utf-8', errors='replace') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error loading changelog: {e}[/red]")
|
||||
logger.warning(f"Error loading changelog: {e}")
|
||||
logger.error(f"Error loading changelog: {e}")
|
||||
return {"entries": []}
|
||||
|
||||
|
||||
@@ -98,7 +80,6 @@ def save_changelog_entry(changelog_file: Path, note: str, mode: str,
|
||||
logger.info(f"[changelog_handler] Saved changelog entry: {note[:50]}")
|
||||
return True
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error saving changelog entry: {e}[/red]")
|
||||
logger.error(f"[changelog_handler] Error saving changelog: {e}")
|
||||
return False
|
||||
|
||||
@@ -115,14 +96,10 @@ def display_previous_comments(changelog_file: Path, mode_name: str):
|
||||
entries = changelog.get("entries", [])
|
||||
|
||||
if not entries:
|
||||
console.print(f"[yellow]No previous {mode_name} backup comments found.[/yellow]")
|
||||
logger.warning(f"No previous {mode_name} backup comments found.")
|
||||
return
|
||||
|
||||
from rich.panel import Panel
|
||||
console.print()
|
||||
console.print(Panel(f"PREVIOUS {mode_name.upper()} BACKUP COMMENTS",
|
||||
style="bold cyan",
|
||||
border_style="cyan"))
|
||||
logger.info(f"PREVIOUS {mode_name.upper()} BACKUP COMMENTS")
|
||||
|
||||
# Show last 10 entries (most recent first)
|
||||
recent_entries = entries[-10:]
|
||||
@@ -133,21 +110,20 @@ def display_previous_comments(changelog_file: Path, mode_name: str):
|
||||
mode_info = entry.get('mode', 'unknown')
|
||||
# Handle encoding issues in notes
|
||||
note = str(entry['note']).encode('ascii', errors='replace').decode('ascii')
|
||||
console.print(f"[bright_blue]{i:2d}.[/bright_blue] [{formatted_time}] [green][{mode_info}][/green] {note}")
|
||||
logger.info(f"{i:2d}. [{formatted_time}] [{mode_info}] {note}")
|
||||
except Exception as e:
|
||||
console.print(f"[bright_blue]{i:2d}.[/bright_blue] [red][ERROR] Failed to display entry: {e}[/red]")
|
||||
logger.error(f"{i:2d}. [ERROR] Failed to display entry: {e}")
|
||||
|
||||
if len(entries) > 10:
|
||||
console.print(f"\n[dim]... and {len(entries) - 10} older entries[/dim]")
|
||||
console.print()
|
||||
logger.info(f"... and {len(entries) - 10} older entries")
|
||||
except FileNotFoundError:
|
||||
console.print(f"[yellow]No previous {mode_name} backup comments found.[/yellow]")
|
||||
logger.warning(f"No previous {mode_name} backup comments found.")
|
||||
except PermissionError as e:
|
||||
console.print(f"[yellow]Warning: Cannot read backup history - permission denied: {e}[/yellow]")
|
||||
console.print("[yellow]Continuing with backup...[/yellow]")
|
||||
logger.warning(f"Cannot read backup history - permission denied: {e}")
|
||||
logger.warning("Continuing with backup...")
|
||||
except Exception as e:
|
||||
console.print(f"[yellow]Warning: Error displaying comments: {e}[/yellow]")
|
||||
console.print("[yellow]Continuing with backup...[/yellow]")
|
||||
logger.warning(f"Error displaying comments: {e}")
|
||||
logger.warning("Continuing with backup...")
|
||||
|
||||
|
||||
# =============================================
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: drive_sync_json.py - Google Drive Sync JSON Operations Handler
|
||||
# Date: 2026-02-20
|
||||
# =================== AIPass ====================
|
||||
# Name: drive_sync_json.py
|
||||
# Description: Google Drive Sync JSON Operations Handler
|
||||
# Version: 1.0.0
|
||||
# Category: backup_system/handlers/json
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-20): Extracted from google_drive_sync module
|
||||
# * Moved JSON I/O functions to handler layer
|
||||
# * Follows seed 3-layer architecture standards
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers must be independent and transportable
|
||||
# - No prax imports (handler tier)
|
||||
# - Pure file I/O operations
|
||||
# Created: 2026-02-20
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: json_handler.py - JSON Auto-Creating Handler
|
||||
# Date: 2025-11-22
|
||||
# =================== AIPass ====================
|
||||
# Name: json_handler.py
|
||||
# Description: JSON Auto-Creating Handler
|
||||
# Version: 3.1.0
|
||||
# Category: backup_system/handlers/json
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v3.1.0 (2026-01-31): Refactored to comply with error handling standards
|
||||
# - v3.0.0 (2025-11-22): Updated to match Cortex template with all features
|
||||
# - v2.0.0 (2025-11-16): Migrated to seed 3-layer architecture
|
||||
# - v1.0.0 (2025-10-14): Initial implementation with auto-detection
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Pure functions with proper error raising
|
||||
# - No Prax imports (handler tier 3)
|
||||
# Created: 2025-11-22
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
import json
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: statistics_handler.py - Backup statistics tracking
|
||||
# Date: 2025-11-18
|
||||
# =================== AIPass ====================
|
||||
# Name: statistics_handler.py
|
||||
# Description: Backup statistics tracking
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted update_data_file() statistics tracking
|
||||
# * Handles runtime state and statistics updates
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-18
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -27,11 +16,11 @@ Manages backup operation statistics and runtime state persistence.
|
||||
# IMPORTS
|
||||
# =============================================
|
||||
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# Import handlers
|
||||
from aipass.backup.apps.handlers.json.json_handler import load_json, save_json
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup_models.py - Backup system data models and structures
|
||||
# Date: 2025-11-16
|
||||
# =================== AIPass ====================
|
||||
# Name: backup_models.py
|
||||
# Description: Backup system data models and structures
|
||||
# Version: 2.0.1
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.1 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang and sys.path manipulation
|
||||
# - v2.0.0 (2025-11-16): Migrated to seed 3-layer architecture
|
||||
# - v1.0.0 (2025-10-14): Initial extraction from backup.py
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-16
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: drive_sync_client.py - Google Drive Sync Client Handler
|
||||
# Date: 2026-02-20
|
||||
# =================== AIPass ====================
|
||||
# Name: drive_sync_client.py
|
||||
# Description: Google Drive Sync Client Handler
|
||||
# Version: 1.0.0
|
||||
# Category: backup_system/handlers/operations
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-20): Extracted GoogleDriveSync class from module
|
||||
# * Moved implementation to handler layer per seed 3-layer architecture
|
||||
# * Module now delegates to this handler for all Drive operations
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers must be independent and transportable
|
||||
# - No prax imports in class methods (handler tier)
|
||||
# - Google API interactions isolated here
|
||||
# Created: 2026-02-20
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: drive_sync_ops.py - Google Drive Sync Business Operations Handler
|
||||
# Date: 2026-02-20
|
||||
# =================== AIPass ====================
|
||||
# Name: drive_sync_ops.py
|
||||
# Description: Google Drive Sync Business Operations Handler
|
||||
# Version: 1.0.0
|
||||
# Category: backup_system/handlers/operations
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-20): Extracted from google_drive_sync module
|
||||
# * Moved get_status, clear_file_tracker, show_file_tracker_stats,
|
||||
# test_drive_sync to handler layer
|
||||
# * Follows seed 3-layer architecture standards
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers must be independent and transportable
|
||||
# - No prax imports (handler tier)
|
||||
# - Delegates to json handler for file operations
|
||||
# Created: 2026-02-20
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,29 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: file_cleanup.py - File deletion operations
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: file_cleanup.py
|
||||
# Description: File deletion operations
|
||||
# Version: 1.0.2
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.2 (2025-11-23): Added dry-run support for cleanup operations
|
||||
# * Added dry_run parameter to cleanup_deleted_files()
|
||||
# * Shows "Would delete" messages instead of actually deleting in dry-run
|
||||
# * All three passes (directories, files, empty dirs) respect dry-run mode
|
||||
# - v1.0.1 (2025-11-23): CRITICAL BUG FIX - respect exceptions in empty dir cleanup
|
||||
# * Third pass now checks should_ignore() before removing empty directories
|
||||
# * Prevents deletion of empty template directories
|
||||
# * Added source_dir mapping to check exceptions properly
|
||||
# * Only removes empty dirs if source doesn't exist OR should be ignored
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted file deletion logic for dynamic mode
|
||||
# * Handles cleanup of deleted source files
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -36,11 +16,11 @@ Handles cleanup of backup files when source files are deleted.
|
||||
# IMPORTS
|
||||
# =============================================
|
||||
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
from aipass.backup.apps.handlers.utils.system_utils import temporarily_writable, safe_print
|
||||
from aipass.backup.apps.handlers.models.backup_models import BackupResult
|
||||
|
||||
@@ -1,40 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: file_operations.py - Core backup file operations
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: file_operations.py
|
||||
# Description: Core backup file operations
|
||||
# Version: 2.0.4
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.4 (2025-11-23): Fix baseline snapshot messages for VS Code clickability
|
||||
# * Changed baseline snapshot message from {baseline_name} to {baseline_path}
|
||||
# * Users can now Ctrl+click on baseline paths to jump directly to files
|
||||
# * Shows full path (e.g., /home/aipass/backups/project/README-baseline-2025-11-23.md)
|
||||
# - v2.0.3 (2025-11-23): CRITICAL performance fix for versioned backup
|
||||
# * Skip copying unchanged files (only copy if mtime differs)
|
||||
# * Fixes 5s -> <1s regression (was copying all 5000+ files every time)
|
||||
# * Added file_changed flag to track copy necessity
|
||||
# * Only copy if is_new_file or file_changed
|
||||
# - v2.0.2 (2025-11-23): Added per-file output to snapshot mode
|
||||
# * Snapshot backup now shows each file as it's copied
|
||||
# * Displays "Copied (new)" or "Copied (updated)" for each file
|
||||
# * Matches the verbosity of versioned backup mode
|
||||
# - v2.0.1 (2025-11-23): Fixed automatic VS Code diff opening
|
||||
# * Removed automatic VS Code integration from copy_versioned_file()
|
||||
# * Diffs are now created silently without opening in editor
|
||||
# * VS Code integration still available via separate command
|
||||
# - v2.0.0 (2025-11-16): Extraction from backup_operations.py
|
||||
# * Extracted core file operations (lines 49-271)
|
||||
# * copy_file_with_structure for snapshot mode
|
||||
# * copy_versioned_file with baseline snapshots and diff generation
|
||||
# * Extensive Linux permission handling with temporarily_writable()
|
||||
# * Retry logic for filesystem errors
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -52,12 +21,12 @@ Functions:
|
||||
# IMPORTS
|
||||
# =============================================
|
||||
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
import shutil
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# Import from handlers modules
|
||||
from aipass.backup.apps.handlers.utils.system_utils import temporarily_writable, safe_print
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: file_scanner.py - File system scanning operations
|
||||
# Date: 2025-11-18
|
||||
# =================== AIPass ====================
|
||||
# Name: file_scanner.py
|
||||
# Description: File system scanning operations
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted file scanning logic (os.walk loops)
|
||||
# * Handles file discovery with ignore patterns
|
||||
# * Returns file list with metadata
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-18
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: integration_ops.py - Backup Integration Operations Handler
|
||||
# Date: 2026-02-20
|
||||
# =================== AIPass ====================
|
||||
# Name: integration_ops.py
|
||||
# Description: Backup Integration Operations Handler
|
||||
# Version: 1.0.0
|
||||
# Category: backup_system/handlers/operations
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-20): Extracted from integrations module
|
||||
# * Moved sync_to_drive() and set_backup_readonly() to handler layer
|
||||
# * Follows seed 3-layer architecture standards
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers must be independent and transportable
|
||||
# - No prax imports (handler tier)
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2026-02-20
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: path_builder.py - Backup path construction
|
||||
# Date: 2025-11-18
|
||||
# =================== AIPass ====================
|
||||
# Name: path_builder.py
|
||||
# Description: Backup path construction
|
||||
# Version: 1.0.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted path construction logic for versioned mode
|
||||
# * Handles long filename hashing
|
||||
# * Mode-specific path building
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-18
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# =================== AIPass ====================
|
||||
# Name: sync_test_ops.py
|
||||
# Description: File operations for Drive sync test
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-08
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
Sync Test File Operations Handler
|
||||
|
||||
Handles file system operations for the Drive sync test workflow:
|
||||
- Creating test directory and test files
|
||||
- Cleaning up test directory after test completes
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from aipass.prax import logger
|
||||
|
||||
|
||||
def create_sync_test_files(backup_root: Path) -> dict:
|
||||
"""Create test directory and test files for Drive sync verification.
|
||||
|
||||
Args:
|
||||
backup_root: Root backup directory (e.g., src/aipass/backup/)
|
||||
|
||||
Returns:
|
||||
dict with keys:
|
||||
- success (bool): Whether files were created
|
||||
- test_dir (Path): Path to test directory
|
||||
- file_count (int): Number of test files created
|
||||
- error (str|None): Error message if failed
|
||||
"""
|
||||
try:
|
||||
test_dir = backup_root / "backups" / "_sync_test"
|
||||
test_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
test_files = {
|
||||
"test_file_1.txt": "Hello from AIPass backup test",
|
||||
"test_file_2.json": '{"test": true, "timestamp": "' + datetime.now().isoformat() + '"}',
|
||||
"subdir/nested_file.txt": "Nested directory test",
|
||||
"subdir/deep/deeper_file.md": "# Deep nested test\nVerifying folder structure",
|
||||
}
|
||||
|
||||
for name, content in test_files.items():
|
||||
path = test_dir / name
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content)
|
||||
|
||||
logger.info(f"[sync_test_ops] Created {len(test_files)} test files in {test_dir}")
|
||||
return {
|
||||
"success": True,
|
||||
"test_dir": test_dir,
|
||||
"file_count": len(test_files),
|
||||
"error": None,
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"[sync_test_ops] Failed to create test files: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"test_dir": None,
|
||||
"file_count": 0,
|
||||
"error": str(e),
|
||||
}
|
||||
|
||||
|
||||
def cleanup_sync_test_dir(test_dir: Path) -> dict:
|
||||
"""Remove the sync test directory and all contents.
|
||||
|
||||
Args:
|
||||
test_dir: Path to test directory to remove
|
||||
|
||||
Returns:
|
||||
dict with keys:
|
||||
- success (bool): Whether cleanup succeeded
|
||||
- error (str|None): Error message if failed
|
||||
"""
|
||||
try:
|
||||
shutil.rmtree(test_dir, ignore_errors=True)
|
||||
logger.info(f"[sync_test_ops] Cleaned up test directory: {test_dir}")
|
||||
return {"success": True, "error": None}
|
||||
except Exception as e:
|
||||
logger.error(f"[sync_test_ops] Failed to cleanup test directory: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
@@ -1,25 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: report_formatter.py - Backup result reporting
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: report_formatter.py
|
||||
# Description: Backup result reporting
|
||||
# Version: 1.1.0
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.1.0 (2025-11-23): Added dry-run statistics display
|
||||
# * Added dry_run parameter to display_backup_results()
|
||||
# * Shows "Would copy", "Would skip", "Would delete" in dry-run mode
|
||||
# * Provides clear differentiation between dry-run and actual execution
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted statistics display formatting
|
||||
# * Handles error/warning display
|
||||
# * Formats skipped items reports
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -35,16 +19,15 @@ Formats and displays backup operation results, statistics, errors, and warnings.
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from rich.console import Console
|
||||
from aipass.prax import logger
|
||||
from aipass.backup.apps.handlers.models.backup_models import BackupResult
|
||||
|
||||
console = Console()
|
||||
# logger imported from aipass.prax
|
||||
|
||||
def _header(text):
|
||||
console.print(f"\n[bold cyan]{'='*70}[/bold cyan]")
|
||||
console.print(f"[bold cyan] {text}[/bold cyan]")
|
||||
console.print(f"[bold cyan]{'='*70}[/bold cyan]")
|
||||
|
||||
from aipass.backup.apps.handlers.models.backup_models import BackupResult
|
||||
logger.info(f"{'='*70}")
|
||||
logger.info(f" {text}")
|
||||
logger.info(f"{'='*70}")
|
||||
|
||||
# =============================================
|
||||
# REPORT FORMATTING OPERATIONS
|
||||
@@ -66,88 +49,77 @@ def display_backup_results(result: BackupResult, mode_config: dict, backup_path:
|
||||
|
||||
# Determine overall result status
|
||||
if result.critical_errors:
|
||||
status_style = "[bold red]"
|
||||
status_icon = "!"
|
||||
status_text = "FAILED"
|
||||
elif result.errors > 0:
|
||||
status_style = "[bold red]"
|
||||
status_icon = "X"
|
||||
status_text = "COMPLETED WITH ERRORS"
|
||||
elif result.warnings:
|
||||
status_style = "[bold yellow]"
|
||||
status_icon = "!"
|
||||
status_text = "COMPLETED WITH WARNINGS"
|
||||
else:
|
||||
status_style = "[bold green]"
|
||||
status_icon = "OK"
|
||||
status_text = "COMPLETED SUCCESSFULLY"
|
||||
|
||||
# Use _header for main status
|
||||
console.print()
|
||||
_header(f"{status_icon} {mode_config['name'].upper()} {status_text}")
|
||||
console.print()
|
||||
|
||||
# Statistics Section
|
||||
console.print("[bold cyan]STATISTICS:[/bold cyan]")
|
||||
console.print(f" Files checked: [dim]{result.files_checked}[/dim]")
|
||||
logger.info("STATISTICS:")
|
||||
logger.info(f" Files checked: {result.files_checked}")
|
||||
|
||||
if dry_run:
|
||||
# Dry-run mode: show "would be" language
|
||||
console.print(f" Would copy: [bold]{result.files_copied}[/bold] files")
|
||||
console.print(f" Would skip: [dim]{result.files_skipped}[/dim] files (unchanged)")
|
||||
logger.info(f" Would copy: {result.files_copied} files")
|
||||
logger.info(f" Would skip: {result.files_skipped} files (unchanged)")
|
||||
if result.files_deleted > 0:
|
||||
console.print(f" Would delete: [yellow]{result.files_deleted}[/yellow] files")
|
||||
logger.warning(f" Would delete: {result.files_deleted} files")
|
||||
else:
|
||||
# Normal mode: show actual actions
|
||||
console.print(f" Files copied: [bold]{result.files_copied}[/bold]")
|
||||
logger.info(f" Files copied: {result.files_copied}")
|
||||
if result.mode == 'versioned' and result.files_added > 0:
|
||||
console.print(f" Files added: [green]{result.files_added}[/green] (new)")
|
||||
console.print(f" Files skipped: [dim]{result.files_skipped}[/dim]")
|
||||
logger.info(f" Files added: {result.files_added} (new)")
|
||||
logger.info(f" Files skipped: {result.files_skipped}")
|
||||
if result.mode == 'versioned' and result.files_deleted == 0:
|
||||
console.print(f" Files deleted: [dim]{result.files_deleted}[/dim] [dim](cleanup disabled - keeps history)[/dim]")
|
||||
logger.info(f" Files deleted: {result.files_deleted} (cleanup disabled - keeps history)")
|
||||
else:
|
||||
console.print(f" Files deleted: [red]{result.files_deleted}[/red]")
|
||||
logger.info(f" Files deleted: {result.files_deleted}")
|
||||
|
||||
console.print(f" Errors: {status_style}{result.errors}[/]")
|
||||
console.print(f" Warnings: [yellow]{len(result.warnings)}[/yellow]")
|
||||
console.print(f" Duration: [blue]{duration.total_seconds():.2f}s[/blue]")
|
||||
console.print(f" Location: [dim]{backup_path}[/dim]")
|
||||
logger.info(f" Errors: {result.errors}")
|
||||
logger.info(f" Warnings: {len(result.warnings)}")
|
||||
logger.info(f" Duration: {duration.total_seconds():.2f}s")
|
||||
logger.info(f" Location: {backup_path}")
|
||||
|
||||
# Display detailed error information
|
||||
if result.critical_errors:
|
||||
console.print()
|
||||
console.print(f"[bold red]CRITICAL ERRORS ({len(result.critical_errors)}):[/bold red]")
|
||||
console.print("-" * 40)
|
||||
logger.error(f"CRITICAL ERRORS ({len(result.critical_errors)}):")
|
||||
logger.info("-" * 40)
|
||||
for i, error in enumerate(result.critical_errors, 1):
|
||||
console.print(f" {i}. [red]{error}[/red]")
|
||||
console.print()
|
||||
console.print("[bold]RECOVERY SUGGESTIONS:[/bold]")
|
||||
console.print(" - Check disk space and permissions")
|
||||
console.print(" - Ensure backup destination is accessible")
|
||||
console.print(" - Try running as administrator if permission issues")
|
||||
console.print(" - Check if antivirus is blocking file operations")
|
||||
logger.error(f" {i}. {error}")
|
||||
logger.info("RECOVERY SUGGESTIONS:")
|
||||
logger.info(" - Check disk space and permissions")
|
||||
logger.info(" - Ensure backup destination is accessible")
|
||||
logger.info(" - Try running as administrator if permission issues")
|
||||
logger.info(" - Check if antivirus is blocking file operations")
|
||||
|
||||
elif result.error_details:
|
||||
console.print()
|
||||
console.print(f"[bold red]ERRORS ({len(result.error_details)}):[/bold red]")
|
||||
console.print("-" * 40)
|
||||
logger.error(f"ERRORS ({len(result.error_details)}):")
|
||||
logger.info("-" * 40)
|
||||
for i, error in enumerate(result.error_details[:10], 1):
|
||||
console.print(f" {i}. [red]{error}[/red]")
|
||||
logger.error(f" {i}. {error}")
|
||||
if len(result.error_details) > 10:
|
||||
console.print(f" [dim]... and {len(result.error_details) - 10} more errors[/dim]")
|
||||
console.print()
|
||||
console.print("[bold]SUGGESTIONS:[/bold]")
|
||||
console.print(" - Some files may be in use - try closing applications")
|
||||
console.print(" - Check file permissions on failed files")
|
||||
logger.info(f" ... and {len(result.error_details) - 10} more errors")
|
||||
logger.info("SUGGESTIONS:")
|
||||
logger.info(" - Some files may be in use - try closing applications")
|
||||
logger.info(" - Check file permissions on failed files")
|
||||
|
||||
if result.warnings:
|
||||
console.print()
|
||||
console.print(f"[bold yellow]WARNINGS ({len(result.warnings)}):[/bold yellow]")
|
||||
console.print("-" * 40)
|
||||
logger.warning(f"WARNINGS ({len(result.warnings)}):")
|
||||
logger.info("-" * 40)
|
||||
for i, warning in enumerate(result.warnings[:5], 1):
|
||||
console.print(f" {i}. [yellow]{warning}[/yellow]")
|
||||
logger.warning(f" {i}. {warning}")
|
||||
if len(result.warnings) > 5:
|
||||
console.print(f" [dim]... and {len(result.warnings) - 5} more warnings[/dim]")
|
||||
logger.info(f" ... and {len(result.warnings) - 5} more warnings")
|
||||
|
||||
# Display project-specific skipped items
|
||||
tracked_items = filter_tracked_items_func(skipped_items)
|
||||
@@ -155,26 +127,24 @@ def display_backup_results(result: BackupResult, mode_config: dict, backup_path:
|
||||
total_all_skipped = len(skipped_items["directories"]) + len(skipped_items["files"])
|
||||
|
||||
if total_tracked > 0:
|
||||
console.print()
|
||||
console.print(f"[bold cyan]NOTABLE SKIPPED ITEMS ({total_tracked}):[/bold cyan]")
|
||||
console.print(f"[dim]Total ignored: {total_all_skipped}[/dim]")
|
||||
console.print("-" * 50)
|
||||
logger.info(f"NOTABLE SKIPPED ITEMS ({total_tracked}):")
|
||||
logger.info(f"Total ignored: {total_all_skipped}")
|
||||
logger.info("-" * 50)
|
||||
|
||||
if tracked_items["directories"]:
|
||||
console.print(f"[bold]Directories ({len(tracked_items['directories'])}):[/bold]")
|
||||
logger.info(f"Directories ({len(tracked_items['directories'])}):")
|
||||
for i, dir_path in enumerate(sorted(tracked_items["directories"]), 1):
|
||||
console.print(f" {i}. [dim]{dir_path}/[/dim]")
|
||||
logger.info(f" {i}. {dir_path}/")
|
||||
|
||||
if tracked_items["files"]:
|
||||
console.print(f"[bold]Files ({len(tracked_items['files'])}):[/bold]")
|
||||
logger.info(f"Files ({len(tracked_items['files'])}):")
|
||||
for i, file_path in enumerate(sorted(tracked_items["files"]), 1):
|
||||
console.print(f" {i}. [dim]{file_path}[/dim]")
|
||||
logger.info(f" {i}. {file_path}")
|
||||
else:
|
||||
console.print()
|
||||
if total_all_skipped > 0:
|
||||
console.print(f"[dim]No project-specific items skipped ({total_all_skipped} common items filtered)[/dim]")
|
||||
logger.info(f"No project-specific items skipped ({total_all_skipped} common items filtered)")
|
||||
else:
|
||||
console.print("[dim]No items were skipped.[/dim]")
|
||||
logger.info("No items were skipped.")
|
||||
|
||||
|
||||
# =============================================
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup_timestamps.py - Tracks last-run timestamps for all backup modes
|
||||
# Date: 2026-02-22
|
||||
# =================== AIPass ====================
|
||||
# Name: backup_timestamps.py
|
||||
# Description: Tracks last-run timestamps for all backup modes
|
||||
# Version: 1.0.0
|
||||
# Category: handlers/utils
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-22): Initial version - show/update backup timestamps
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handler utility: no console output, returns data for module layer
|
||||
# - JSON file at backups/backup_timestamps.json
|
||||
# Created: 2026-02-22
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: reauth_handler.py - Google Drive Re-Authentication Handler
|
||||
# Date: 2026-02-20
|
||||
# =================== AIPass ====================
|
||||
# Name: reauth_handler.py
|
||||
# Description: Google Drive Re-Authentication Handler
|
||||
# Version: 1.0.0
|
||||
# Category: backup_system/handlers/utils
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-20): Extracted from reauth_drive.py module
|
||||
# * Moved reauth() implementation to handler layer
|
||||
# * Follows seed 3-layer architecture standards
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers must be independent and transportable
|
||||
# - No prax imports (handler tier)
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2026-02-20
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,31 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: system_utils.py - Platform-aware file and console utilities
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: system_utils.py
|
||||
# Description: Platform-aware file and console utilities
|
||||
# Version: 2.1.1
|
||||
# Category: handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.1.1 (2025-11-23): CRITICAL FIX - Switch to plain print() for clickability
|
||||
# * Replaced console.print() with plain print() in safe_print()
|
||||
# * Rich console truncates at 80 chars breaking long paths
|
||||
# * Plain print() preserves full paths for terminal Ctrl+click
|
||||
# - v2.1.0 (2025-11-23): Attempted fix with no_wrap parameter (insufficient)
|
||||
# * Added no_wrap=True to console.print() but Rich still truncates
|
||||
# * Identified Rich console 80-char limit as root cause
|
||||
# - v2.0.0 (2025-11-16): Extracted to seed standards
|
||||
# * Applied seed standards formatting and meta header
|
||||
# * Preserved all logic from backup_utils v1.0.0
|
||||
# - v1.1.0 (2025-11-22): Updated to seed Rich formatting standards
|
||||
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
|
||||
# * Extracted system utilities
|
||||
# * Cross-platform file operations
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Handlers must be independent and transportable
|
||||
# - No cross-handler imports except within same domain
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -48,11 +26,11 @@ Key Functions:
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
from pathlib import Path
|
||||
from contextlib import contextmanager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# =============================================
|
||||
# CONSTANTS
|
||||
|
||||
@@ -1,25 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: backup_core.py - Main backup system orchestration module
|
||||
# Date: 2025-11-23
|
||||
# =================== AIPass ====================
|
||||
# Name: backup_core.py
|
||||
# Description: Main backup system orchestration module
|
||||
# Version: 2.1.0
|
||||
# Category: backup_system
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.1.0 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang, sys.path manipulation, prax/cli imports
|
||||
# * Uses standard logging and rich console
|
||||
# * Relative handler imports
|
||||
# * JSON_DIR uses path relative to __file__
|
||||
# - v2.0.4 (2025-11-23): CRITICAL FIX - Versioned dry-run accuracy
|
||||
# - v2.0.3 (2025-11-23): Enhanced dry-run with accurate statistics
|
||||
# - v2.0.2 (2025-11-23): CRITICAL FIX - Dry-run now shows proposed changes
|
||||
# - v2.0.1 (2025-11-23): CRITICAL BUG FIX - Dry-run statistics counter
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Orchestrate workflows, delegate to handlers
|
||||
# - Import handlers, never implement business logic
|
||||
# Created: 2025-11-23
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -48,14 +32,11 @@ Architecture Pattern:
|
||||
# Infrastructure
|
||||
import sys
|
||||
import datetime
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
console = Console()
|
||||
from aipass.cli.apps.modules import console
|
||||
from aipass.prax import logger
|
||||
|
||||
|
||||
def _header(text):
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: google_drive_sync.py - Google Drive Integration for AIPass Backup System
|
||||
# Date: 2025-10-30
|
||||
# =================== AIPass ====================
|
||||
# Name: google_drive_sync.py
|
||||
# Description: Google Drive Integration for AIPass Backup System
|
||||
# Version: 2.6.0
|
||||
# Category: backup_system/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries - remove oldest when adding new):
|
||||
# - v2.6.0 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang, sys.path manipulation, prax/cli imports
|
||||
# * Uses standard logging and rich console
|
||||
# * Relative handler imports, Google API deps wrapped in try/except
|
||||
# - v2.5.0 (2026-02-22): Rich progress bar for drive-sync uploads, per-file progress callback
|
||||
# - v2.4.0 (2026-02-21): Two-phase sync (prepare+upload), CLI visibility, dedup fix, --test mode
|
||||
# - v2.3.2 (2026-02-10): Fixed deepcopy RuntimeError in _save_data during concurrent uploads
|
||||
# - v2.2.0 (2026-02-10): Fixed SSL concurrency bug - per-thread credentials, retry with backoff, folder cache lock
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Module orchestrates, handlers implement
|
||||
# - CLI display (console.print) belongs here, not in handlers
|
||||
# - Google API calls delegated to drive_sync_client handler
|
||||
# Created: 2025-10-30
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -33,15 +18,10 @@ drive_sync_client handler for API operations.
|
||||
# =============================================
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from rich.console import Console
|
||||
from rich.progress import Progress, BarColumn, TextColumn, TimeElapsedColumn, TimeRemainingColumn
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
console = Console()
|
||||
from aipass.cli.apps.modules import console
|
||||
from aipass.prax import logger
|
||||
|
||||
_BACKUP_ROOT = Path(__file__).resolve().parents[2] # src/aipass/backup/
|
||||
|
||||
@@ -103,6 +83,11 @@ except ImportError:
|
||||
get_file_tracker_stats = None # type: ignore
|
||||
_test_drive_connection = None # type: ignore
|
||||
|
||||
from aipass.backup.apps.handlers.operations.sync_test_ops import (
|
||||
create_sync_test_files,
|
||||
cleanup_sync_test_dir,
|
||||
)
|
||||
|
||||
|
||||
def _show_file_tracker_stats() -> bool:
|
||||
"""Display file tracker statistics."""
|
||||
@@ -163,34 +148,23 @@ def _test_drive_sync() -> bool:
|
||||
|
||||
def _run_sync_test() -> bool:
|
||||
"""Run a small test sync to verify Drive integration."""
|
||||
import shutil
|
||||
|
||||
console.print("[bold cyan]Drive Sync Test[/bold cyan]")
|
||||
console.print()
|
||||
|
||||
# Create test files
|
||||
test_dir = _BACKUP_ROOT / "backups" / "_sync_test"
|
||||
test_dir.mkdir(parents=True, exist_ok=True)
|
||||
# Create test files via handler
|
||||
setup = create_sync_test_files(_BACKUP_ROOT)
|
||||
if not setup["success"]:
|
||||
console.print(f"[red]Failed to create test files: {setup['error']}[/red]")
|
||||
return False
|
||||
|
||||
test_files = {
|
||||
"test_file_1.txt": "Hello from AIPass backup test",
|
||||
"test_file_2.json": '{"test": true, "timestamp": "' + datetime.now().isoformat() + '"}',
|
||||
"subdir/nested_file.txt": "Nested directory test",
|
||||
"subdir/deep/deeper_file.md": "# Deep nested test\nVerifying folder structure",
|
||||
}
|
||||
|
||||
for name, content in test_files.items():
|
||||
path = test_dir / name
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content)
|
||||
|
||||
console.print(f" Created {len(test_files)} test files in {test_dir}")
|
||||
test_dir = setup["test_dir"]
|
||||
console.print(f" Created {setup['file_count']} test files in {test_dir}")
|
||||
|
||||
# Run sync
|
||||
sync = GoogleDriveSync()
|
||||
if not sync.authenticate():
|
||||
console.print("[red]Auth failed[/red]")
|
||||
shutil.rmtree(test_dir, ignore_errors=True)
|
||||
cleanup_sync_test_dir(test_dir)
|
||||
return False
|
||||
|
||||
console.print(f"\nScanning...")
|
||||
@@ -205,7 +179,7 @@ def _run_sync_test() -> bool:
|
||||
if not folder_id:
|
||||
error_msg = sync.last_error or "Unknown error"
|
||||
console.print(f"[red]FAILED: {error_msg}[/red]")
|
||||
shutil.rmtree(test_dir, ignore_errors=True)
|
||||
cleanup_sync_test_dir(test_dir)
|
||||
return False
|
||||
console.print(f" Drive folder ready: AIPass_Test")
|
||||
|
||||
@@ -225,7 +199,7 @@ def _run_sync_test() -> bool:
|
||||
|
||||
if result.get("error"):
|
||||
console.print(f"\n[red]FAILED: {result['error']}[/red]")
|
||||
shutil.rmtree(test_dir, ignore_errors=True)
|
||||
cleanup_sync_test_dir(test_dir)
|
||||
return False
|
||||
|
||||
console.print()
|
||||
@@ -243,8 +217,8 @@ def _run_sync_test() -> bool:
|
||||
else:
|
||||
console.print(f"[red]Dedup check failed: {len(files_to_upload2)} files flagged for re-upload[/red]")
|
||||
|
||||
# Cleanup local test dir
|
||||
shutil.rmtree(test_dir, ignore_errors=True)
|
||||
# Cleanup local test dir via handler
|
||||
cleanup_sync_test_dir(test_dir)
|
||||
console.print(f"\nCleaned up local test files")
|
||||
console.print(f"[dim]Test Drive folder 'AIPass_Test' left on Drive for inspection[/dim]")
|
||||
|
||||
@@ -423,6 +397,28 @@ def handle_command(args) -> bool:
|
||||
# CLI/EXECUTION
|
||||
# =============================================
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
console.print()
|
||||
console.print("google_drive_sync Module")
|
||||
console.print("Orchestrates Google Drive backup sync with two-phase upload pipeline")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/operations/")
|
||||
console.print(" - drive_sync_client.py (GoogleDriveSync — Drive API client and upload engine)")
|
||||
console.print(" - drive_sync_ops.py (clear_file_tracker — reset sync tracker cache)")
|
||||
console.print(" - drive_sync_ops.py (get_file_tracker_stats — tracker statistics)")
|
||||
console.print(" - drive_sync_ops.py (test_drive_connection — connectivity verification)")
|
||||
console.print(" - sync_test_ops.py (create_sync_test_files — generate test fixtures)")
|
||||
console.print(" - sync_test_ops.py (cleanup_sync_test_dir — remove test fixtures)")
|
||||
console.print(" handlers/json/")
|
||||
console.print(" - drive_sync_json.py (load_config — read module config JSON)")
|
||||
console.print(" - drive_sync_json.py (load_data — read module data JSON)")
|
||||
console.print(" handlers/utils/")
|
||||
console.print(" - backup_timestamps.py (get_timestamps, update_timestamp, format_age — backup timing)")
|
||||
console.print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
@@ -550,4 +546,4 @@ EXAMPLES:
|
||||
sys.exit(0)
|
||||
else:
|
||||
console.print("Google Drive sync test failed")
|
||||
sys.exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: integrations.py - External integrations and backup protection
|
||||
# Date: 2025-11-29
|
||||
# =================== AIPass ====================
|
||||
# Name: integrations.py
|
||||
# Description: External integrations and backup protection
|
||||
# Version: 2.1.0
|
||||
# Category: backup_system
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.1.0 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang, sys.path manipulation, prax/cli imports
|
||||
# * Uses standard logging and rich console
|
||||
# * Relative handler imports, GoogleDriveSync via sibling module
|
||||
# - v2.0.1 (2025-11-29): UX FIX - Import error and missing help output
|
||||
# - v2.0.0 (2025-11-16): Created seed-compliant layout module
|
||||
# - v1.1.0 (2025-10-30): Original backup_integrations features
|
||||
# - v1.0.0 (2025-10-14): Initial extraction
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follow seed 3-layer architecture
|
||||
# - Orchestrate workflows, delegate to handlers
|
||||
# - Import handlers, never implement business logic
|
||||
# Created: 2025-11-29
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -45,13 +30,10 @@ Architecture Pattern:
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
console = Console()
|
||||
from aipass.cli.apps.modules import console
|
||||
from aipass.prax import logger
|
||||
|
||||
|
||||
def _header(text):
|
||||
@@ -278,6 +260,21 @@ def print_help():
|
||||
safe_print("="*70)
|
||||
safe_print("")
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
console.print()
|
||||
console.print("integrations Module")
|
||||
console.print("External integrations and backup protection (Drive sync, read-only)")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/utils/")
|
||||
console.print(" - system_utils.py (safe_print — terminal-safe output wrapper)")
|
||||
console.print(" handlers/operations/")
|
||||
console.print(" - integration_ops.py (sync_to_drive — Drive upload orchestration)")
|
||||
console.print(" - integration_ops.py (set_backup_readonly — read-only permission setter)")
|
||||
console.print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""Display help when module is run directly."""
|
||||
import sys as _sys
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: reauth_drive.py - Google Drive Re-Authentication Module
|
||||
# Date: 2026-02-21
|
||||
# =================== AIPass ====================
|
||||
# Name: reauth_drive.py
|
||||
# Description: Google Drive Re-Authentication Module
|
||||
# Version: 1.2.0
|
||||
# Category: backup_system
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.2.0 (2026-03-06): Adapted for AIPass public repo
|
||||
# * Removed shebang, sys.path manipulation, prax/cli imports
|
||||
# * Uses standard logging and rich console
|
||||
# * Relative handler imports, Google API deps wrapped in try/except
|
||||
# - v1.1.0 (2026-02-21): Fixed handle_command() signature (command, args) → (args)
|
||||
# - v1.0.0 (2026-02-20): Initial version - standalone reauth utility
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers implement logic, modules orchestrate
|
||||
# Created: 2026-02-21
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -26,13 +15,10 @@ Delegates implementation to reauth_handler.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
console = Console()
|
||||
from aipass.cli.apps.modules import console
|
||||
from aipass.prax import logger
|
||||
|
||||
# Handler imports
|
||||
from aipass.backup.apps.handlers.utils.reauth_handler import reauth as _run_reauth
|
||||
@@ -139,6 +125,18 @@ def _execute_reauth() -> bool:
|
||||
return success
|
||||
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
console.print()
|
||||
console.print("reauth_drive Module")
|
||||
console.print("Google Drive re-authentication via console OAuth flow")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/utils/")
|
||||
console.print(" - reauth_handler.py (reauth — OAuth credential refresh and re-auth)")
|
||||
console.print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1 and sys.argv[1] in ['--help', '-h', 'help']:
|
||||
print_help()
|
||||
|
||||
Reference in New Issue
Block a user