87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
"""Contrôle d'exécution.
|
|
"""
|
|
|
|
__all__ = ('Status', 'OK_STATUS', 'ERROR_STATUS',
|
|
'Exit', 'exit', 'die')
|
|
|
|
import sys
|
|
|
|
from .base import isnum
|
|
from .output import eerror
|
|
|
|
class Status:
|
|
"""Un objet qui peut être utilisé pour retourner un status pour l'exécution
|
|
d'un programme ou d'une opération.
|
|
|
|
Le status peut être OK ou ERROR. La valeur booléenne de cet objet est True
|
|
ou False en fonction de la valeur du status. Un code de retour de programme
|
|
associé est disponible avec la propriété exitcode.
|
|
"""
|
|
|
|
ok = True
|
|
exitcode = 0
|
|
def __init__(self, ok=None, exitcode=None):
|
|
if ok is not None:
|
|
self.ok = ok
|
|
if exitcode is None:
|
|
if ok: exitcode = 0
|
|
else: exitcode = 1
|
|
self.exitcode = exitcode
|
|
elif exitcode is not None:
|
|
self.ok = exitcode == 0
|
|
self.exitcode = exitcode
|
|
|
|
def __nonzero__(self):
|
|
return self.ok
|
|
|
|
OK_STATUS = Status(True)
|
|
ERROR_STATUS = Status(False)
|
|
|
|
def ensure_status(status):
|
|
"""Retourner une instance de Status.
|
|
|
|
Si status est un entier, le prendre comme valeur de retour.
|
|
Sinon, le considérer comme une valeur booléenne indiquant le status: OK ou ERREUR.
|
|
"""
|
|
if isinstance(status, Status): return status
|
|
elif isnum(status): return Status(exitcode=int(status))
|
|
else: return Status(status)
|
|
|
|
class Exit(Exception):
|
|
"""Classe qui peut être utilisée pour propager un code de retour quand on
|
|
quitte l'application.
|
|
"""
|
|
def __init__(self, status):
|
|
self.exitcode = ensure_status(status).exitcode
|
|
|
|
def exit(status=OK_STATUS):
|
|
"""Quitter le programme avec l'exception Exit, en propageant par défaut le
|
|
status OK_STATUS.
|
|
"""
|
|
raise Exit(status)
|
|
|
|
def die(msg=None, status=ERROR_STATUS):
|
|
"""Quitter le programme en affichant un message d'erreur, en propageant
|
|
par défaut le status ERROR_STATUS.
|
|
|
|
Si msg==None, on prend le message de la dernière exception capturée.
|
|
"""
|
|
eerror(msg)
|
|
raise Exit(status)
|
|
|
|
def enable_exit_control():
|
|
"""Installer un excepthook qui appelle sys.exit() quand on lève l'exception
|
|
Exit.
|
|
"""
|
|
prev_excepthook = sys.excepthook
|
|
if prev_excepthook is sys.__excepthook__:
|
|
prev_excepthook = None
|
|
def exit(cls, obj, tb, prev_excepthook=prev_excepthook):
|
|
if issubclass(cls, Exit): sys.exit(obj.exitcode)
|
|
elif prev_excepthook is not None:
|
|
prev_excepthook(cls, obj, tb)
|
|
else: sys.__excepthook__(cls, obj, tb)
|
|
sys.excepthook = exit
|