Corrigindo uma função bash

0

Eu tenho uma função de shell (ok, é a função deactivate() definida por um virtualenv do Python), e gostaria de corrigi-la inserindo algumas instruções antes ou depois de sua execução. Meu objetivo é ter uma nova função deactivate() que faça o que a antiga fez, além de um pouco mais. Existe uma maneira de conseguir isso?

A função original é definida dinamicamente a partir de vários lugares (os vários virtualenvs), portanto modificá-la em cada fonte não é uma opção atraente.

    
por alexis 11.10.2018 / 12:49

3 respostas

1

Você poderia criar um alias de desativação (se isso for suficiente) que tenha prioridade mais alta que uma função. Em que você poderia executar um comando antes, mas não é fácil de executar depois.

alias deactivate='before; deactivate'

Ou simplesmente (muito melhor) crie uma função com um nome mais simples:

deact(){ [[ $somevar == true ]] && deactivate
         [[ $othervar == admin ]] && sudo deactivate
       }

Ou qualquer coisa que você queira implementar. Sim, isso só será executado quando definido. Não é um substituto para a palavra deactivate nem funciona para outros usuários.

A única maneira de fazer isso é criar um programa executável chamado deactivate , mas que tem prioridade menor que aliases e funções. Ambos precisarão ser definidos.

    
por 11.10.2018 / 13:01
1

Se o seu shell for bash , zsh ou ksh93 , você poderá aproveitar o typeset -f builtin, que mostra a origem de uma função:

# usage patch_func funcname before after
function patch_func {
        typeset nl=$'\n' lb={ src='typeset -f "$1"' before=$2 after=$3
        src="${src/$lb/$lb$nl    $before$nl}"
        src="${src%\}*}$nl    $after$nl}"
        eval "$src"
}

Exemplo:

$ deactivate(){ echo -n "{$0}"; for i; do echo -n " {$i}"; done; echo; }
$ patch_func deactivate 'echo before' 'echo after'
$ typeset -f deactivate
deactivate ()
{
    echo before;
    echo -n "{$0}";
    for i in "$@";
    do
        echo -n " {$i}";
    done;
    echo;
    echo after
}

Isso é muito frágil.

    
por 13.10.2018 / 22:49
0

Embora essa resposta não se aplique diretamente ao virtualenv usage - que tal usar virtualenvwrapper ? É basicamente virtualenv em esteróides, cuidando do gerenciamento de envs. Uma vez instalado, você recebe um conjunto de comandos adicionais:

  • workon lista todos os ambientes disponíveis quando chamado sem argumentos e ativa o env quando chamado com nome de env como um argumento, por exemplo workon myenv ativa o env myenv ;
  • mkvirtualenv myenv cria um novo env myenv ;
  • rmvirtualenv myenv remove.

Mas há mais - virtualenvwrapper define um conjunto de ganchos úteis onde você pode implementar sua própria lógica para personalização de envs, por exemplo:

  • premkvirtualenv é executado quando um env é criado, mas ainda não é ativado;
  • postmkvirtualenv é executado quando um env é criado e ativado;
  • preactivate é executado quando uma ativação env foi acionada;
  • postactivate é executado quando um env foi ativado;
  • predeactivate é executado quando uma desativação env foi acionada;
  • postdeactivate é executado quando um env foi desativado;

e muito mais. Por exemplo, eu tenho um gancho postmkvirtualenv que instala ipython em um novo env:

$ cat $VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv
#!/bin/bash
# This hook is sourced after a new virtualenv is activated.

env=$(basename "$VIRTUAL_ENV")
logger -s -t "($env)" "installing ipython ..."
"$VIRTUAL_ENV/bin/pip" install ipython --quiet

Para definir lógica adicional para a desativação de env, você teria que escrever um script bash personalizado e colocar seu conteúdo em $VIRTUALENVWRAPPER_HOOK_DIR/predeactivate (se você precisar executar suas coisas enquanto o env ainda estiver ativado) ou $VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate (se você precisar que o env seja desativado para executar o código personalizado).

Para referência: virtualenvwrapper docs .

Para obter uma lista completa dos ganchos, consulte a Personalização por usuário .

    
por 13.10.2018 / 22:16