Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédente | |||
| python:pyinvoke [2017/11/28 19:25] – marc dexet | python:pyinvoke [2017/11/28 20:56] (Version actuelle) – marc dexet | ||
|---|---|---|---|
| Ligne 4: | Ligne 4: | ||
| [[http:// | [[http:// | ||
| - | |||
| - | Il repose sur la définition des tâches (//task//) via l' | ||
| - | Ces tâches sont définies au sein d'un fichier // | ||
| - | |||
| - | // | ||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def remove_all(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke -l | ||
| - | Available tasks: | ||
| - | |||
| - | remove-all | ||
| - | |||
| - | $ invoke remove-all | ||
| - | $ | ||
| - | </ | ||
| - | |||
| - | ===== Mise en oeuvre ===== | ||
| - | |||
| - | Création de l' | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/Workdirs$ virtualenv -p python3 test_invoke | ||
| - | Running virtualenv with interpreter / | ||
| - | Using base prefix '/ | ||
| - | New python executable in / | ||
| - | Also creating executable in / | ||
| - | Installing setuptools, pip, wheel...done. | ||
| - | $ ~/Workdirs$ cd test_invoke/ | ||
| - | $ ~/ | ||
| - | </ | ||
| - | |||
| - | Installation de pyInvoke | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/ | ||
| - | Collecting invoke | ||
| - | Downloading invoke-0.21.0-py3-none-any.whl (153kB) | ||
| - | 100% |████████████████████████████████| 153kB 3.9MB/ | ||
| - | Installing collected packages: invoke | ||
| - | Successfully installed invoke-0.21.0 | ||
| - | |||
| - | </ | ||
| - | |||
| - | ===== Créer une tâche ===== | ||
| - | |||
| - | Pour créer une tâche il suffit | ||
| - | |||
| - | * de créer un fichier // | ||
| - | * de créer une fonction qui prend //au moins// un // | ||
| - | * et de l' | ||
| - | |||
| - | <code python> | ||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | .... | ||
| - | | ||
| - | </ | ||
| - | |||
| - | Une tâche peut exécuter une fonction python //ou// une commande système avec // | ||
| - | |||
| - | **Appel de fonction** | ||
| - | <code python> | ||
| - | def do_it_right(): | ||
| - | // | ||
| - | |||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | | ||
| - | | ||
| - | </ | ||
| - | |||
| - | **Appel de commande système** | ||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | ===== Ordonnancement des tâches ===== | ||
| - | |||
| - | Un tâche peut nécessiter plusieurs taches en amont et/ou en aval du processus. | ||
| - | |||
| - | Pour modéliser cet enchaînement, | ||
| - | |||
| - | * ses prédécesseurs avec la propriété // | ||
| - | * et ses successeurs avec la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | La succession des tâches s' | ||
| - | |||
| - | * une exception est levée | ||
| - | * une commande système ( // | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | a = 10/0 | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Traceback (most recent call last): | ||
| - | File "/ | ||
| - | sys.exit(program.run()) | ||
| - | ... | ||
| - | File "/ | ||
| - | a = 10/0 | ||
| - | ZeroDivisionError: | ||
| - | </ | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | raise Exit(' | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | hostname not found | ||
| - | </ | ||
| - | |||
| - | ==== Tâche par défaut ==== | ||
| - | |||
| - | Pour désigner une tâche par défaut, il suffit de lui donner la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(default=True) | ||
| - | def build(ctx): | ||
| - | ... | ||
| - | |||
| - | </ | ||
| - | |||
| - | ==== Exemple complet d' | ||
| - | |||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def clean_workdir(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def compile_project(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def deploy_artefact(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def update_website(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task( | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Commit | ||
| - | Building | ||
| - | Deploy | ||
| - | Update website | ||
| - | </ | ||
| - | |||
| - | |||
| - | ====== Aperçu de Invoke (pyinvoke) ====== | ||
| - | |||
| - | Invoke est un **ordonnanceur** et un **exécuteur** de tâches. | ||
| Il repose sur la définition des tâches (//task//) via l' | Il repose sur la définition des tâches (//task//) via l' | ||
| Ligne 519: | Ligne 321: | ||
| ctx.run(" | ctx.run(" | ||
| </ | </ | ||
| - | |||
| - | ====== Invoke (pyinvoke) ====== | ||
| - | |||
| - | [[http:// | ||
| - | |||
| - | |||
| - | Il repose sur la définition des tâches (//task//) via l' | ||
| - | Ces tâches sont définies au sein d'un fichier // | ||
| - | |||
| - | // | ||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def remove_all(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke -l | ||
| - | Available tasks: | ||
| - | |||
| - | remove-all | ||
| - | |||
| - | $ invoke remove-all | ||
| - | $ | ||
| - | </ | ||
| - | |||
| - | ===== Mise en oeuvre ===== | ||
| - | |||
| - | Création de l' | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/Workdirs$ virtualenv -p python3 test_invoke | ||
| - | Running virtualenv with interpreter / | ||
| - | Using base prefix '/ | ||
| - | New python executable in / | ||
| - | Also creating executable in / | ||
| - | Installing setuptools, pip, wheel...done. | ||
| - | $ ~/Workdirs$ cd test_invoke/ | ||
| - | $ ~/ | ||
| - | </ | ||
| - | |||
| - | Installation de pyInvoke | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/ | ||
| - | Collecting invoke | ||
| - | Downloading invoke-0.21.0-py3-none-any.whl (153kB) | ||
| - | 100% |████████████████████████████████| 153kB 3.9MB/ | ||
| - | Installing collected packages: invoke | ||
| - | Successfully installed invoke-0.21.0 | ||
| - | |||
| - | </ | ||
| - | |||
| - | ===== Créer une tâche ===== | ||
| - | |||
| - | Pour créer une tâche il suffit | ||
| - | |||
| - | * de créer un fichier // | ||
| - | * de créer une fonction qui prend //au moins// un // | ||
| - | * et de l' | ||
| - | |||
| - | <code python> | ||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | .... | ||
| - | | ||
| - | </ | ||
| - | |||
| - | Une tâche peut exécuter une fonction python //ou// une commande système avec // | ||
| - | |||
| - | **Appel de fonction** | ||
| - | <code python> | ||
| - | def do_it_right(): | ||
| - | // | ||
| - | |||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | | ||
| - | | ||
| - | </ | ||
| - | |||
| - | **Appel de commande système** | ||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | ===== Ordonnancement des tâches ===== | ||
| - | |||
| - | Un tâche peut nécessiter plusieurs taches en amont et/ou en aval du processus. | ||
| - | |||
| - | Pour modéliser cet enchaînement, | ||
| - | |||
| - | * ses prédécesseurs avec la propriété // | ||
| - | * et ses successeurs avec la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | La succession des tâches s' | ||
| - | |||
| - | * une exception est levée | ||
| - | * une commande système ( // | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | a = 10/0 | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Traceback (most recent call last): | ||
| - | File "/ | ||
| - | sys.exit(program.run()) | ||
| - | ... | ||
| - | File "/ | ||
| - | a = 10/0 | ||
| - | ZeroDivisionError: | ||
| - | </ | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | raise Exit(' | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | hostname not found | ||
| - | </ | ||
| - | |||
| - | ==== Tâche par défaut ==== | ||
| - | |||
| - | Pour désigner une tâche par défaut, il suffit de lui donner la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(default=True) | ||
| - | def build(ctx): | ||
| - | ... | ||
| - | |||
| - | </ | ||
| - | |||
| - | ==== Exemple complet d' | ||
| - | |||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def clean_workdir(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def compile_project(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def deploy_artefact(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def update_website(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task( | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Commit | ||
| - | Building | ||
| - | Deploy | ||
| - | Update website | ||
| - | </ | ||
| - | |||
| - | |||
| - | ====== Aperçu de Invoke (pyinvoke) ====== | ||
| - | |||
| - | Invoke est un **ordonnanceur** et un **exécuteur** de tâches. | ||
| - | |||
| - | Il repose sur la définition des tâches (//task//) via l' | ||
| - | Ces tâches sont définies au sein d'un fichier // | ||
| - | |||
| - | // | ||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def remove_all(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke -l | ||
| - | Available tasks: | ||
| - | |||
| - | remove-all | ||
| - | |||
| - | $ invoke remove-all | ||
| - | $ | ||
| - | </ | ||
| - | |||
| - | ===== Mise en oeuvre ===== | ||
| - | |||
| - | Création de l' | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/Workdirs$ virtualenv -p python3 test_invoke | ||
| - | Running virtualenv with interpreter / | ||
| - | Using base prefix '/ | ||
| - | New python executable in / | ||
| - | Also creating executable in / | ||
| - | Installing setuptools, pip, wheel...done. | ||
| - | $ ~/Workdirs$ cd test_invoke/ | ||
| - | $ ~/ | ||
| - | </ | ||
| - | |||
| - | Installation de pyInvoke | ||
| - | |||
| - | <code bash> | ||
| - | $ ~/ | ||
| - | Collecting invoke | ||
| - | Downloading invoke-0.21.0-py3-none-any.whl (153kB) | ||
| - | 100% |████████████████████████████████| 153kB 3.9MB/ | ||
| - | Installing collected packages: invoke | ||
| - | Successfully installed invoke-0.21.0 | ||
| - | |||
| - | </ | ||
| - | |||
| - | ===== Créer une tâche ===== | ||
| - | |||
| - | Pour créer une tâche il suffit | ||
| - | |||
| - | * de créer un fichier // | ||
| - | * de créer une fonction qui prend //au moins// un // | ||
| - | * et de l' | ||
| - | |||
| - | <code python> | ||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | .... | ||
| - | | ||
| - | </ | ||
| - | |||
| - | Une tâche peut exécuter une fonction python //ou// une commande système avec // | ||
| - | |||
| - | **Appel de fonction** | ||
| - | <code python> | ||
| - | def do_it_right(): | ||
| - | // | ||
| - | |||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | | ||
| - | | ||
| - | </ | ||
| - | |||
| - | **Appel de commande système** | ||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | ===== Ordonnancement des tâches ===== | ||
| - | |||
| - | Un tâche peut nécessiter plusieurs taches en amont et/ou en aval du processus. | ||
| - | |||
| - | Pour modéliser cet enchaînement, | ||
| - | |||
| - | * ses prédécesseurs avec la propriété // | ||
| - | * et ses successeurs avec la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(pre=[clean_workdir, | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | La succession des tâches s' | ||
| - | |||
| - | * une exception est levée | ||
| - | * une commande système ( // | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | a = 10/0 | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Traceback (most recent call last): | ||
| - | File "/ | ||
| - | sys.exit(program.run()) | ||
| - | ... | ||
| - | File "/ | ||
| - | a = 10/0 | ||
| - | ZeroDivisionError: | ||
| - | </ | ||
| - | |||
| - | **Exemple d' | ||
| - | <code python> | ||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | raise Exit(' | ||
| - | print(' | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | hostname not found | ||
| - | </ | ||
| - | |||
| - | ==== Tâche par défaut ==== | ||
| - | |||
| - | Pour désigner une tâche par défaut, il suffit de lui donner la propriété // | ||
| - | |||
| - | <code python> | ||
| - | @task(default=True) | ||
| - | def build(ctx): | ||
| - | ... | ||
| - | |||
| - | </ | ||
| - | |||
| - | ==== Exemple complet d' | ||
| - | |||
| - | <code python> | ||
| - | from invoke import task | ||
| - | |||
| - | @task | ||
| - | def clean_workdir(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def get_last_commit(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def compile_project(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def deploy_artefact(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task | ||
| - | def update_website(ctx): | ||
| - | print(' | ||
| - | |||
| - | @task( | ||
| - | post=[deploy_artefact, | ||
| - | def build(ctx): | ||
| - | | ||
| - | </ | ||
| - | |||
| - | <code bash> | ||
| - | $ invoke build | ||
| - | Clean workdir | ||
| - | Get last commit | ||
| - | Commit | ||
| - | Building | ||
| - | Deploy | ||
| - | Update website | ||
| - | </ | ||
| - | |||
| - | |||
| - | ===== Exemples ===== | ||
| - | |||
| - | ==== Convertir en PDF des fichiers asciidoc ==== | ||
| - | |||
| - | Imaginons un projet avec | ||
| - | * un répertoire // | ||
| - | * un répertoire // | ||
| - | * un listing de fichiers dans // | ||
| - | |||
| - | Décomposons le workflow. | ||
| - | |||
| - | Il faut | ||
| - | |||
| - | * générer un document // | ||
| - | * générer un PDF dans // | ||
| - | * avant il faut s' | ||
| - | |||
| - | <code python> | ||
| - | from invoke import task | ||
| - | import os | ||
| - | import shutil | ||
| - | from mako.template import Template | ||
| - | |||
| - | work_dirname = '/ | ||
| - | |||
| - | |||
| - | def collectfilenames(path): | ||
| - | """ | ||
| - | Collect full qualified names of file within path. | ||
| - | :param path: directory to scan | ||
| - | :return: full qualified filenames from this path | ||
| - | """ | ||
| - | path_list = [] | ||
| - | for dirpath, _, files_name in os.walk(path): | ||
| - | for name in files_name: | ||
| - | path_list.append(" | ||
| - | return path_list | ||
| - | |||
| - | |||
| - | def recreate_dir(dirname): | ||
| - | """ | ||
| - | Remove and recreate dirname | ||
| - | :param dirname: | ||
| - | """ | ||
| - | if os.path.exists(dirname): | ||
| - | shutil.rmtree(dirname) | ||
| - | os.makedirs(dirname) | ||
| - | |||
| - | |||
| - | @task | ||
| - | def move_in_tempdir(ctx): | ||
| - | recreate_dir(work_dirname) | ||
| - | with ctx.cd(' | ||
| - | ctx.run(' | ||
| - | |||
| - | |||
| - | @task(pre=[move_in_tempdir]) | ||
| - | def create_listing(ctx): | ||
| - | with open(' | ||
| - | listing.write(Template(filename=' | ||
| - | |||
| - | |||
| - | @task(move_in_tempdir, | ||
| - | def generate_pdf(ctx): | ||
| - | with ctx.cd(work_dirname): | ||
| - | ctx.run(' | ||
| - | |||
| - | |||
| - | @task(pre=[generate_pdf], | ||
| - | def copy_to_builddir(ctx): | ||
| - | dirname = ' | ||
| - | |||
| - | recreate_dir(dirname) | ||
| - | with ctx.cd(dirname): | ||
| - | ctx.run(' | ||
| - | |||
| - | </ | ||
| - | |||
| - | ===== FAQ ===== | ||
| - | |||
| - | |||
| - | ==== Comment récupérer le résultat d'une tâche ? ==== | ||
| - | |||
| - | Si une tâche doit retourner un résultat pour la tâche suivante, comment le passer ? | ||
| - | Apparemment il n'est pas possible de transmettre un résultat par l' | ||
| - | |||
| - | Le seul moyen est de peut-être utiliser un dictionnaire de stockage global. | ||
| - | |||
| - | |||
| - | <code python> | ||
| - | |||
| - | storage = {} | ||
| - | |||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | | ||
| - | |||
| - | |||
| - | @task(pre=[do_something]) | ||
| - | def use_something(ctx): | ||
| - | bar = storage[' | ||
| - | </ | ||
| - | |||
| - | ==== Comment répondre à une commande interactive ? ==== | ||
| - | |||
| - | //Exemple tiré de la documentation officielle// | ||
| - | |||
| - | Supposons que nous ayons une commande qui demande des informations de façon interactive : | ||
| - | |||
| - | < | ||
| - | $ excitable-program | ||
| - | When you give the OK, I'm going to do the things. All of them!! | ||
| - | Are you ready? [Y/n] y | ||
| - | OK! I just did all sorts of neat stuff. You're welcome! Bye! | ||
| - | </ | ||
| - | |||
| - | Pour cela il faut utiliser un // | ||
| - | |||
| - | <code python> | ||
| - | responder = Responder(pattern=r" | ||
| - | ctx.run(" | ||
| - | </ | ||
| - | ==== Comment récupérer le résultat d'une tâche ? ==== | ||
| - | |||
| - | Si une tâche doit retourner un résultat pour la tâche suivante, comment le passer ? | ||
| - | Apparemment il n'est pas possible de transmettre un résultat par l' | ||
| - | |||
| - | Le seul moyen est de peut-être utiliser un dictionnaire de stockage global. | ||
| - | |||
| - | |||
| - | <code python> | ||
| - | |||
| - | storage = {} | ||
| - | |||
| - | @task | ||
| - | def do_something(ctx): | ||
| - | | ||
| - | |||
| - | |||
| - | @task(pre=[do_something]) | ||
| - | def use_something(ctx): | ||
| - | bar = storage[' | ||
| - | </ | ||
| - | |||
| - | ==== Comment répondre à une commande interactive ? ==== | ||
| - | |||
| - | //Exemple tiré de la documentation officielle// | ||
| - | |||
| - | Supposons que nous ayons une commande qui demande des informations de façon interactive : | ||
| - | |||
| - | < | ||
| - | $ excitable-program | ||
| - | When you give the OK, I'm going to do the things. All of them!! | ||
| - | Are you ready? [Y/n] y | ||
| - | OK! I just did all sorts of neat stuff. You're welcome! Bye! | ||
| - | </ | ||
| - | |||
| - | Pour cela il faut utiliser un // | ||
| - | |||
| - | <code python> | ||
| - | responder = Responder(pattern=r" | ||
| - | ctx.run(" | ||
| - | </ | ||
| - | |||
| - | |||
| - | {{tag> | ||