diff --git a/setup.cfg b/setup.cfg index 643f412..4af6729 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,7 +8,7 @@ description = new library to interface with the smaXtec system author = smaXtec author_email = support@smaxtec.com license = Apache License 2.0 -long_description = file: README.md +long_description = file: README.rst long_description_content_type = text/markdown url = https://github.com/pyscaffold/pyscaffold/ # Add here related links, for example: diff --git a/src/sxapi/cli/cli.py b/src/sxapi/cli/cli.py index 72bede6..16ea253 100644 --- a/src/sxapi/cli/cli.py +++ b/src/sxapi/cli/cli.py @@ -10,7 +10,6 @@ from setuptools import setup from sxapi.cli import cli_user -from sxapi.cli.subparser.get_sensor_data import create_gsd_parser from sxapi.cli.subparser.token import create_token_parser @@ -111,7 +110,8 @@ def parse_args(args): main_parser = argparse.ArgumentParser( description=( "Issue calls to the smaXtec system API to import and export data." - ) + ), + usage="%(prog)s [options] [sub_command_options] []", ) main_parser.add_argument( "--version", @@ -127,7 +127,7 @@ def parse_args(args): ) main_parser.add_argument( "-t", - "--arg_token", + "--access_token", type=str, help="Access Token", ) @@ -146,14 +146,20 @@ def parse_args(args): help="Print example config file and exits", ) - # gsd_parser - subparsers = main_parser.add_subparsers(help="sub-command help") - create_gsd_parser(subparsers) + subparsers = main_parser.add_subparsers(title="sub_commands") + # create_gsd_parser(subparsers) create_token_parser(subparsers) if not args: main_parser.print_help() return + + # check if subparser is called with arguments + # otherwise print help for subparser + elif args[0] in subparsers.choices.keys() and len(args) == 1: + subparsers.choices[args[0]].print_help() + return + return main_parser.parse_args(args) def run(self): @@ -171,7 +177,7 @@ def run(self): self.update_config_with_env(config_dict) - cli_user.init_user(config_dict, args.arg_token, args.use_keyring) + cli_user.init_user(config_dict, args.access_token, args.use_keyring) if args.status: self.api_status() @@ -179,7 +185,7 @@ def run(self): if args.version: self.version_info() - if args.use_keyring and args.arg_token: + if args.use_keyring and args.access_token: print("Choose either -k (keyring), -t (argument) or no flag (environment)!") return diff --git a/src/sxapi/cli/subparser/token.py b/src/sxapi/cli/subparser/token.py index 28b5a9f..745dc26 100644 --- a/src/sxapi/cli/subparser/token.py +++ b/src/sxapi/cli/subparser/token.py @@ -31,6 +31,7 @@ def create_token_parser(subparsers): "token", help="Get/Set credentials aka 'SMAXTEC_API_ACCESS_TOKEN' from/to specified " "storage location or create new one", + usage="sxapi [base_options] token [options]", ) token_parser.add_argument( @@ -41,19 +42,20 @@ def create_token_parser(subparsers): help="Print the current token stored in keyring/environment to stdout. " "One argument required. Possible args 'e' environment | " "'k' keyring | ek for printing both.", + metavar="SOURCE", ) token_parser.add_argument( "--set_keyring", "-s", nargs=1, - help="Store the given token in keyring! Requires one argument ", + help="Store the given token in keyring! Requires one argument .", + metavar="TOKEN", ) token_parser.add_argument( "--new_token", "-n", - nargs="+", - help="Reqeust new token. Requires one argument , " - "second argument is optional!", + action="store_true", + help="Reqeust new token", ) token_parser.add_argument( "--clear_keyring", @@ -86,16 +88,16 @@ def token_sub_function(args): "Invalid Combination! Please use just one out of these parameters " "[--print_token, --set_keyring, --new_token, --clear_keyring]" ) - return + return 1 if args.print_token: - handle_print_token(args) + return handle_print_token(args) elif args.set_keyring: - handle_set_token(args) + return handle_set_token(args) elif args.clear_keyring: - handle_clear_token() + return handle_clear_token() elif args.new_token: - handle_new_token(args) + return handle_new_token(args) # Flag helper functions @@ -110,22 +112,24 @@ def handle_print_token(args): if args.print_token == "ek": print(f"\nKeyring: {keyring}\n\nEnvironment: {env}") - return + return 0 elif len(args.print_token) > 2: print("Invalid number of arguments. Use --help for usage information.") - return + return 0 if "e" != args.print_token and "k" != args.print_token: print( "Invalid arguments. Only use 'e' for environment, 'k' for keyring " "or 'ek' for both." ) - return + return 1 if "e" == args.print_token: print(f"\nEnvironment Token: {env}\n") + return 0 elif "k" == args.print_token: print(f"\nKeyring Token: {keyring}\n") + return 0 def handle_set_token(args): @@ -138,6 +142,8 @@ def handle_set_token(args): cli_user.set_token_keyring(token=token) print("Token is stored in keyring!") + return 0 + def handle_clear_token(): """ @@ -148,6 +154,8 @@ def handle_clear_token(): cli_user.clear_token_keyring() print("Token was deleted from keyring!") + return 0 + def handle_new_token(args): """ @@ -156,23 +164,20 @@ def handle_new_token(args): Parses the args, creates an PublicAPIV2 instance to get new token and print the new token to stdout. """ - if len(args.new_token) == 2: - username = args.new_token[0] if "@" in args.new_token[0] else args.new_token[1] - pwd = args.new_token[1] if "@" not in args.new_token[1] else args.new_token[0] - if len(args.new_token) == 1: - username = args.new_token[0] - pwd = getpass.getpass() + username = input("Username: ") if "@" not in username: print("Username must be a email!") - return + return 1 + + pwd = getpass.getpass() try: token = str(PublicAPIV2(email=username, password=pwd).get_token()) print("SMAXTEC_API_ACCESS_TOKEN=" + token) + return 0 except requests.HTTPError as e: if "401" in str(e) or "422" in str(e): print("Username or Password is wrong!") - except Exception as e: - print(e) + return 1 diff --git a/tests/cli_tests/test_gsd_subparser.py b/tests/cli_tests/test_gsd_subparser.py index 6a8afea..7d7aaad 100644 --- a/tests/cli_tests/test_gsd_subparser.py +++ b/tests/cli_tests/test_gsd_subparser.py @@ -1,4 +1,5 @@ import mock +import pytest from sxapi.cli.cli import Cli from sxapi.publicV2 import PublicAPIV2 @@ -11,6 +12,7 @@ ) @mock.patch("sxapi.cli.cli_user.check_credentials_set", return_value=True) @mock.patch("sxapi.cli.cli_user.public_v2_api", PublicAPIV2()) +@pytest.mark.skip() def test_get_sensor_data_parser(creds_mock, get_data_mock): namespace = args_parser( [ diff --git a/tests/cli_tests/test_token_subparser.py b/tests/cli_tests/test_token_subparser.py index 3569b9a..53fb900 100644 --- a/tests/cli_tests/test_token_subparser.py +++ b/tests/cli_tests/test_token_subparser.py @@ -13,7 +13,7 @@ @mock.patch("builtins.print") @mock.patch("sxapi.publicV2.PublicAPIV2.get_token", return_value="api_token") -def test_handle_print_token(api_mock, print_mock): +def test_handle_print_token(_, print_mock): namespace = args_parser(["token", "-p"]) assert namespace.print_token == "ek" handle_print_token(namespace) @@ -84,7 +84,7 @@ def test_handle_set_token(cred_mock, print_mock): @mock.patch("builtins.print") @mock.patch("sxapi.cli.cli_user.clear_token_keyring", return_value="api_token") -def test_handle_clear_token(creds_mock, print_mock): +def test_handle_clear_token(_, print_mock): namespace = args_parser(["token", "-c"]) assert namespace.clear_keyring is True handle_clear_token() @@ -97,37 +97,40 @@ def test_handle_clear_token(creds_mock, print_mock): @mock.patch("builtins.print") @mock.patch("sxapi.cli.subparser.token.getpass.getpass", return_value=None) @mock.patch("sxapi.cli.cli_user") -def test_handle_new_token(creds_mock, getpass_mock, print_mock): +def test_handle_new_token(_, getpass_mock, print_mock): print_mock.reset_mock() - namespace = args_parser(["token", "-n", "no_at"]) - assert namespace.new_token == ["no_at"] - handle_new_token(namespace) - assert getpass_mock.call_count == 1 - call_args = print_mock.call_args_list[0] - assert print_mock.call_count == 1 - assert call_args.args[0] == "Username must be a email!" - print_mock.reset_mock() - - namespace = args_parser(["token", "-n", "marco@test"]) - assert namespace.new_token == ["marco@test"] - handle_new_token(namespace) - assert getpass_mock.call_count == 2 - call_args = print_mock.call_args_list[0] - assert print_mock.call_count == 1 - assert call_args.args[0] == "Username or Password is wrong!" - print_mock.reset_mock() + namespace = args_parser(["token", "-n"]) + assert namespace.new_token is True + with mock.patch("builtins.input", lambda _: "marco_no_at_test"): + handle_new_token(namespace) + assert getpass_mock.call_count == 0 + call_args = print_mock.call_args_list[0] + assert print_mock.call_count == 1 + assert call_args.args[0] == "Username must be a email!" + print_mock.reset_mock() - with mock.patch("sxapi.publicV2.PublicAPIV2.get_token", return_value="api_token"): - namespace = args_parser(["token", "-n", "marco@test", "pwd"]) - assert namespace.new_token == ["marco@test", "pwd"] + namespace = args_parser(["token", "-n"]) + assert namespace.new_token is True + with mock.patch("builtins.input", lambda _: "marco@test"): handle_new_token(namespace) - assert getpass_mock.call_count == 2 + assert getpass_mock.call_count == 1 call_args = print_mock.call_args_list[0] assert print_mock.call_count == 1 - assert call_args.args[0] == "SMAXTEC_API_ACCESS_TOKEN=api_token" + assert call_args.args[0] == "Username or Password is wrong!" print_mock.reset_mock() + with mock.patch("sxapi.publicV2.PublicAPIV2.get_token", return_value="api_token"): + namespace = args_parser(["token", "-n"]) + assert namespace.new_token is True + with mock.patch("builtins.input", lambda _: "marco@test"): + handle_new_token(namespace) + assert getpass_mock.call_count == 2 + call_args = print_mock.call_args_list[0] + assert print_mock.call_count == 1 + assert call_args.args[0] == "SMAXTEC_API_ACCESS_TOKEN=api_token" + print_mock.reset_mock() + @mock.patch("builtins.print") def test_token_subfunc(print_mock):