Skip to content

Commit 9dbd896

Browse files
authored
Merge pull request #37 from jan-janssen/friendly_cmd
Provide a more user-friendly command line interface
2 parents 175853f + 27800ff commit 9dbd896

File tree

2 files changed

+89
-12
lines changed

2 files changed

+89
-12
lines changed

pyauthenticator/__main__.py

+42-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Generate two factor authentication codes on the command line
33
"""
44
import argparse
5+
import sys
56
from pyauthenticator.share import (
67
list_services,
78
load_config,
@@ -11,17 +12,25 @@
1112
)
1213

1314

14-
def command_line_parser():
15+
def command_line_parser(cmd_args=None):
1516
"""
1617
Main function primarly used for the command line interface
1718
"""
19+
if cmd_args is None:
20+
cmd_args = sys.argv[1:]
1821
parser = argparse.ArgumentParser(prog="pyauthenticator")
1922
config_dict = load_config()
20-
parser.add_argument(
21-
"service",
22-
help="Service to generate optauth code for. Available services are: "
23-
+ str(list_services(config_dict=config_dict)),
24-
)
23+
if len(config_dict) > 0:
24+
parser.add_argument(
25+
"service",
26+
help="Service to generate optauth code for. The config file ~/.pyauthenticator contains the following services: "
27+
+ ", ".join(list_services(config_dict=config_dict)),
28+
)
29+
else:
30+
parser.add_argument(
31+
"service",
32+
help="Service to generate optauth code for. Currently no service is defined in the ~/.pyauthenticator config file.",
33+
)
2534
parser.add_argument(
2635
"-qr",
2736
"--qrcode",
@@ -31,18 +40,41 @@ def command_line_parser():
3140
parser.add_argument(
3241
"-a",
3342
"--add",
34-
help="Add service by providing the qrcode png file as additional argument.",
43+
help="Add service by providing the <qrcode.png> file as additional argument.",
3544
)
36-
args = parser.parse_args()
45+
args = parser.parse_args(args=cmd_args)
3746
if args.qrcode:
3847
generate_qrcode(key=args.service, config_dict=config_dict)
48+
print("The qrcode file <" + args.service + ".png> was generated.")
3949
elif args.add:
4050
add_service(
4151
key=args.service, qrcode_png_file_name=args.add, config_dict=config_dict
4252
)
43-
print(args.service, "added.")
53+
print(
54+
"The service '"
55+
+ args.service
56+
+ "' was added, from file <"
57+
+ args.add
58+
+ ">."
59+
)
4460
else:
45-
print(get_two_factor_code(key=args.service, config_dict=config_dict))
61+
try:
62+
print(get_two_factor_code(key=args.service, config_dict=config_dict))
63+
except ValueError:
64+
if len(config_dict) > 0:
65+
print(
66+
'The service "'
67+
+ args.service
68+
+ '" does not exist.\n\nThe config file ~/.pyauthenticator contains the following services:'
69+
)
70+
for service in list_services(config_dict=config_dict):
71+
print(" * " + service)
72+
print("\nChoose one of these or add a new service using:")
73+
else:
74+
print(
75+
"The config file ~/.pyauthenticator does not contain any services. To add a new service use:"
76+
)
77+
print(" pyauthenticator --add <qr-code.png> <servicename>\n")
4678

4779

4880
if __name__ == "__main__":

tests/test_cmd.py

+47-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
import os
33
import subprocess
44
import json
5+
from contextlib import redirect_stdout
6+
from io import StringIO
57
from pyauthenticator.share import expand_path, write_config, config_file
8+
from pyauthenticator.__main__ import command_line_parser
69

710

8-
class MyTestCase(unittest.TestCase):
11+
class CmdSubprocessTest(unittest.TestCase):
912
@classmethod
1013
def setUpClass(cls):
1114
cls.config_dict = {
@@ -36,7 +39,49 @@ def test_main_generate_qr_code(self):
3639
)
3740
with open(self.config_path, "r") as f:
3841
config_dict = json.load(f)
39-
self.assertEqual(len(config_dict.keys()), 2)
42+
self.assertTrue("test2" in config_dict.keys())
43+
44+
45+
class CmdParserTest(unittest.TestCase):
46+
@classmethod
47+
def setUpClass(cls):
48+
cls.config_dict = {
49+
"test": "otpauth://totp/Test%3A%20root%40github.com?secret=6IQXETC4ADOSMMUN&issuer=Test"
50+
}
51+
cls.config_path = expand_path(config_file)
52+
if not os.path.exists(cls.config_path):
53+
write_config(
54+
config_dict=cls.config_dict
55+
)
56+
57+
def test_main_generate_two_factor(self):
58+
with redirect_stdout(StringIO()) as sout:
59+
command_line_parser(cmd_args=["test"])
60+
self.assertEqual(len(sout.getvalue().rstrip('\n')), 6)
61+
with redirect_stdout(StringIO()) as sout:
62+
command_line_parser(cmd_args=["test3"])
63+
self.assertEqual(
64+
sout.getvalue().split("\n")[0],
65+
"The service \"test3\" does not exist."
66+
)
67+
68+
def test_main_generate_qr_code(self):
69+
with redirect_stdout(StringIO()) as sout:
70+
command_line_parser(cmd_args=["-qr", "test"])
71+
self.assertEqual(
72+
sout.getvalue(),
73+
"The qrcode file <test.png> was generated.\n"
74+
)
75+
self.assertTrue(os.path.exists("test.png"))
76+
with redirect_stdout(StringIO()) as sout:
77+
command_line_parser(cmd_args=["-a", "test.png", "test4"])
78+
self.assertEqual(
79+
sout.getvalue(),
80+
"The service 'test4' was added, from file <test.png>.\n"
81+
)
82+
with open(self.config_path, "r") as f:
83+
config_dict = json.load(f)
84+
self.assertTrue("test4" in config_dict.keys())
4085

4186

4287
if __name__ == '__main__':

0 commit comments

Comments
 (0)