Créez une application de ligne de commande en Python pour comprendre les actions setup.py, argparse et GitHub

J'ai pensé que ce serait bien de créer une application de ligne de commande en Python pour apprendre les techniques autour des actions setup.py, argparse et GitHub, alors je l'ai essayé. Nous n'expliquerons pas chaque technologie en détail ici, veuillez donc vous référer aux documents officiels et aux articles de commentaires présentés dans l'article.

Livrables

J'ai créé To-Do List App. Toutefois

todo add "Hoge"
todo complete "Hoge"
todo remove "Hoge"

Il vous suffit d'ajouter, de compléter et de supprimer des tâches. Aussi,

todo complete --all
todo remove -a

Vous pouvez tout compléter ou tout supprimer avec. La liste des tâches est stockée dans ~ / .todo.json et

$ todo show
□ Hoge
☑ Hogehoge

Il peut être affiché sous la forme.

Créer une interface de ligne de commande

Utilisez argparse pour définir la gestion des arguments de ligne de commande.

argparse a trop de fonctions à saisir, mais cette fois j'ai utilisé ce qui suit. Le code entier est ici.

parser = argparse.ArgumentParser()

#Quelque chose comme commit ou run tel que git commit ou docker run
#Est nommé comme sous-commande et ajouté
parser.add_argument('subcommand', help='add, complete, or remove')

#Soit content l'argument qui vient après la sous-commande.
#nargs est le nombre d'arguments, l'un est nargs=1
# nagrgs='*'Se traduira par un argument de longueur variable de 0 ou plus
# nargs='+'Est un argument de longueur variable de 1 ou plus
# nargs='?'Est 0 ou 1
# https://docs.python.org/ja/3/library/argparse.html#nargs
parser.add_argument('content', help='Content of To-Do', nargs='?')

# --toutes les options(Forme raccourcie-a)Ajouter
#C'est un drapeau, pas une option qui prend un argument`store_true=True`Spécifier
parser.add_argument('-a', '--all', action='store_true', help='remove or complete all To-Dos')

Si la sous-commande est «show» ou «remove --all», l'argument «contenu» n'est pas nécessaire, mais il peut être spécifié. Je ne savais pas comment l'écrire dans argparse pour qu'il ne puisse pas être spécifié, donc même si un argument est spécifié, il est ignoré en interne.

Vous pouvez l'utiliser pour appeler le processus en fonction de l'argument spécifié (car il n'y a aucune connaissance notable sur le processus, code source Voir sample / blob / master / src / todo / main.py)).

Emballage

Écrivez setup.py pour que l'application de ligne de commande soit installée automatiquement.

Le setup.py écrit peut être trouvé à ici (écrit en [pip](https: /) /github.com/pypa/pip/blob/master/setup.py) et numpy Cependant, je pense que les parties suivantes sont importantes à cet égard.

    entry_points={
        "console_scripts": [
            "todo=todo.main:main"
        ]
    },

Cela installera la commande dans votre OS PATH lorsque vous effectuez python3 setup.py install. Dans mon environnement, cela ressemble à ceci [^ 3].

$ which todo
/home/linuxbrew/.linuxbrew/bin/todo
 $ cat $(which todo)
#!/home/linuxbrew/.linuxbrew/opt/python/bin/python3.7
# EASY-INSTALL-ENTRY-SCRIPT: 'todo==0.1.0','console_scripts','todo'
__requires__ = 'todo==0.1.0'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('todo==0.1.0', 'console_scripts', 'todo')()
    )

Maintenant, quel que soit le répertoire dans lequel vous vous trouvez, appuyez sur todo dans le terminal pour appeler une fonction appelée main dans le module principal du package todo pour faire ce que vous avez écrit.

[^ 3]: J'utilise Python que j'ai mis dans Linuxbrew.

Installer avec pip

Je l'ai installé en exécutant setup.py plus tôt, mais vous pouvez également l'installer à partir du référentiel Git en utilisant pip comme suit. S'il s'agit d'une commande ou d'un package à usage général, c'est une bonne idée de l'enregistrer dans PyPI.

pip3 install git+https://github.com/pn11/python-command-line-sample

Tests automatisés avec les actions GitHub

Avant de le savoir, [^ 1] je voulais utiliser les actions qui ont été ajoutées à GitHub, ce qui a été la raison pour laquelle cet article [^ 2]. Cette fois, je vais effectuer un test automatique en toute sécurité.

[^ 1]: [Dernières nouvelles] Les actions GitHub sont désormais officielles. Exécutez build / test / deploy etc. dans GitHub et réalisez CI / CD. GitHub Universe 2019-Publickey [^ 2]: C'est incroyable que de nouvelles fonctionnalités aient été ajoutées de plus en plus depuis son acquisition par MS. ..

Pour le moment, écrivez un putain de test qui supprime simplement toutes les listes de tâches, puis les ajoute. J'ai fait.

import todo.main

def test_add():
    todo.main._remove_todo('', all_flag=True)
    todo.main._add_todo('foo')
    dic = todo.main._load_todos()
    assert dic['foo'] == 'Not Yet'

Je voudrais faire cela avec le nez en utilisant les actions GitHub.

Créer YAML pour l'action

Si vous allez dans l'onglet Actions du référentiel, vous verrez un écran comme celui ci-dessous, alors essayons-le avec Python package pour le moment.

919fa3a4-176e-419d-b249-4892ffe4f18d.jpg

L'écran suivant apparaîtra, donc pour le moment, appuyez sur Start Commit sans penser à rien.

71a5aa3e-4fbb-4a7b-aaad-32fcee02ad5f.jpg

Le test échoue.

9f8800a4-0658-4dc6-a264-a9aa1a1e1348.jpg

En regardant YAML, cela ressemble à ceci:

name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: [2.7, 3.5, 3.6, 3.7]

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v1
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Lint with flake8
      run: |
        pip install flake8
        # stop the build if there are Python syntax errors or undefined names
        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
    - name: Test with pytest
      run: |
        pip install pytest
        pytest

D'une manière ou d'une autre, sous étapes:

- name:Choses à faire
  run: |
Commande 1
Commande 2

Cela semble bon de jouer avec quelque chose comme ça. Donc, j'ai écrit le processus suivant.

    - name: Install Package
      run: |
        python setup.py install
    - name: Test with nose
      run: |
        pip install nose
        nosetests

Après avoir installé le paquet To-Do avec setup.py, installez également nose et exécutez le test.

Lorsque j'ai commis cela, le test a réussi. Je n'étais pas particulièrement conscient du répertoire d'exécution, mais il semble être exécuté à la racine du référentiel. De plus, j'ai utilisé le nez d'une manière ou d'une autre, mais comme il ne s'agit pas d'un test dépendant de la bibliothèque, pytest devrait-il fonctionner tel quel?

2e3474ac-5bb2-49ed-a87f-c349eaf64855.jpg

Désormais, le test s'exécutera à chaque fois que vous vous engagez. Si vous réussissez le test, il semble bon avec la marque: white_check_mark:.

caaef1bb-00d2-4be6-b7b8-eceac4bb906a.jpg

Résumé

Jusqu'à présent, j'ai essayé de créer des commandes avec argparse, l'empaquetage avec setup.py et des tests automatisés avec des actions GitHub. À l'avenir, j'aimerais produire en masse des commandes putain en utilisant cette méthode.

Autre

Bien que cela ne soit pas couvert dans cet article, il peut être bon d'utiliser click etc. en plus de argparse lors de la création d'outils de ligne de commande.

Recommended Posts

Créez une application de ligne de commande en Python pour comprendre les actions setup.py, argparse et GitHub
Comment obtenir une chaîne à partir d'un argument de ligne de commande en python
Notes J'ai recherché la création d'outils de ligne de commande en Python
Comment recevoir des arguments de ligne de commande en Python
Comment exécuter une commande à l'aide d'un sous-processus en Python
Dans la commande python, python pointe vers python3.8
Créez un outil de ligne de commande pour convertir des dollars en yens en utilisant Python
[Python] J'ai essayé de créer un programme simple qui fonctionne sur la ligne de commande en utilisant argparse
Méthode pour créer un environnement Python dans Xcode 6
Créer une application GUI simple en Python
Je veux créer un environnement Python
Comment obtenir stacktrace en python
Lancer une application Flask dans Python Anywhere
Décomposer les arguments de commande en une seule ligne en Python
J'ai un package Python privé mais je souhaite installer pipenv sur GitHub Actions et créer une image Docker
Différentes façons de lire la dernière ligne d'un fichier csv en Python
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
Comment gérer les arguments lors de l'implémentation d'un script Python en tant qu'outil de ligne de commande
Modèle pour créer des applications de ligne de commande en Python
[Python] Comment tester l'analyseur de ligne de commande cliquez sur
Envoyer un message à LINE avec Python (LINE Notify)
Calculons en fait le problème statistique avec Python
Comment effacer un taple dans une liste (Python)
Déployer à partir d'actions GitHub vers Azure App Service
Comment incorporer des variables dans des chaînes python
Je veux créer une fenêtre avec Python
Comment créer un fichier JSON en Python
Une manière intelligente de chronométrer le traitement avec Python
Créez un jeu Janken en une seule ligne (python)
Pour ajouter un module à python que vous mettez dans Julialang
Mes réflexions sur le modèle d'application de ligne de commande python2.6
Comment notifier les canaux Discord en Python
[Introduction à Udemy Python3 + Application] 67. Arguments de ligne de commande
[Python] Comment dessiner un histogramme avec Matplotlib
Je ne peux pas dormir tant que je n'ai pas construit un serveur !! (Introduction au serveur Python faite en un jour)
Comprendre le rendement Python Si vous mettez le rendement dans une fonction, elle se transforme en générateur
Comment héberger le traitement du backend d'application Web en Python à l'aide d'un sous-domaine de serveur de location
Analyser une chaîne JSON écrite dans un fichier en Python
Je veux facilement implémenter le délai d'expiration en python
Essayez de créer un module Python en langage C
[Python] Comment dessiner un graphique linéaire avec Matplotlib
Faisons un outil de veille de commande avec python
[API LINE Messaging] Créez un menu riche avec Python
Je veux écrire en Python! (2) Écrivons un test
Développement d'applications pour tweeter en Python à partir de Visual Studio 2017
Créer un plugin pour exécuter Python Doctest sur Vim (2)
J'ai essayé d'implémenter un pseudo pachislot en Python
Un mémorandum pour exécuter un script python dans un fichier bat
Je veux échantillonner au hasard un fichier avec Python
Comment créer un environnement Django (python) sur Docker
Étapes de l'installation de Python 3 à la création d'une application Django
Je veux travailler avec un robot en python.
Choses à noter lors de l'initialisation d'une liste en Python
Introduction à l'algèbre linéaire avec Python: Décomposition A = LU
[Python] Création d'une méthode pour convertir la base en 1 seconde
Écrire du code dans UnitTest une application Web Python