Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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.

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

2 . 1 This Tutorial This Tutorial Ok, now that we're mostly installed, let's go over how this is going to work

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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.

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

4 Tutorial Tutorial Now let's run the tutorial commands (Switch to terminal and run tutorial --help)

Slide 17

Slide 17 text

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.

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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)

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

5 . 5 Utilities Utilities Output paging Screen clearing Launch executable /editor Get terminal size Get app config directory Format file names Lots of utilities

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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.