Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyTennessee 2016 - Writing Command Line Applications that Click

Dave Forgac
February 07, 2016

PyTennessee 2016 - Writing Command Line Applications that Click

Dave Forgac

February 07, 2016

More Decks by Dave Forgac

Other Decks in Technology


  1. 1 . 1 Writing Command Line Writing Command Line Applications

    that Click Applications that Click Instructions: http://bit.ly/pytn-click Instructions: http://bit.ly/pytn-click While we're waiting you can go ahead and follow the installation instructions
  2. 1 . 2 Feedback Please! Feedback Please! Instructions: http://bit.ly/pytn-click Instructions:

    http://bit.ly/pytn-click Dave Forgac Dave Forgac [email protected] [email protected] @tylerdave @tylerdave My name is... I currently work as API development lead at American Greetings in Cleveland, OH Previously worked as sysadmin and support engineer In all these jobs I've had things to automate which meant creating CLI tool I really want your feedback on this tutorial So please let me know if you got what you were expecting and what works for you and what didn't. I'll put this info up again at the end.
  3. 1 . 3 Installation Installation Instructions: http://bit.ly/pytn-click Instructions: http://bit.ly/pytn-click Have

    Python & Git Create and activate virtualenv Clone this repo Install this repo: Run the tests: pip install -e . py.test -v tests/ Now if you haven't already, let's go ahead and get the tutorial installed. Longer directions are at the link at the bottom. If you're having trouble getting it installed I'm going to come around and help If you already have your installed see if the people around you need help
  4. 2 . 1 This Tutorial This Tutorial Ok, now that

    we're mostly installed, let's go over how this is going to work
  5. 2 . 2 Python Package Python Package Installed Dependencies Put

    new commands on $PATH: Installed in editable mode hello, pytn, tutorial The thing you just installed is a Python package By installing it you installed our dependencies: click itself, colorama (for handling CLI colors) and pytest for running the tests It put three new commands that we're going to use on your PATH Installed the package in editable mode so code updates are reflected without reinstallation
  6. 2 . 3 Directory Layout Directory Layout ├── click_tutorial │

    ├── cli.py │ ├── data │ │ └── tutorial_lessons.json │ ├── hello.py │ ├── tutorial.py │ ├── tutorial_runner.py │ └── ( ... ) ├── setup.py ├── solutions │ └── ( ... ) ├── tests │ ├── __init__.py │ ├── test_click_tutorial.py │ └── test_dependencies.py ├── tutorial │ └── ( ... ) └── ( ... ) Go over repo contents: click_tutorial is the python package directory cli.py is the file we'll be changing data is the tutorial configuration hello.py is a hello, world example tutorial and tutorial_runner give us tutorial command setup.py is normal packaging config solutions contains code to complete each lesson tutorial contains tests for each lesson
  7. 2 . 4 Entry Points Entry Points setup( # ...

    entry_points={ 'console_scripts':[ 'pytn=click_tutorial.cli:cli', 'hello=click_tutorial.hello:cli', 'tutorial=click_tutorial.tutorial_runner:cli', ], }, # ... ) The package uses setuptool's entry points to provide the new commands This is configured int he setup.py for the package Entry points define interfaces for your python pacakge In this case we're using the special type called console_scripts This causes setuptools to make a small wrapper command and maps it to package.module:function This works in a platform-independent way
  8. 2 . 5 'tutorial' Command 'tutorial' Command $ tutorial --help

    Usage: tutorial [OPTIONS] COMMAND [ARGS]... Runs the tutorial Options: --status-file PATH --help Show this message and exit. Commands: lesson Run tests to check given LESSON_ID. lesson-ids Output a list of all LESSON_IDs. next Run the next lesson. reset Reset the status for all lessons (start-over) solve Copy solution for LESSON_ID into place. status Show the status of the tutorial lessons. One of the new commands that the package provides is 'tutorial' If you run tutorial --help this is what you'll see The tutorial command itself was created with click It's used to run tests for each lesson and was created based on feedback from a preview of this tutorial that I gave a couple weeks ago
  9. 3 . 1 Click Click So now just a little

    about click You're already here so I'm not going to spend time convincing you it's worth looking at
  10. 3 . 2 http://click.pocoo.org http://click.pocoo.org Click was created by Armin

    Ronacher who you might recognize from flask, sphinx, among others Click has great documentation available at this URL There's a section on why click instead of some alternatives so you can read that later if you need more convincing
  11. 3 . 3 Why? Why? POSIX-compliant Supports common use cases

    Python 2/3 Allows / encourages good separation For me though there were a few things that attracted me to click It creates POSIX compliant command interfaces so there's no surprises in how your commands work Supports things I do in most CLIs like reading stdin, opening files, writing output, type checking, etc It's python 2&3 compatible which is especially important for me at work where we have a lot of legacy python 2 stuff but are trying to develop new systems in 3.
  12. 3 . 4 Hello, World! Hello, World! import click @click.command()

    def cli(): """ Outputs a greeting. """ click.echo("Hello, PyTennessee!") if __name__ == '__main__': cli() This is the most basic of click commands It imports click and then uses a decorator to turn a normal function into a click command A lot of configuration is done using decorators. If you're not familiar with them what you need to know for our purposes today is that a decorator wraps a function (or method or class) and adds to or changes its functionality. This uses click's built-in echo function instead of print. This does the right thing on python 2 and 3 Then we have the if __name__ == '__main__' check that allows this to be either imported or run at CLI
  13. 3 . 5 Click Basics Click Basics import click @click.command(name='hello')

    @click.argument('name') @click.option('--excited', '-e', is_flag=True) def cli(name, excited): """ Given a NAME, outputs a greeting. """ punctuation = '!' if excited else '.' click.echo("Hello, {0}{1}".format(name, punctuation)) if __name__ == '__main__': cli() There are two types of command line parameters: arguments and options. Arguments are generally required and positional. Options are optional. This command adds a required argument for name and an option for whether the output should be excited or not These values are passed into the cli function based on their name and then the variables are available within the function
  14. 3 . 6 Help Output Help Output $ hello --help

    Usage: hello [OPTIONS] NAME Given a NAME, outputs a greeting. Options: -e, --excited --help Show this message and exit. Click gives us generated help output when we run the command
  15. 3 . 7 Examples Examples $ hello PyTennessee Hello, PyTennessee.

    $ hello --excited PyTennessee Hello, PyTennessee! $ hello -e PyTennessee Hello, PyTennessee! $ hello --invalid-option PyTennessee Error: no such option: --invalid-option And here you can see how it works with the required argument and the long or short version of the option flag and then there's an example of what happens when you don't provide a required argument
  16. 5 . 1 But wait, But wait, there's more! there's

    more! There's a ton more that click can do that we didn't have time to cover. Here are some of the more interesting things.
  17. 5 . 2 Complex Commands Complex Commands Merging Chaining Loading

    Plugins Context defaults Commands can be combined together in a bunch of different ways . The tutorial command does this with the next command where it invokes the lesson command internally You can load new subcommands dynamically from plugins Set defaults for subcommands
  18. 5 . 3 Options Options Explicit values from env var

    Auto load from env var prefix Change option prefix You can read values for options from environment variables either in an explicit one-off fashion or automatically based on an environment variable prefix for your command You can change the option prefix from - (like if you want / windows style options)
  19. 5 . 4 Validation Validation Custom types Callbacks Eager options

    You can do a lot more with validation You can define custom types by subclassing click's types or by defining a simple type that raises a value error You can also provide callbacks to do validation or manipulation of input Eager options can be used to short circuit option handling
  20. 5 . 5 Utilities Utilities Output paging Screen clearing Launch

    executable /editor Get terminal size Get app config directory Format file names Lots of utilities
  21. 5 . 6 Autocompletion Autocompletion And finally there's bash autocompletion

    which click can do for you. You can either set a special environment variable or add a function to be sourced in your bashrc
  22. 6 Thank You! Thank You! Feedback please: Feedback please: [email protected]

    [email protected] @tylerdave @tylerdave Thank you! Again, please let me know how this went for you and / or if you have any questions.