4360
Commentaire:
|
4497
Il en reste sûrement plein…
|
Texte supprimé. | Texte ajouté. |
Ligne 8: | Ligne 8: |
En tant qu'utilisateur vous pouver l'utiliser en lançant sur zamok | En tant qu'utilisateur vous pouvez l'utiliser en lançant sur zamok |
Ligne 15: | Ligne 15: |
Pour info, crans_lc accèpte des argument pour faciliter les tests et le debug : | Pour info, crans_lc accepte des arguments pour faciliter les tests et le debug : |
Ligne 34: | Ligne 34: |
Tout le monde peux utiliser la base de test, utilisez là pour faire vos tests en utilisant de script pour le découvrir. Vous êtes sûr de l'utiliser s'il est inscrit en haut du menu principal : {{{Vous êtes connecté en tant que login sur la base de test}}}. |
Tout le monde peut utiliser la base de test. ## Utilisez la pour faire vos tests en utilisant de script pour le découvrir. ### Elle veut dire quelque chose cette phrase ? -- NativeeKing <<DateTime(2015-03-04T14:11:07+0100)>> Vous êtes sûr de l'utiliser s'il est inscrit en haut du menu principal : {{{Vous êtes connectés en tant que login sur la base de test}}}. |
Ligne 40: | Ligne 42: |
Pour l'immense majorité du code, gest_crans_lc est écrit [[https://en.wikipedia.org/wiki/Continuation-passing_style|Continuation-passing style]], c'est a dire qu'au lieu de retourner une valeur, on passe a chaque fonction un (ou plusieurs) callback qu'elle devrait appeler a la fin de son exécution. | Pour l'immense majorité du code, gest_crans_lc est écrit [[https://en.wikipedia.org/wiki/Continuation-passing_style|Continuation-passing style]], c'est-à-dire qu'au lieu de retourner une valeur, on passe à chaque fonction un (ou plusieurs) callback qu'elle doit appeler à la fin de son exécution. |
Ligne 42: | Ligne 44: |
Cela est implémenter ici grâce à deux classe : * {{{TailCall}}} qui représente un callback : une fonction et ses argument. Les arguments peuvent être modifié après l'initialisation en appelant un {{{TailCall}}} comme une fonction. * {{{Continue}}} un exception. En levant un {{{Continue}}} avec comme argument un {{{TailCall}}}, la fonction du {{{TailCall}}} est ensuite exécuter sur les arguments contenu dans le {{{TailCall}}} |
Cela est implémenté ici grâce à deux classes : * {{{TailCall}}} qui représente un callback : une fonction et ses arguments. Les arguments peuvent être modifiés après l'initialisation en appelant un {{{TailCall}}} comme une fonction. * {{{Continue}}} qui représente une exception. En levant un {{{Continue}}} avec comme argument un {{{TailCall}}}, la fonction du {{{TailCall}}} est ensuite exécutée sur les arguments contenus dans le {{{TailCall}}} |
Ligne 49: | Ligne 51: |
* une fonciton gérant les valeurs retourné par dialog, généralement appelée {{{todo}}} | * une fonction gérant les valeurs retournées par dialog, généralement appelée {{{todo}}} |
Ligne 80: | Ligne 82: |
Dans l'exemple ici en cas d'annulation, on exécute le {{{TailCall}}} {{{cont}}} (sans doute retourner au menu parent), en cas d'erreur, elle est affiché par {{{handle_dialog_result}}} puis {{{retry_cont}}} est appelé : la fonction est réexécuté et l'utilisateur peut corriger les informations a l'origine de l'exception. | Dans l'exemple ici en cas d'annulation, on exécute le {{{TailCall}}} {{{cont}}} (sans doute retourner au menu parent), en cas d'erreur, elle est affichée par {{{handle_dialog_result}}} puis {{{retry_cont}}} est appelé : la fonction est réexécutée et l'utilisateur peut corriger les informations à l'origine de l'exception. |
Ligne 82: | Ligne 84: |
Si {{{todo}}} est exécuté, on retourne en exécutant le {{{TailCall}}} {{{cont}}} en y mettant certain paramètres à jour (par exemple l'objet que l'on vient de modifier). | Si {{{todo}}} est exécuté, on retourne en exécutant le {{{TailCall}}} {{{cont}}} en y mettant certains paramètres à jour (par exemple l'objet que l'on vient de modifier). |
Ligne 84: | Ligne 86: |
Comme vous avez pu le remarquez, on ne se préoccupe absolument pas de savoir d'où vient la fonction et où elle va. On appel juste la continuation lorsqu'on a fini ce qu'on avait a faire et tout se passe bien. | Comme vous avez pu le remarquer, on ne se préoccupe absolument pas de savoir d'où vient la fonction et où elle va. On appel juste la continuation lorsqu'on a fini ce qu'on avait à faire et tout se passe bien. |
gest_crans_lc
Il s'agit du programme visant à remplacer l'ancien gest_crans en utilisant le nouveau binding ldap.
En tant qu'utilisateur vous pouvez l'utiliser en lançant sur zamok
samir@zamok $ crans_lc
au lien de la commande crans.
Pour info, crans_lc accepte des arguments pour faciliter les tests et le debug :
samir@zamok $ crans_lc -h [sudo] password for samir on zamok: usage: gest_crans_lc.py [-h] [--test] [--debug] [login] Interface utilisateur du système de gestion des machines et adhérents du crans positional arguments: login Se connecter en tant qu'un autre utilisateur optional arguments: -h, --help show this help message and exit --test Utiliser la base de test --debug Afficher des info de débug comme les tracebacks
Tout le monde peut utiliser la base de test.
Vous êtes sûr de l'utiliser s'il est inscrit en haut du menu principal : Vous êtes connectés en tant que login sur la base de test.
Seule les nounous peuvent utiliser le script en tant qu'un autre utilisateur.
Paradigme de programmation
Pour l'immense majorité du code, gest_crans_lc est écrit Continuation-passing style, c'est-à-dire qu'au lieu de retourner une valeur, on passe à chaque fonction un (ou plusieurs) callback qu'elle doit appeler à la fin de son exécution.
Cela est implémenté ici grâce à deux classes :
TailCall qui représente un callback : une fonction et ses arguments. Les arguments peuvent être modifiés après l'initialisation en appelant un TailCall comme une fonction.
Continue qui représente une exception. En levant un Continue avec comme argument un TailCall, la fonction du TailCall est ensuite exécutée sur les arguments contenus dans le TailCall
Une fonction affichant un menu dialog
Une fonction utilisant dialogue se compose en général de deux sous fonctions :
une fonction gérant l'affichage du menu dialog, généralement appelé box
une fonction gérant les valeurs retournées par dialog, généralement appelée todo
Ça nous donne :
def ma_fonction(self, …, cont, …): def box(box_arg1, …): … return self.dialog.WIDGET(args1, …) def todo(todo_arg1, …, cont): … raise Continue(cont(cont_argn=togo_argk)) retry_cont = TailCall(self.ma_fonction, …, cont=cont, …) (code, output) = self.handle_dialog(cont, box, box_arg1, …) return self.handle_dialog_result( code=code, output=output, cancel_cont=cont, error_cont=retry_cont, codes_todo=[ ([self.dialog.DIALOG_OK], todo, [todo_arg1, …, cont]), ] )
Les fonctions handle_dialog et handle_dialog_result permettent de gérer sans peine les rattrapages d'exception, ctrl-C ou ESC.
Généralement, les codes de retour de dialog sont binaire (ok ou annuler), s'il y en a d'autre, les ajouter à la liste codes_todo avec une autre fonction todo pour les prendre en charge.
Dans l'exemple ici en cas d'annulation, on exécute le TailCall cont (sans doute retourner au menu parent), en cas d'erreur, elle est affichée par handle_dialog_result puis retry_cont est appelé : la fonction est réexécutée et l'utilisateur peut corriger les informations à l'origine de l'exception.
Si todo est exécuté, on retourne en exécutant le TailCall cont en y mettant certains paramètres à jour (par exemple l'objet que l'on vient de modifier).
Comme vous avez pu le remarquer, on ne se préoccupe absolument pas de savoir d'où vient la fonction et où elle va. On appel juste la continuation lorsqu'on a fini ce qu'on avait à faire et tout se passe bien. Cela permet d'utiliser plus facilement la même fonction à plusieurs endroit du code et de construire naturellement des chaînes d'annulation (tu annules, j'exécute cont, qui fera de même si tu annules encore).