Client SSH/SFTP personnel pour Windows
Reunit en un seul outil les fonctions utiles de MobaXterm, Termius et Bitvise, sans compte ni service tiers, avec toutes les donnees en local. - Terminaux multi-onglets : sessions SSH et terminaux Windows locaux (PowerShell / cmd) via la pseudo-console native ConPTY - Gestionnaire de fichiers SFTP facon WinSCP : double panneau, colonnes triables, glisser-deposer, renommage, permissions, file de transferts. Ouvrable sur une connexion en cours sans creer de favori - Gestion des cles SSH : generation Ed25519/RSA, import, export - Gestion du fichier known_hosts, avec remplacement guide d'une cle d'hote modifiee (cas frequent des serveurs en DHCP) - Trois themes (clair, bleu nuit, noir), commutables a chaud - Authentification automatique reprenant le comportement de la commande ssh (agent SSH et cles ~/.ssh), mot de passe demande seulement en secours Aucun mot de passe n'est stocke sur le disque. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
49
app/paths.py
Normal file
49
app/paths.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""Emplacements des donnees et des ressources, valables en mode script comme en .exe.
|
||||
|
||||
Point d'attention : une fois l'application figee par PyInstaller, `__file__` pointe vers
|
||||
un dossier temporaire (`sys._MEIPASS`) que Windows supprime a la fermeture. Y ecrire les
|
||||
sessions, les cles ou known_hosts reviendrait a les perdre a chaque sortie. Les donnees
|
||||
utilisateur vont donc a cote de l'executable (mode portable), avec repli sur %APPDATA%
|
||||
si cet emplacement n'est pas accessible en ecriture (installation dans Program Files,
|
||||
lancement depuis un support en lecture seule...).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
FROZEN = getattr(sys, "frozen", False)
|
||||
|
||||
|
||||
def _app_dir() -> Path:
|
||||
"""Dossier de l'executable (mode figé) ou racine du projet (mode script)."""
|
||||
if FROZEN:
|
||||
return Path(sys.executable).resolve().parent
|
||||
return Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def _resolve_resources() -> Path:
|
||||
if FROZEN:
|
||||
bundled = getattr(sys, "_MEIPASS", None)
|
||||
if bundled: # onefile : ressources extraites dans un dossier temporaire
|
||||
return Path(bundled) / "resources"
|
||||
return _app_dir() / "resources"
|
||||
|
||||
|
||||
def _resolve_data() -> Path:
|
||||
candidate = _app_dir() / "data"
|
||||
try:
|
||||
candidate.mkdir(parents=True, exist_ok=True)
|
||||
probe = candidate / ".write_test"
|
||||
probe.write_text("", encoding="utf-8")
|
||||
probe.unlink()
|
||||
return candidate
|
||||
except OSError:
|
||||
fallback = Path(os.environ.get("APPDATA") or Path.home()) / "PySSHClient"
|
||||
fallback.mkdir(parents=True, exist_ok=True)
|
||||
return fallback
|
||||
|
||||
|
||||
RESOURCES_DIR = _resolve_resources()
|
||||
DATA_DIR = _resolve_data()
|
||||
Reference in New Issue
Block a user