Skip to content

Instantly share code, notes, and snippets.

@jmquintana79
Last active September 22, 2024 13:33
Show Gist options
  • Save jmquintana79/e9061a9bab1b07cf73d8fd511e503b69 to your computer and use it in GitHub Desktop.
Save jmquintana79/e9061a9bab1b07cf73d8fd511e503b69 to your computer and use it in GitHub Desktop.
Este es la libreria de Python que voy a usar como sustituto de *Makefiles*. *Invoke* es util para: - Make task commands. - Run shells commands.

Invoke Commands - Getting started

References

Commands

  • invoke = inv: Comando principal que solo funciona donde hay un fichero tasks.py.
  • invoke --help / -h: Listar opciones del comando invoke.
  • invoke --list / -l: Lista de tareas disponibles en el fichero tasks.py.

Task boolean parameters

Script tasks.py:

from invoke import task

@task
def build(c):
    print("Building!")

@task
def clean(c, all=False):
    if all:
        print("Cleaning all!")
    else:
        print("Cleaning!")
    
@task(help = {"all":"Si se quiere limpiar todo.", 
              "only_one":"Si se quiere limpiar solo uno."})
def clean2(c, all=False, only_one = False):
    if all:
        print("Cleaning all!")
    elif only_one:
        print("Cleaning only-one.")
    else:
        print("Cleaning!")

Comandos para realizar estas tareas:

  • invoke build: Devuelve Building!.
  • invoke clean: Devuelve Cleaning!.
  • invoke clean --all / -a: Devuelve Cleaning all!.
  • invoke clean2 --help / -h: Develve...
Options:
  -a, --all        Si se quiere limpiar todo.
  -o, --only-one   Si se quiere limpiar solo uno.

Running shell commands + Argument with required input

Script taskds.py:

from invoke import task

@task
def hello(c, who = ""):
    if who == "":
        msg = "hello world!!"
    else:
        msg = f"hello {who}!!"
    c.run(f"echo '{msg}'")

Comandos para usar esta tarea:

  • invoke hello: Devuelve Hello world!!.
  • invoke hello --who / -w: Devuelve Hello world!!.
  • invoke hello --who "Juan" / -w "Juan": Devuelve Hello Juan!!.

Declaring pre/post-tasks

Script tasks.py:

from invoke import task

@task
def build(c):
    print("Building!")

@task(build) # <--------------------------- Opcion 1 pre
def clean(c, all=False):
    if all:
        print("Cleaning all!")
    else:
        print("Cleaning!")

@task(pre=[build], post=[clean2])  # <----- Opcion 2 pre/post
def hello(c, who = ""):
    if who == "":
        msg = "hello world!!"
    else:
        msg = f"hello {who}!!"
    c.run(f"echo '{msg}'")

Comandos para usar esta tarea:

  • invoke clean: Devuelve...
Building!
Cleaning!
  • invoke hello: Devuelve...
Building!
hello world!!
Cleaning!

Creating namespaces to add "external" tasks

Script others.py:

from invoke import task

@task
def other(c):
    print("I am other task")

Script tasks.py:

from invoke import task, Collection
import others

@task
def build(c):
    print("Building!")

namespace = Collection(others, build)

Comandos para usar esta tarea:

  • invoke --list: Devuelve...
Available tasks:

  build
  others.other
  • invoke others.other: Devuelve I am other task.

Review Invoke : Command Runner

En la librería invoke, el método run es utilizado para ejecutar comandos en la línea de comandos desde un script de Python. Los argumentos más importantes de este método son:

  1. command: (requerido) Es el comando que se va a ejecutar como una cadena de texto.

  2. hide: (opcional) Puede ser un booleano o una lista de streams ('stdout', 'stderr' o 'both'). Controla si la salida del comando se oculta o no. Si se establece en True, oculta toda la salida.

  3. pty: (opcional) Es un booleano. Indica si se debe utilizar un pseudo terminal para ejecutar el comando, lo que puede ser necesario para comandos interactivos como sudo.

  4. echo: (opcional) Es un booleano. Si es True, imprime el comando antes de ejecutarlo.

  5. warn: (opcional) Es un booleano. Si es True, no se lanza una excepción si el comando retorna un código de salida distinto de 0, lo que permite manejar errores manualmente.

  6. env: (opcional) Es un diccionario. Permite especificar variables de entorno que se usarán durante la ejecución del comando.

  7. timeout: (opcional) Es un número que especifica el tiempo máximo, en segundos, para que el comando se ejecute antes de ser terminado.

  8. encoding: (opcional) Especifica la codificación de los datos de salida.

  9. in_stream, out_stream, err_stream: (opcionales) Pueden ser usados para redirigir los flujos de entrada, salida o error estándar del proceso.

Ejemplo

from invoke import run

cmd = "echo 'hello world!!!'"
result = run(cmd, 
             hide=True, 
             warn=True, 
             timeout = 60 # seconds
             )

print(result.env)
print(result.shell, result.command)
print(result.ok, result.failed)
print(result.stdout.splitlines()[-1])
print(result.stderr)

# [out]:
# {'COMMAND_MODE': 'unix2003', 'CONDA_DEFAULT_ENV': 'analysis', 'CONDA_EXE': '/Users/juan/miniconda3/bin/conda', 'CONDA_PREFIX': '/Users/juan/miniconda3/envs/analysis', 'CONDA_PROMPT_MODIFIER': '(analysis) ', 'CONDA_PYTHON_EXE': '/Users/juan/miniconda3/bin/python', 'CONDA_SHLVL': '2', 'DISPLAY': '/private/tmp/com.apple.launchd.TAd4mgl1fA/org.macosforge.xquartz:0', 'HOME': '/Users/juan', 'LOCAL_GIT_DIRECTORY': '/Applications/GitHub Desktop.app/Contents/Resources/app/git', 'LOGNAME': 'juan', 'MallocNanoZone': '0', 'ORIGINAL_XDG_CURRENT_DESKTOP': 'undefined', 'PATH': '/Users/juan/miniconda3/envs/analysis/bin:/usr/local/sbin:/usr/local/opt/python/libexec/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/juan/miniconda3/envs/analysis/bin:/Users/juan/miniconda3/condabin:/usr/local/sbin:/usr/local/opt/python/libexec/bin', 'PWD': '/', 'SHELL': '/bin/bash', 'SHLVL': '4', 'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.RTBTivf6lA/Listeners', 'TMPDIR': '/var/folders/vk/s0y7mtzs23vgwd0s7jck3c_80000gn/T/', 'USER': 'juan', 'VSCODE_AMD_ENTRYPOINT': 'vs/workbench/api/node/extensionHostProcess', 'VSCODE_CODE_CACHE_PATH': '/Users/juan/Library/Application Support/Code/CachedData/af28b32d7e553898b2a91af498b1fb666fdebe0c', 'VSCODE_CRASH_REPORTER_PROCESS_TYPE': 'extensionHost', 'VSCODE_CWD': '/', 'VSCODE_HANDLES_UNCAUGHT_ERRORS': 'true', 'VSCODE_IPC_HOOK': '/Users/juan/Library/Application Support/Code/1.85-main.sock', 'VSCODE_NLS_CONFIG': '{"locale":"en-gb","osLocale":"en-es","availableLanguages":{},"_languagePackSupport":true}', 'VSCODE_PID': '740', 'XPC_FLAGS': '0x0', 'XPC_SERVICE_NAME': '0', '_': '/usr/local/opt/python/libexec/bin/python', '__CFBundleIdentifier': 'com.microsoft.VSCode', '__CF_USER_TEXT_ENCODING': '0x1F5:0x0:0x0', 'ELECTRON_RUN_AS_NODE': '1', 'VSCODE_L10N_BUNDLE_LOCATION': '', 'PYTHONUNBUFFERED': '1', 'PYTHONIOENCODING': 'utf-8', '_CE_CONDA': '', 'CONDA_PREFIX_1': '/Users/juan/miniconda3', 'CONDA_ROOT': '/Users/juan/miniconda3', '_CE_M': '', 'LC_CTYPE': 'UTF-8', 'PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING': '1', 'PYDEVD_USE_FRAME_EVAL': 'NO', 'TERM': 'xterm-color', 'CLICOLOR': '1', 'PAGER': 'cat', 'GIT_PAGER': 'cat', 'MPLBACKEND': 'module://matplotlib_inline.backend_inline'}
# /bin/bash echo 'hello world!!!'
# True False
# hello world!!!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment