Extrait les appels macOS derriere le contrat Systeme

- systeme/macos.py : SystemeMacOS (sons afplay, modificateurs Quartz, chemins,
  verrou d'instance fcntl) implementant le contrat Systeme.
- systeme/__init__.py : choisir_systeme() fabrique selon sys.platform,
  refuse clairement une plateforme inconnue.
- core.py : verrou d'instance (fcntl, LOCK_PATH, acquire_single_instance_lock)
  retire ; import os retire aussi, verifie inutilise ailleurs dans le fichier.
- app.py : passe par choisir_systeme().acquerir_verrou_instance(dossier_donnees()
  + instance.lock) au lieu de core.acquire_single_instance_lock. Seul changement
  dans ce fichier, nom de fichier inchange.
- tests/test_single_instance.py : reoriente vers choisir_systeme(), memes
  assertions et meme nombre de tests.
- tests/test_systeme.py (nouveau) : verrou du test_le_verrou_refuse_une_seconde_prise
  garde desormais la reference au premier verrou — sans variable, CPython le
  garbage-collectait entre les deux assert (refcount 0 -> fermeture -> verrou
  relache), le test passait pour la mauvaise raison.

89 tests verts (84 + 5).
This commit is contained in:
2026-08-23 17:57:52 +02:00
parent 434944def6
commit 5c4477fe1d
6 changed files with 125 additions and 43 deletions
+9 -9
View File
@@ -13,7 +13,7 @@ bug — quel que soit le nombre de bundles présents, la 2e instance renonce.
import os
import tempfile
from core import acquire_single_instance_lock
from systeme import choisir_systeme
def _tmp_lock():
@@ -21,31 +21,31 @@ def _tmp_lock():
def test_premiere_instance_obtient_le_verrou():
handle = acquire_single_instance_lock(_tmp_lock())
handle = choisir_systeme().acquerir_verrou_instance(_tmp_lock())
assert handle is not None
def test_deuxieme_instance_est_refusee():
path = _tmp_lock()
premier = acquire_single_instance_lock(path)
premier = choisir_systeme().acquerir_verrou_instance(path)
assert premier is not None
assert acquire_single_instance_lock(path) is None
assert choisir_systeme().acquerir_verrou_instance(path) is None
def test_verrou_repris_apres_liberation():
path = _tmp_lock()
premier = acquire_single_instance_lock(path)
premier = choisir_systeme().acquerir_verrou_instance(path)
premier.close()
assert acquire_single_instance_lock(path) is not None
assert choisir_systeme().acquerir_verrou_instance(path) is not None
def test_cree_le_dossier_parent_manquant():
path = _tmp_lock()
assert not os.path.isdir(os.path.dirname(path))
acquire_single_instance_lock(path)
choisir_systeme().acquerir_verrou_instance(path)
assert os.path.isdir(os.path.dirname(path))
def test_deux_chemins_differents_ne_se_genent_pas():
assert acquire_single_instance_lock(_tmp_lock()) is not None
assert acquire_single_instance_lock(_tmp_lock()) is not None
assert choisir_systeme().acquerir_verrou_instance(_tmp_lock()) is not None
assert choisir_systeme().acquerir_verrou_instance(_tmp_lock()) is not None
+39
View File
@@ -0,0 +1,39 @@
"""La fabrique rend une implémentation conforme au contrat Systeme."""
import os
import tempfile
import pytest
from systeme import choisir_systeme
def test_la_fabrique_rend_une_implementation_complete():
s = choisir_systeme()
for methode in ("jouer_son", "modificateurs_enfonces", "raccourci_defaut",
"chemin_log", "dossier_donnees", "acquerir_verrou_instance"):
assert callable(getattr(s, methode)), f"{methode} manque"
def test_une_plateforme_inconnue_est_refusee_clairement():
with pytest.raises(NotImplementedError) as e:
choisir_systeme(plateforme="haiku-os")
assert "haiku-os" in str(e.value)
def test_le_raccourci_macos_est_celui_d_aujourd_hui():
assert choisir_systeme(plateforme="darwin").raccourci_defaut() == "<cmd>+<ctrl>+d"
def test_le_verrou_refuse_une_seconde_prise():
s = choisir_systeme()
chemin = os.path.join(tempfile.mkdtemp(), "sous-dossier", "z.lock")
# Référence gardée : sinon CPython ramasse l'objet fichier dès la fin de
# l'assert (refcount à 0), ce qui referme le fichier et relâche le verrou
# AVANT la seconde prise — le test passerait pour la mauvaise raison.
verrou = s.acquerir_verrou_instance(chemin)
assert verrou is not None
assert s.acquerir_verrou_instance(chemin) is None
def test_aucun_modificateur_enfonce_pendant_les_tests():
assert choisir_systeme().modificateurs_enfonces() is False