From 33d6b9a4560b8085dd1c242e5f0b8d2b41f35aed Mon Sep 17 00:00:00 2001 From: Thomas Schneider <thomas@fsmpi.rwth-aachen.de> Date: Tue, 11 Apr 2023 17:40:00 +0200 Subject: [PATCH] Use Click for CLI --- pdm.lock | 15 +++++++++++- pyproject.toml | 1 + src/nctool/cli.py | 61 +++++++++++++++++++---------------------------- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/pdm.lock b/pdm.lock index 323e7a8..dca5593 100644 --- a/pdm.lock +++ b/pdm.lock @@ -15,6 +15,15 @@ dependencies = [ "pycparser", ] +[[package]] +name = "click" +version = "8.1.3" +requires_python = ">=3.7" +summary = "Composable command line interface toolkit" +dependencies = [ + "colorama; platform_system == \"Windows\"", +] + [[package]] name = "colorama" version = "0.4.6" @@ -103,7 +112,7 @@ dependencies = [ [metadata] lock_version = "4.1" -content_hash = "sha256:e49493c40f029631f0f923d9f3306cb05766876dfc284149bcf2bfdc891be04f" +content_hash = "sha256:c98532200135ebeef1c30c0c059c06d6568956765158022c0eb9bb561d946e38" [metadata.files] "bcrypt 4.0.1" = [ @@ -195,6 +204,10 @@ content_hash = "sha256:e49493c40f029631f0f923d9f3306cb05766876dfc284149bcf2bfdc8 {url = "https://files.pythonhosted.org/packages/f9/96/fc9e118c47b7adc45a0676f413b4a47554e5f3b6c99b8607ec9726466ef1/cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, {url = "https://files.pythonhosted.org/packages/ff/fe/ac46ca7b00e9e4f9c62e7928a11bc9227c86e2ff43526beee00cdfb4f0e8/cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, ] +"click 8.1.3" = [ + {url = "https://files.pythonhosted.org/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {url = "https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, +] "colorama 0.4.6" = [ {url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, diff --git a/pyproject.toml b/pyproject.toml index ca7d28a..2fef79a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ "ncclient>=0.6.13", "lxml>=4.9.2", "tqdm>=4.65.0", + "click>=8.1.3", ] [project.scripts] diff --git a/src/nctool/cli.py b/src/nctool/cli.py index 90b0649..18b59e3 100644 --- a/src/nctool/cli.py +++ b/src/nctool/cli.py @@ -1,8 +1,9 @@ -import argparse from getpass import getpass import os import os.path +import click + import lxml.etree as et from ncclient import manager @@ -10,23 +11,38 @@ from ncclient import manager from tqdm import tqdm -def get_models(args): +@click.group(context_settings=dict(help_option_names=["-h", "--help"])) +def main(): + pass + + +@main.command() +@click.option("-a", "--host", required=True, help="Device IP address or Hostname") +@click.option( + "--port", type=int, default=830, show_default=True, help="Netconf agent port" +) +@click.option( + "-u", "--username", required=True, help="Device Username (netconf agent username)" +) +@click.option("-d", "--destination", default="models", help="Destination directory") +def get_models(host, port, username, destination): + """Get YANG models from device""" try: password = getpass(prompt="Password (C-d for none/agent only): ") except EOFError: password = None with manager.connect( - host=args.host, - port=args.port, - username=args.username, + host=host, + port=port, + username=username, password=password, timeout=90, device_params={"name": "iosxe"}, ) as m: caps = list(map(lambda x: x.strip(), m.server_capabilities)) if not any(map(lambda x: x.startswith(manager.NETCONF_MONITORING_NS), caps)): - raise Exception("device does not support rfc6022") + raise click.ClickException("device does not support rfc6022") _filter = et.fromstring( f""" @@ -38,7 +54,7 @@ def get_models(args): prefix = f"{{{manager.NETCONF_MONITORING_NS}}}" - os.makedirs(args.destination, exist_ok=True) + os.makedirs(destination, exist_ok=True) pbar = tqdm( res.data.findall( @@ -64,34 +80,5 @@ def get_models(args): # Don’t pass format because IOS XE doesn’t eat its own definition. r = m.get_schema(identifier, version) - with open(os.path.join(args.destination, filename), "w") as fp: + with open(os.path.join(destination, filename), "w") as fp: fp.write(r.data) - - -def main(): - parser = argparse.ArgumentParser() - - parser.add_argument( - "-a", "--host", type=str, required=True, help="Device IP address or Hostname" - ) - parser.add_argument( - "-u", - "--username", - type=str, - required=True, - help="Device Username (netconf agent username)", - ) - parser.add_argument("--port", type=int, default=830, help="Netconf agent port") - - subparsers = parser.add_subparsers(required=True) - - parser_gm = subparsers.add_parser( - "get-models", aliases=["gm"], help="Get YANG models from device" - ) - parser_gm.add_argument( - "-d", "--destination", default="models", help="Destination directory" - ) - parser_gm.set_defaults(func=get_models) - - args = parser.parse_args() - args.func(args) -- GitLab