mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 15:58:48 +00:00
Merge pull request #851 from PR0M3TH3AN/codex/revise-logging-configuration-and-wrap-ui-sections
Limit console logging noise during interactive prompts
This commit is contained in:
18
src/main.py
18
src/main.py
@@ -39,7 +39,7 @@ from utils import (
|
|||||||
)
|
)
|
||||||
from utils.clipboard import ClipboardUnavailableError
|
from utils.clipboard import ClipboardUnavailableError
|
||||||
from utils.atomic_write import atomic_write
|
from utils.atomic_write import atomic_write
|
||||||
from utils.logging_utils import ConsolePauseFilter
|
from utils.logging_utils import ConsolePauseFilter, pause_logging_for_ui
|
||||||
import queue
|
import queue
|
||||||
from local_bip85.bip85 import Bip85Error
|
from local_bip85.bip85 import Bip85Error
|
||||||
|
|
||||||
@@ -86,12 +86,6 @@ def configure_logging():
|
|||||||
"""Configure application-wide logging with queue-based handlers."""
|
"""Configure application-wide logging with queue-based handlers."""
|
||||||
global _queue_listener
|
global _queue_listener
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
for handler in logger.handlers[:]:
|
|
||||||
logger.removeHandler(handler)
|
|
||||||
|
|
||||||
log_directory = Path("logs")
|
log_directory = Path("logs")
|
||||||
log_directory.mkdir(parents=True, exist_ok=True)
|
log_directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@@ -99,7 +93,7 @@ def configure_logging():
|
|||||||
queue_handler = QueueHandler(log_queue)
|
queue_handler = QueueHandler(log_queue)
|
||||||
|
|
||||||
console_handler = logging.StreamHandler(sys.stderr)
|
console_handler = logging.StreamHandler(sys.stderr)
|
||||||
console_handler.setLevel(logging.ERROR)
|
console_handler.setLevel(logging.WARNING)
|
||||||
console_handler.addFilter(ConsolePauseFilter())
|
console_handler.addFilter(ConsolePauseFilter())
|
||||||
|
|
||||||
file_handler = logging.FileHandler(log_directory / "main.log")
|
file_handler = logging.FileHandler(log_directory / "main.log")
|
||||||
@@ -114,12 +108,17 @@ def configure_logging():
|
|||||||
_queue_listener = QueueListener(log_queue, console_handler, file_handler)
|
_queue_listener = QueueListener(log_queue, console_handler, file_handler)
|
||||||
_queue_listener.start()
|
_queue_listener.start()
|
||||||
|
|
||||||
logger.addHandler(queue_handler)
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
handlers=[queue_handler],
|
||||||
|
force=True,
|
||||||
|
)
|
||||||
|
|
||||||
logging.getLogger("monstr").setLevel(logging.WARNING)
|
logging.getLogger("monstr").setLevel(logging.WARNING)
|
||||||
logging.getLogger("nostr").setLevel(logging.WARNING)
|
logging.getLogger("nostr").setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def confirm_action(prompt: str) -> bool:
|
def confirm_action(prompt: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Prompts the user for confirmation.
|
Prompts the user for confirmation.
|
||||||
@@ -168,6 +167,7 @@ def get_notification_text(pm: PasswordManager) -> str:
|
|||||||
return color_text(getattr(note, "message", ""), category)
|
return color_text(getattr(note, "message", ""), category)
|
||||||
|
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_switch_fingerprint(password_manager: PasswordManager):
|
def handle_switch_fingerprint(password_manager: PasswordManager):
|
||||||
"""
|
"""
|
||||||
Handles switching the active fingerprint.
|
Handles switching the active fingerprint.
|
||||||
|
@@ -103,6 +103,7 @@ from mnemonic import Mnemonic
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from utils.fingerprint_manager import FingerprintManager
|
from utils.fingerprint_manager import FingerprintManager
|
||||||
|
from utils.logging_utils import pause_logging_for_ui
|
||||||
|
|
||||||
# Import NostrClient
|
# Import NostrClient
|
||||||
from nostr.client import NostrClient
|
from nostr.client import NostrClient
|
||||||
@@ -834,6 +835,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to load parent seed: {e}", "red"))
|
print(colored(f"Error: Failed to load parent seed: {e}", "red"))
|
||||||
raise SeedPassError(f"Failed to load parent seed: {e}") from e
|
raise SeedPassError(f"Failed to load parent seed: {e}") from e
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
@requires_unlocked
|
@requires_unlocked
|
||||||
def handle_switch_fingerprint(self, *, password: Optional[str] = None) -> bool:
|
def handle_switch_fingerprint(self, *, password: Optional[str] = None) -> bool:
|
||||||
return self.profile_service.handle_switch_fingerprint(password=password)
|
return self.profile_service.handle_switch_fingerprint(password=password)
|
||||||
@@ -894,6 +896,7 @@ class PasswordManager:
|
|||||||
self.update_activity()
|
self.update_activity()
|
||||||
self.start_background_sync()
|
self.start_background_sync()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_existing_seed(self, *, password: Optional[str] = None) -> None:
|
def handle_existing_seed(self, *, password: Optional[str] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Handles the scenario where an existing parent seed file is found.
|
Handles the scenario where an existing parent seed file is found.
|
||||||
@@ -980,6 +983,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to decrypt parent seed: {e}", "red"))
|
print(colored(f"Error: Failed to decrypt parent seed: {e}", "red"))
|
||||||
raise SeedPassError(f"Failed to decrypt parent seed: {e}") from e
|
raise SeedPassError(f"Failed to decrypt parent seed: {e}") from e
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_new_seed_setup(self) -> None:
|
def handle_new_seed_setup(self) -> None:
|
||||||
"""
|
"""
|
||||||
Handles the setup process when no existing parent seed is found.
|
Handles the setup process when no existing parent seed is found.
|
||||||
@@ -1881,9 +1885,11 @@ class PasswordManager:
|
|||||||
self.notify("Starting with a new, empty vault.", level="INFO")
|
self.notify("Starting with a new, empty vault.", level="INFO")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_password(self) -> None:
|
def handle_add_password(self) -> None:
|
||||||
self.entry_service.handle_add_password()
|
self.entry_service.handle_add_password()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_totp(self) -> None:
|
def handle_add_totp(self) -> None:
|
||||||
"""Add a TOTP entry either derived from the seed or imported."""
|
"""Add a TOTP entry either derived from the seed or imported."""
|
||||||
try:
|
try:
|
||||||
@@ -2025,6 +2031,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add TOTP: {e}", "red"))
|
print(colored(f"Error: Failed to add TOTP: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_ssh_key(self) -> None:
|
def handle_add_ssh_key(self) -> None:
|
||||||
"""Add an SSH key pair entry and display the derived keys."""
|
"""Add an SSH key pair entry and display the derived keys."""
|
||||||
try:
|
try:
|
||||||
@@ -2082,6 +2089,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add SSH key: {e}", "red"))
|
print(colored(f"Error: Failed to add SSH key: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_seed(self) -> None:
|
def handle_add_seed(self) -> None:
|
||||||
"""Add a derived BIP-39 seed phrase entry."""
|
"""Add a derived BIP-39 seed phrase entry."""
|
||||||
try:
|
try:
|
||||||
@@ -2151,6 +2159,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add seed phrase: {e}", "red"))
|
print(colored(f"Error: Failed to add seed phrase: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_pgp(self) -> None:
|
def handle_add_pgp(self) -> None:
|
||||||
"""Add a PGP key entry and display the generated key."""
|
"""Add a PGP key entry and display the generated key."""
|
||||||
try:
|
try:
|
||||||
@@ -2218,6 +2227,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add PGP key: {e}", "red"))
|
print(colored(f"Error: Failed to add PGP key: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_nostr_key(self) -> None:
|
def handle_add_nostr_key(self) -> None:
|
||||||
"""Add a Nostr key entry and display the derived keys."""
|
"""Add a Nostr key entry and display the derived keys."""
|
||||||
try:
|
try:
|
||||||
@@ -2277,6 +2287,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add Nostr key: {e}", "red"))
|
print(colored(f"Error: Failed to add Nostr key: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_key_value(self) -> None:
|
def handle_add_key_value(self) -> None:
|
||||||
"""Add a generic key/value entry."""
|
"""Add a generic key/value entry."""
|
||||||
try:
|
try:
|
||||||
@@ -2358,6 +2369,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to add key/value entry: {e}", "red"))
|
print(colored(f"Error: Failed to add key/value entry: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_add_managed_account(self) -> None:
|
def handle_add_managed_account(self) -> None:
|
||||||
"""Add a managed account seed entry."""
|
"""Add a managed account seed entry."""
|
||||||
try:
|
try:
|
||||||
@@ -3147,6 +3159,7 @@ class PasswordManager:
|
|||||||
print(colored("Error: Failed to retrieve the password.", "red"))
|
print(colored("Error: Failed to retrieve the password.", "red"))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_retrieve_entry(self) -> None:
|
def handle_retrieve_entry(self) -> None:
|
||||||
"""Prompt for an index and display the corresponding entry."""
|
"""Prompt for an index and display the corresponding entry."""
|
||||||
try:
|
try:
|
||||||
@@ -3181,6 +3194,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to retrieve password: {e}", "red"))
|
print(colored(f"Error: Failed to retrieve password: {e}", "red"))
|
||||||
pause()
|
pause()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_modify_entry(self) -> None:
|
def handle_modify_entry(self) -> None:
|
||||||
"""
|
"""
|
||||||
Handles modifying an existing password entry by prompting the user for the index number
|
Handles modifying an existing password entry by prompting the user for the index number
|
||||||
@@ -3621,6 +3635,7 @@ class PasswordManager:
|
|||||||
logging.error(f"Error during modifying entry: {e}", exc_info=True)
|
logging.error(f"Error during modifying entry: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to modify entry: {e}", "red"))
|
print(colored(f"Error: Failed to modify entry: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_search_entries(self) -> None:
|
def handle_search_entries(self) -> None:
|
||||||
"""Prompt for a query, list matches and optionally show details."""
|
"""Prompt for a query, list matches and optionally show details."""
|
||||||
try:
|
try:
|
||||||
@@ -3830,6 +3845,7 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
print("-" * 40)
|
print("-" * 40)
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_list_entries(self) -> None:
|
def handle_list_entries(self) -> None:
|
||||||
self.menu_handler.handle_list_entries()
|
self.menu_handler.handle_list_entries()
|
||||||
|
|
||||||
@@ -3870,6 +3886,7 @@ class PasswordManager:
|
|||||||
logging.error(f"Error during entry deletion: {e}", exc_info=True)
|
logging.error(f"Error during entry deletion: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to delete entry: {e}", "red"))
|
print(colored(f"Error: Failed to delete entry: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_archive_entry(self) -> None:
|
def handle_archive_entry(self) -> None:
|
||||||
"""Archive an entry without deleting it."""
|
"""Archive an entry without deleting it."""
|
||||||
try:
|
try:
|
||||||
@@ -3888,6 +3905,7 @@ class PasswordManager:
|
|||||||
logging.error(f"Error archiving entry: {e}", exc_info=True)
|
logging.error(f"Error archiving entry: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to archive entry: {e}", "red"))
|
print(colored(f"Error: Failed to archive entry: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_view_archived_entries(self) -> None:
|
def handle_view_archived_entries(self) -> None:
|
||||||
"""Display archived entries and optionally view or restore them."""
|
"""Display archived entries and optionally view or restore them."""
|
||||||
try:
|
try:
|
||||||
@@ -3955,9 +3973,11 @@ class PasswordManager:
|
|||||||
logging.error(f"Error viewing archived entries: {e}", exc_info=True)
|
logging.error(f"Error viewing archived entries: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to view archived entries: {e}", "red"))
|
print(colored(f"Error: Failed to view archived entries: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_display_totp_codes(self) -> None:
|
def handle_display_totp_codes(self) -> None:
|
||||||
self.menu_handler.handle_display_totp_codes()
|
self.menu_handler.handle_display_totp_codes()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_verify_checksum(self) -> None:
|
def handle_verify_checksum(self) -> None:
|
||||||
"""
|
"""
|
||||||
Handles verifying the script's checksum against the stored checksum to ensure integrity.
|
Handles verifying the script's checksum against the stored checksum to ensure integrity.
|
||||||
@@ -3997,6 +4017,7 @@ class PasswordManager:
|
|||||||
logging.error(f"Error during checksum verification: {e}", exc_info=True)
|
logging.error(f"Error during checksum verification: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to verify checksum: {e}", "red"))
|
print(colored(f"Error: Failed to verify checksum: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_update_script_checksum(self) -> None:
|
def handle_update_script_checksum(self) -> None:
|
||||||
"""Generate a new checksum for the manager script."""
|
"""Generate a new checksum for the manager script."""
|
||||||
if not confirm_action("Generate new script checksum? (Y/N): "):
|
if not confirm_action("Generate new script checksum? (Y/N): "):
|
||||||
@@ -4142,6 +4163,7 @@ class PasswordManager:
|
|||||||
logging.error(f"Failed to restore backup: {e}", exc_info=True)
|
logging.error(f"Failed to restore backup: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to restore backup: {e}", "red"))
|
print(colored(f"Error: Failed to restore backup: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_export_database(
|
def handle_export_database(
|
||||||
self,
|
self,
|
||||||
dest: Path | None = None,
|
dest: Path | None = None,
|
||||||
@@ -4184,6 +4206,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to export database: {e}", "red"))
|
print(colored(f"Error: Failed to export database: {e}", "red"))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_import_database(self, src: Path) -> None:
|
def handle_import_database(self, src: Path) -> None:
|
||||||
"""Import a portable database file, replacing the current index."""
|
"""Import a portable database file, replacing the current index."""
|
||||||
|
|
||||||
@@ -4266,6 +4289,7 @@ class PasswordManager:
|
|||||||
print(colored("Database imported successfully.", "green"))
|
print(colored("Database imported successfully.", "green"))
|
||||||
self.sync_vault()
|
self.sync_vault()
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_export_totp_codes(self) -> Path | None:
|
def handle_export_totp_codes(self) -> Path | None:
|
||||||
"""Export all 2FA codes to a JSON file for other authenticator apps."""
|
"""Export all 2FA codes to a JSON file for other authenticator apps."""
|
||||||
try:
|
try:
|
||||||
@@ -4336,6 +4360,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Error: Failed to export 2FA codes: {e}", "red"))
|
print(colored(f"Error: Failed to export 2FA codes: {e}", "red"))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_backup_reveal_parent_seed(
|
def handle_backup_reveal_parent_seed(
|
||||||
self, file: Path | None = None, *, password: Optional[str] = None
|
self, file: Path | None = None, *, password: Optional[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@@ -10,6 +10,7 @@ from .entry_types import EntryType, ALL_ENTRY_TYPES
|
|||||||
import seedpass.core.manager as manager_module
|
import seedpass.core.manager as manager_module
|
||||||
from utils.color_scheme import color_text
|
from utils.color_scheme import color_text
|
||||||
from utils.terminal_utils import clear_header_with_notification
|
from utils.terminal_utils import clear_header_with_notification
|
||||||
|
from utils.logging_utils import pause_logging_for_ui
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover - typing only
|
if TYPE_CHECKING: # pragma: no cover - typing only
|
||||||
from .manager import PasswordManager
|
from .manager import PasswordManager
|
||||||
@@ -21,6 +22,7 @@ class MenuHandler:
|
|||||||
def __init__(self, manager: PasswordManager) -> None:
|
def __init__(self, manager: PasswordManager) -> None:
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_list_entries(self) -> None:
|
def handle_list_entries(self) -> None:
|
||||||
"""List entries and optionally show details."""
|
"""List entries and optionally show details."""
|
||||||
pm = self.manager
|
pm = self.manager
|
||||||
@@ -86,6 +88,7 @@ class MenuHandler:
|
|||||||
logging.error(f"Failed to list entries: {e}", exc_info=True)
|
logging.error(f"Failed to list entries: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to list entries: {e}", "red"))
|
print(colored(f"Error: Failed to list entries: {e}", "red"))
|
||||||
|
|
||||||
|
@pause_logging_for_ui
|
||||||
def handle_display_totp_codes(self) -> None:
|
def handle_display_totp_codes(self) -> None:
|
||||||
"""Display all stored TOTP codes with a countdown progress bar."""
|
"""Display all stored TOTP codes with a countdown progress bar."""
|
||||||
pm = self.manager
|
pm = self.manager
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
_console_paused = False
|
_console_paused = False
|
||||||
|
|
||||||
@@ -22,3 +24,24 @@ def resume_console_logging() -> None:
|
|||||||
"""Resume logging to console handlers."""
|
"""Resume logging to console handlers."""
|
||||||
global _console_paused
|
global _console_paused
|
||||||
_console_paused = False
|
_console_paused = False
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def console_logging_paused() -> None:
|
||||||
|
"""Context manager to pause console logging within a block."""
|
||||||
|
pause_console_logging()
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
resume_console_logging()
|
||||||
|
|
||||||
|
|
||||||
|
def pause_logging_for_ui(func):
|
||||||
|
"""Decorator to pause console logging while ``func`` executes."""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
with console_logging_paused():
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
Reference in New Issue
Block a user