Qualite : pyproject.toml (ruff/pytest/pyright) + CI Gitea (lint/tests/build)
pyproject.toml devient le point d'entree unique de configuration des outils
(pytest.ini supprime, sa config y est deplacee). Les dependances restent dans
requirements.txt/requirements-dev.txt (deja utilises par setup.bat) plutot que
dupliquees ici : ce projet se distribue par PyInstaller, pas par "pip install".
ruff : configure puis passe sur tout app/ + tests/ (154 corrections
automatiques, purement mecaniques - tri des imports, imports multiples sur une
ligne separes, alias depreciees) suivies de 7 corrections manuelles ciblees :
- app/ssh_connection.py : `raise ... from None` pour le refus explicite de
passphrase (ce n'est pas un echec a diagnostiquer).
- app/controllers/workspace_manager.py : zip() sans strict= documente en
commentaire (deliberement tolerant a un workspace legerement perime).
- tests/test_ai_redaction.py : nom de variable ambigu renomme.
- E702 (construction compacte "widget = X(); widget.setY(...)" dans
sftp_panel.py/tunnel_dialog.py) et E402 (quelques tests qui importent un
symbole juste avant la section qui l'utilise) : ignores explicitement, ce
sont des styles deliberes preexistants, pas des oublis.
`ruff check app main.py tests` est desormais propre.
pyright : mode "basic" (le code n'a jamais ete type). Plus de 200 signalements
sur ~300 etaient le meme faux positif connu de l'ecosysteme PySide6 (acces
plat aux enums Qt, ex. Qt.UserRole, valide a l'execution mais que les stubs ne
reconnaissent que sous leur forme imbriquee) : desactive avec justification en
commentaire. Reste un socle de 77 signalements reels (surtout des acces
Optional non filtres dans app/ui/tabs.py et app/ssh_connection.py) : non
corrige dans cette phase - resserrer le typage la ou pyright a raison est un
travail a part, pas une consequence automatique de l'ajout de l'outil. La CI
le lance en mode informatif (continue-on-error) tant que ce socle n'est pas
resorbe.
.gitea/workflows/ci.yml : lint (ruff, bloquant), tests (pytest, bloquant),
typecheck (pyright, informatif), build (PyInstaller, sur main uniquement,
artefact du dossier portable). Necessite un runner Gitea Actions Windows
enregistre - PySide6/pywinpty/Credential Manager/ACL NTFS sont Windows
uniquement, comme l'application elle-meme ; non verifiable depuis ce poste.
Suite complete revalidee apres coup (33/33) pour confirmer qu'aucune des 154
corrections automatiques n'a modifie de comportement.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,13 @@ from __future__ import annotations
|
||||
import re
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTextEdit, QPushButton, QLabel, QApplication,
|
||||
QApplication,
|
||||
QDialog,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QTextEdit,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
_CODE_BLOCK_RE = re.compile(r"```(?:[a-zA-Z0-9_+-]*\n)?(.*?)```", re.DOTALL)
|
||||
|
||||
@@ -6,8 +6,8 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
from app.app_settings import get_setting, set_setting
|
||||
from app.ai.redaction import detect_secrets
|
||||
from app.app_settings import get_setting, set_setting
|
||||
|
||||
_NOTICE_ACK_KEY = "ai_notice_acknowledged"
|
||||
|
||||
|
||||
@@ -4,13 +4,21 @@ compatibles avec l'API OpenAI (OpenAI, OpenRouter, proxy interne, LLM local...).
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QFormLayout, QLineEdit, QCheckBox, QDoubleSpinBox,
|
||||
QPushButton, QDialogButtonBox, QMessageBox, QLabel,
|
||||
QCheckBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.ai.settings import AISettings, load_ai_settings, save_ai_settings, load_api_key, save_api_key
|
||||
from app.ai.provider import OpenAICompatibleProvider
|
||||
from app.ai.service import KIND_TEST, AIRequestWorker
|
||||
from app.ai.settings import AISettings, load_ai_settings, load_api_key, save_ai_settings, save_api_key
|
||||
from app.credentials import CredentialStore, NullCredentialStore
|
||||
|
||||
|
||||
|
||||
@@ -3,17 +3,36 @@ d'une nouvelle session dans ce dossier (voir app.groups)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QFormLayout, QLineEdit, QSpinBox, QComboBox, QDialogButtonBox,
|
||||
QHBoxLayout, QPushButton, QWidget, QVBoxLayout, QCheckBox, QStackedWidget, QLabel,
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFormLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QPushButton,
|
||||
QSpinBox,
|
||||
QStackedWidget,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from app.session_manager import (
|
||||
SessionStore, BastionConfig, AUTH_AUTO, AUTH_KEY, AUTH_PASSWORD, AUTH_AGENT,
|
||||
BASTION_NONE, BASTION_SESSION, BASTION_OPENSSH, BASTION_MANUAL,
|
||||
)
|
||||
from app.key_manager import KeyManager
|
||||
from app.groups import GroupSettings, GroupSettingsStore
|
||||
from app.key_manager import KeyManager
|
||||
from app.openssh.config import load_openssh_hosts
|
||||
from app.session_manager import (
|
||||
AUTH_AGENT,
|
||||
AUTH_AUTO,
|
||||
AUTH_KEY,
|
||||
AUTH_PASSWORD,
|
||||
BASTION_MANUAL,
|
||||
BASTION_NONE,
|
||||
BASTION_OPENSSH,
|
||||
BASTION_SESSION,
|
||||
BastionConfig,
|
||||
SessionStore,
|
||||
)
|
||||
|
||||
|
||||
class GroupSettingsDialog(QDialog):
|
||||
|
||||
@@ -5,13 +5,28 @@ from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QListWidget, QListWidgetItem, QPushButton,
|
||||
QMessageBox, QFileDialog, QFormLayout, QLineEdit, QComboBox, QSpinBox,
|
||||
QDialogButtonBox, QApplication, QLabel,
|
||||
QApplication,
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFileDialog,
|
||||
QFormLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QListWidget,
|
||||
QListWidgetItem,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QSpinBox,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.key_manager import (
|
||||
KeyManager, KEY_TYPE_ED25519, KEY_TYPE_RSA, KEY_TYPE_LABELS, KEY_TYPE_DESCRIPTIONS,
|
||||
KEY_TYPE_DESCRIPTIONS,
|
||||
KEY_TYPE_LABELS,
|
||||
KEY_TYPE_RSA,
|
||||
KeyManager,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -3,8 +3,15 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QTreeWidgetItem, QPushButton,
|
||||
QMessageBox, QLabel, QAbstractItemView,
|
||||
QAbstractItemView,
|
||||
QDialog,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QTreeWidget,
|
||||
QTreeWidgetItem,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.known_hosts_manager import KnownHostsStore
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
snippets et actions, avec recherche floue et navigation entierement au clavier."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Callable
|
||||
|
||||
from PySide6.QtCore import Qt, QEvent
|
||||
from PySide6.QtCore import QEvent, Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QLineEdit, QListWidget, QListWidgetItem, QMessageBox,
|
||||
QDialog,
|
||||
QLineEdit,
|
||||
QListWidget,
|
||||
QListWidgetItem,
|
||||
QMessageBox,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.openssh.config import load_openssh_hosts
|
||||
@@ -111,9 +116,9 @@ class QuickConnectDialog(QDialog):
|
||||
return results
|
||||
|
||||
def _quick_actions(self) -> list[tuple[str, Callable[[], None]]]:
|
||||
from app.dialogs.workspace_dialog import WorkspaceDialog
|
||||
from app.dialogs.snippet_dialog import SnippetManagerDialog
|
||||
from app.dialogs.key_dialog import KeyManagerDialog
|
||||
from app.dialogs.snippet_dialog import SnippetManagerDialog
|
||||
from app.dialogs.workspace_dialog import WorkspaceDialog
|
||||
|
||||
return [
|
||||
("Nouvelle session...", self.session_controller.new_session),
|
||||
|
||||
@@ -3,20 +3,44 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QFormLayout, QLineEdit, QSpinBox, QComboBox, QDialogButtonBox,
|
||||
QHBoxLayout, QPushButton, QTextEdit, QFileDialog, QWidget, QVBoxLayout,
|
||||
QCheckBox, QMessageBox, QGroupBox, QStackedWidget, QCompleter,
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
QCompleter,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFileDialog,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
QLineEdit,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QSpinBox,
|
||||
QStackedWidget,
|
||||
QTextEdit,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from app.session_manager import (
|
||||
Session, SessionStore, BastionConfig, AUTH_AUTO, AUTH_KEY, AUTH_PASSWORD, AUTH_AGENT,
|
||||
BASTION_NONE, BASTION_SESSION, BASTION_OPENSSH, BASTION_MANUAL,
|
||||
PASSWORD_STORAGE_NONE, PASSWORD_STORAGE_SECURE,
|
||||
)
|
||||
from app.credentials import CredentialStore, NullCredentialStore, session_credential_key
|
||||
from app.groups import GroupSettingsStore
|
||||
from app.key_manager import KeyManager
|
||||
from app.openssh.config import load_openssh_hosts
|
||||
from app.groups import GroupSettingsStore
|
||||
from app.credentials import CredentialStore, NullCredentialStore, session_credential_key
|
||||
from app.session_manager import (
|
||||
AUTH_AGENT,
|
||||
AUTH_AUTO,
|
||||
AUTH_KEY,
|
||||
AUTH_PASSWORD,
|
||||
BASTION_MANUAL,
|
||||
BASTION_NONE,
|
||||
BASTION_OPENSSH,
|
||||
BASTION_SESSION,
|
||||
PASSWORD_STORAGE_NONE,
|
||||
PASSWORD_STORAGE_SECURE,
|
||||
BastionConfig,
|
||||
Session,
|
||||
SessionStore,
|
||||
)
|
||||
|
||||
|
||||
class SessionDialog(QDialog):
|
||||
|
||||
@@ -4,8 +4,19 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QTreeWidgetItem, QPushButton,
|
||||
QMessageBox, QLineEdit, QLabel, QFormLayout, QTextEdit, QDialogButtonBox, QComboBox,
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFormLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QTextEdit,
|
||||
QTreeWidget,
|
||||
QTreeWidgetItem,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.snippets import Snippet, SnippetStore
|
||||
|
||||
@@ -3,8 +3,19 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QTreeWidget, QTreeWidgetItem,
|
||||
QPushButton, QComboBox, QSpinBox, QLineEdit, QLabel, QMessageBox, QAbstractItemView,
|
||||
QAbstractItemView,
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QFormLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QSpinBox,
|
||||
QTreeWidget,
|
||||
QTreeWidgetItem,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.tunnels import DIRECTION_DYNAMIC, DIRECTION_LABELS, TunnelManager, describe
|
||||
|
||||
@@ -3,12 +3,20 @@ from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QListWidget, QListWidgetItem, QPushButton,
|
||||
QMessageBox, QInputDialog, QLabel, QCheckBox,
|
||||
QCheckBox,
|
||||
QDialog,
|
||||
QHBoxLayout,
|
||||
QInputDialog,
|
||||
QLabel,
|
||||
QListWidget,
|
||||
QListWidgetItem,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from app.app_settings import get_setting, set_setting
|
||||
from app.controllers.workspace_manager import WorkspaceManager, SETTING_RESTORE_ON_STARTUP
|
||||
from app.controllers.workspace_manager import SETTING_RESTORE_ON_STARTUP, WorkspaceManager
|
||||
|
||||
|
||||
class WorkspaceDialog(QDialog):
|
||||
|
||||
Reference in New Issue
Block a user