I thought it would be nice to make a command line app in Python to learn the techniques around setup.py, argparse, and GitHub Actions, so I tried it. We will not explain each technology in detail here, so please refer to the official documents and commentary articles introduced in the article.
I made a To-Do list app. Even so
todo add "Hoge"
todo complete "Hoge"
todo remove "Hoge"
Just add, complete, and delete to-dos. Also,
todo complete --all
todo remove -a
You can complete or delete everything with. The to-do list is stored in ~ / .todo.json
and
$ todo show
□ Hoge
☑ Hogehoge
It can be displayed as.
Use argparse to define the handling of command line arguments.
--argparse --- command line options, arguments, subcommand parsers — Python 3.8.0 documentation -A brief summary of how to use ArgumentParser --Qiita
argparse has too many functions to grasp, but this time I used the following. The entire code is here.
parser = argparse.ArgumentParser()
#Something like commit or run like git commit or docker run
#Is named a subcommand and added
parser.add_argument('subcommand', help='add, complete, or remove')
#The argument that comes after the subcommand is content.
#nargs is the number of arguments, one is nargs=1
# nagrgs='*'Will result in a variadic argument of 0 or more
# nargs='+'Is a variadic argument of 1 or more
# nargs='?'Is 0 or 1
# https://docs.python.org/ja/3/library/argparse.html#nargs
parser.add_argument('content', help='Content of To-Do', nargs='?')
# --all option(Shortened form-a)Add
#It's a flag, not an option that takes arguments`store_true=True`Specify
parser.add_argument('-a', '--all', action='store_true', help='remove or complete all To-Dos')
If the subcommand is show
or remove --all
, the argument'content' is not necessary, but it can be specified. I didn't know how to write it with argparse so that it couldn't be specified, so even if an argument is specified, it is ignored internally.
You can use this to call the process according to the specified argument (since there is no noteworthy knowledge about the process, source code See sample / blob / master / src / todo / main.py)).
Write setup.py
to have the command line app installed automatically.
-2. Write setup script — Python 3.8.0 documentation -How to make a Python package (written for internship) --Qiita
The written setup.py
can be found at here (written in [pip](https: /) /github.com/pypa/pip/blob/master/setup.py) and numpy However, I think the following parts are important in this.
entry_points={
"console_scripts": [
"todo=todo.main:main"
]
},
This will install the command in your OS's PATH when you do python3 setup.py install
. In my environment it looks like this [^ 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')()
)
Now, no matter what directory you are in, typing todo in the terminal will call a function called main in the main module of the todo package to do what you've written.
[^ 3]: I'm using Python that I put in Linuxbrew.
I installed it by running setup.py
earlier, but you can also install it from the Git repository using pip as follows. If it's a general-purpose command or package, it's a good idea to register it with PyPI.
pip3 install git+https://github.com/pn11/python-command-line-sample
Before I knew it, [^ 1] I wanted to use Actions that was added to GitHub, which was the reason for writing this article [^ 2]. This time I will safely perform an automatic test.
[^ 1]: [Breaking news] GitHub Actions is now official. Build / test / deploy, etc. in GitHub, and realize CI / CD. GitHub Universe 2019-Publickey [^ 2]: It's amazing that new features have been added more and more since it was acquired by MS. ..
For the time being, write a fucking test that just deletes all the to-do lists and then adds them. I did.
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'
I would like to do this with nose using GitHub Actions.
If you go to the Actions tab of the repository, you will see a screen like the one below, so let's try using Python package
for the time being.
The screen will look like the one below, so just press Start Commit
without thinking about anything.
The test fails.
Looking at YAML, it looks like this:
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
Somehow, under steps:
- name:things to do
run: |
Command 1
Command 2
It seems good to play with something like this. So, I wrote the following process.
- name: Install Package
run: |
python setup.py install
- name: Test with nose
run: |
pip install nose
nosetests
After installing the To-Do package with setup.py
, also install nose and run the test.
When I committed this, the test passed successfully. I wasn't particularly aware of the execution directory, but it seems to be running at the root of the repository. Also, I used nose somehow, but since it is not a library-dependent test, should it work with pytest as it is?
From now on, the test will run every time you commit. If you pass the test, it looks good with the: white_check_mark: mark.
So far, I created a command with argparse, packaged it with setup.py, and did an automated test with GitHub Actions. In the future, I would like to mass-produce fucking commands using this method.
Although not covered in this article, it may be good to use click etc. in addition to argparse when creating command line tools.
-Create a Python console application easily with Click --Qiita -[Awesome Python: Great Python Framework Library Software Resources --Qiita](https://qiita.com/hatai/items/34c91d4ee0b54bd7cb8b#%E3%82%B3%E3%83%9E%E3% 83% B3% E3% 83% 89% E3% 83% A9% E3% 82% A4% E3% 83% B3% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 82% B1% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E9% 96% 8B% E7% 99% BA)
Recommended Posts