Skip to main content

A small example package for creating an executable CLI.

Project description

Sample Python CLI

Sample repository for creating a CLI in Python.

Motivation

This repository is for educational purposes. I want to show how to create an executable CLI tool written in Python. With this I wanna cover:

  • Creating a Python Package using traditional setup.py.
  • Creating a Python Package using poetry.
  • Publishing to PyPI.
  • Creating a simple CLI tool that installs on to your system and is executable.
  • Creating plugins for the CLI tool that are pipinstalable.

Package

We are going to create a package called pier-mob. Why? Just because! I don't wanna use traditional example, foo, or bar because I think those names lack semantics and the use of such names becomes difficult for less experienced devs to understand. If you are wondering, I let roke choose the name for the example tool that we are going to build.

Add files and directories:

pier_mob
|-- LICENSE               # License file
|-- README.md             # **This** file
|-- pier_mob              # Main directory: all source code inside
|   |-- __init__.py       # needed for converting directory into a package
|   |-- __main__.py       # Defines what is executed when package is called
|   `-- cli.py            # Sample source code module
|-- setup.py              # Python Packaging config file
`-- tests                 # Test cases directory
    |-- __init__.py       # needed for converting directory into a package
    `-- test_version.py   # Test source code sample

With this minimal structure we can run our program as module and as a simple script. Using pip strategy to be able of running in both ways. Look deeper on pier_mob/__main__.py.

As simple script:

$ python3 pier_mob
Pier Mob v0.0.1

And running as module:

$ python3 -m pier_mob
Pier Mob v0.0.1

Also with this minimal structure we have tests.

Tests can be run as:

$ python3 setup.py test

Let's publish our package

You will need setuptools, wheel, and twine for creating and uploading to PyPI. Install this packages with pip in new virtualenv or in your user level packages.

Create a new virualenv, activate it and install needed packages:

$ python3 -m venv pier_build
$ source pier_build/bin/activate
(pier_build) $ pip install setuptools wheel twine

Now we need to build source distribution files. Run the following command:

(pier_build) $ python3 setup.py sdist bdist_wheel

This command will output a lot of text and once completed will generate two files in the dist directory: a .tar.gz which is a Source Distribution, and a .whl which is a Built Distribution.

Now we are ready to upload our package. Use your PyPI account and create a new API Token. When twine prompts your username write __token__ then use your API Token as password.

(pier_build) $ python3 -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
Uploading distributions to https://upload.pypi.org/legacy/
Enter your username: __token__
Enter your password:

✨ 🍰 ✨ Congrats! Your package is now published on PyPI: https://pypi.org/project/pier-mob-lecovi/

Create a new virtualenv and install your package from PyPI

$ python3 -m venv venv
$ source venv/bin/activate
(venv) $ pip install pier-mob-lecovi
...
$ python

Inside REPL run:

>>> import pier_mob
>>> pier_mob.version()
'0.0.1'

✨ 🍰 ✨ It works!!

Test PyPI

It's a complete separate instance. If you have a user on PyPI you need to create another one for Test PyPI (and vivecersa). The same goes for Tokens.

Executable

Let's change pier_mob/__main__.py for creating a console script instalable. Wrap the print function inside main() and modify setup.py

entry_points={
'console_scripts': [
    'pier=pier_mob.__main__:main',
    ],
},

This will create a pier executable that will call the main() function inside __main__.py.

Create a new virtualenv and test installation:

$ python3 -m venv executable
$ source executable/bin/activate
(executable) $ python3 setup.py install
(executable) $ pier
Pier Mob v0.0.2

Adding commands

Let's improve our interface using Typer. Add info() and version() functions to cli.py. DON'T FORGET TO UPDATE __version__. You also will need to update __main__ and __init__ and import the new app instead of version(). We need to change our unittest for the better pytest suite.

(install) $ pip install typer pytest

Now test must be run with:

(install) $ pytest

Now you can update your package on PyPI.

(build) $ python3 setup.py build
(build) $ python3 -m twine upload --repository pypi dist/*

Resources

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pier-mob-lecovi-0.0.3.2.tar.gz (4.7 kB view details)

Uploaded Source

Built Distribution

pier_mob_lecovi-0.0.3.2-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

Details for the file pier-mob-lecovi-0.0.3.2.tar.gz.

File metadata

  • Download URL: pier-mob-lecovi-0.0.3.2.tar.gz
  • Upload date:
  • Size: 4.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.7.3

File hashes

Hashes for pier-mob-lecovi-0.0.3.2.tar.gz
Algorithm Hash digest
SHA256 9f03601711551fd58c8270e25ddbe5dfc0850baa9ecfb25eaefcb00581e8f857
MD5 f97d76759c6f0840c4323dfd444172b8
BLAKE2b-256 e3568df29b575ef61ffd778e735b1691eb814c76a4319e24776da25919693c68

See more details on using hashes here.

File details

Details for the file pier_mob_lecovi-0.0.3.2-py3-none-any.whl.

File metadata

  • Download URL: pier_mob_lecovi-0.0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 17.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.7.3

File hashes

Hashes for pier_mob_lecovi-0.0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 17a69a31652d9af326ac394d37080b3a0f3a74e0a25d4eb842b8d4730c0c1112
MD5 b6340d4cfc11d9117a7fce754651a41a
BLAKE2b-256 20a4827b02cbc936d24544d9299165921fae7f332d980c6ce7d9625105785e96

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page