Created
November 21, 2018 21:48
example of writing cli program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import argparse | |
import getpass | |
import sys | |
from contextlib import contextmanager | |
from distutils.util import strtobool | |
def yes_or_no(question, default='no'): | |
"""Ask question and wait for yes/no answer. | |
Args: | |
question (str) - question to ask | |
default (str) - default anser; 'yes' or 'no' | |
Return: | |
bool - whether user answered yes (true) or no (false) | |
""" | |
if default is None: | |
prompt = " [y/n] " | |
elif default == "yes": | |
prompt = " [Y/n] " | |
elif default == "no": | |
prompt = " [y/N] " | |
else: | |
raise ValueError("invalid default answer: '%s'" % default) | |
while True: | |
sys.stdout.write(question + prompt) | |
choice = input().lower() | |
if default is not None and choice == '': | |
return strtobool(default) | |
try: | |
return strtobool(choice) | |
except ValueError: | |
sys.stdout.write( | |
"Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n" | |
) | |
class NjuConnection: | |
def __init__(self, username, password): | |
pass | |
def login(self): | |
pass | |
def logout(self): | |
pass | |
def account_balance(self): | |
return 12 | |
@contextmanager | |
def nju_connection(username, password): | |
"""NJU connection manager | |
Args: | |
username (str) - nju account username | |
password (str) - nju account password | |
Returns: | |
NjuConnection - logged connection instance | |
""" | |
conn = NjuConnection(username, password) | |
try: | |
conn.login() | |
yield conn | |
finally: | |
conn.logout() | |
def main(): | |
# define program name and description for --help | |
prog = sys.argv[0] | |
description = "NJU CLI manager" | |
# user argparse to create program arguments/options | |
parser = argparse.ArgumentParser(prog=prog, description=description) | |
parser.add_argument( | |
"-c", "--clean", action='store_true', | |
help="clean configuration", | |
) | |
# parse command line | |
options = parser.parse_args() | |
# you can easily check options | |
if options.clean: | |
print("Cleaning configuration.") | |
# use standard input for username | |
username = input('Username: ') | |
# use getpass to hide typed password | |
password = getpass.getpass('Password: ') | |
if yes_or_no('Save configuration?', default='yes'): | |
print("... saving configuration") | |
if not yes_or_no('Continue?', default='yes'): | |
sys.exit("Aborted by user.") | |
# thanks to context manager you don't have to care about login/logout | |
# manually | |
with nju_connection(username, password) as conn: | |
print(f"Account balance: {conn.account_balance()} PLN") | |
if __name__ == "__main__": | |
# all interactive code is wrapped in 'main' functions so you can | |
# import cli module to reuse code without side effects | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment