Skip to content

Commit 56af4e6

Browse files
committed
refactor(commands): pass args namespace directly
makes later usage of additional args easier without having to change function signatures
1 parent d8b6b2d commit 56af4e6

File tree

16 files changed

+184
-63
lines changed

16 files changed

+184
-63
lines changed

compiler_admin/commands/convert.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from argparse import Namespace
2+
13
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
24
from compiler_admin.services.google import (
35
GROUP_PARTNERS,
@@ -18,7 +20,7 @@
1820
ACCOUNT_TYPE_OU = {"contractor": OU_CONTRACTORS, "partner": OU_PARTNERS, "staff": OU_STAFF}
1921

2022

21-
def convert(username: str, account_type: str) -> int:
23+
def convert(args: Namespace) -> int:
2224
f"""Convert a user of one type to another.
2325
Args:
2426
username (str): The account to convert. Must exist already.
@@ -27,7 +29,13 @@ def convert(username: str, account_type: str) -> int:
2729
Returns:
2830
A value indicating if the operation succeeded or failed.
2931
"""
30-
account = user_account_name(username)
32+
if not hasattr(args, "username"):
33+
raise ValueError("username is required")
34+
if not hasattr(args, "account_type"):
35+
raise ValueError("account_type is required")
36+
37+
account = user_account_name(args.username)
38+
account_type = args.account_type
3139

3240
if not user_exists(account):
3341
print(f"User does not exist: {account}")

compiler_admin/commands/create.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from argparse import Namespace
12
from typing import Sequence
23

34
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
45
from compiler_admin.services.google import GROUP_TEAM, add_user_to_group, CallGAMCommand, user_account_name, user_exists
56

67

7-
def create(username: str, *args: Sequence[str]) -> int:
8+
def create(args: Namespace, *extra: Sequence[str]) -> int:
89
"""Create a new user account in Compiler.
910
1011
The user's password is randomly generated and requires reset on first login.
@@ -18,15 +19,18 @@ def create(username: str, *args: Sequence[str]) -> int:
1819
Returns:
1920
A value indicating if the operation succeeded or failed.
2021
"""
21-
account = user_account_name(username)
22+
if not hasattr(args, "username"):
23+
raise ValueError("username is required")
24+
25+
account = user_account_name(args.username)
2226

2327
if user_exists(account):
2428
print(f"User already exists: {account}")
2529
return RESULT_FAILURE
2630

2731
print(f"User does not exist, continuing: {account}")
2832

29-
res = CallGAMCommand(("create", "user", account, "password", "random", "changepassword", *args))
33+
res = CallGAMCommand(("create", "user", account, "password", "random", "changepassword", *extra))
3034

3135
res += add_user_to_group(account, GROUP_TEAM)
3236

compiler_admin/commands/delete.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1+
from argparse import Namespace
2+
13
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
24
from compiler_admin.services.google import CallGAMCommand, user_account_name, user_exists
35

46

5-
def delete(username: str) -> int:
7+
def delete(args: Namespace) -> int:
68
"""Delete the user account.
79
810
Args:
911
username (str): The account to delete. Must exist and not be an alias.
1012
Returns:
1113
A value indicating if the operation succeeded or failed.
1214
"""
13-
account = user_account_name(username)
15+
if not hasattr(args, "username"):
16+
raise ValueError("username is required")
17+
18+
account = user_account_name(args.username)
1419

1520
if not user_exists(account):
1621
print(f"User does not exist: {account}")

compiler_admin/commands/init.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from argparse import Namespace
12
import os
23
from pathlib import Path
34
from shutil import rmtree
@@ -21,7 +22,7 @@ def _clean_config_dir(config_dir: Path) -> None:
2122
rmtree(path)
2223

2324

24-
def init(admin_user: str, gam: bool = False, gyb: bool = False) -> int:
25+
def init(args: Namespace) -> int:
2526
"""Initialize a new GAM project.
2627
2728
See https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Install-Advanced-GAM
@@ -36,17 +37,21 @@ def init(admin_user: str, gam: bool = False, gyb: bool = False) -> int:
3637
Returns:
3738
A value indicating if the operation succeeded or failed.
3839
"""
40+
if not hasattr(args, "admin_user"):
41+
raise ValueError("admin_user is required")
42+
43+
admin_user = args.admin_user
3944
res = RESULT_SUCCESS
4045

41-
if gam:
46+
if getattr(args, "gam", False):
4247
_clean_config_dir(GAM_CONFIG_PATH)
4348
# GAM is already installed via pyproject.toml
4449
res += CallGAMCommand(("config", "drive_dir", str(GAM_CONFIG_PATH), "verify"))
4550
res += CallGAMCommand(("create", "project"))
4651
res += CallGAMCommand(("oauth", "create"))
4752
res += CallGAMCommand(("user", admin_user, "check", "serviceaccount"))
4853

49-
if gyb:
54+
if getattr(args, "gyb", False):
5055
_clean_config_dir(GYB_CONFIG_PATH)
5156
# download GYB installer to config directory
5257
gyb = GYB_CONFIG_PATH / "gyb-install.sh"

compiler_admin/commands/offboard.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from argparse import Namespace
12
from tempfile import NamedTemporaryFile
23

34
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
@@ -12,7 +13,7 @@
1213
)
1314

1415

15-
def offboard(username: str, alias: str = None) -> int:
16+
def offboard(args: Namespace) -> int:
1617
"""Fully offboard a user from Compiler.
1718
1819
Args:
@@ -22,12 +23,17 @@ def offboard(username: str, alias: str = None) -> int:
2223
Returns:
2324
A value indicating if the operation succeeded or failed.
2425
"""
26+
if not hasattr(args, "username"):
27+
raise ValueError("username is required")
28+
29+
username = args.username
2530
account = user_account_name(username)
2631

2732
if not user_exists(account):
2833
print(f"User does not exist: {account}")
2934
return RESULT_FAILURE
3035

36+
alias = getattr(args, "alias", None)
3137
alias_account = user_account_name(alias)
3238
if alias_account is not None and not user_exists(alias_account):
3339
print(f"Alias target user does not exist: {alias_account}")

compiler_admin/commands/restore.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1+
from argparse import Namespace
12
import pathlib
23

34
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
45
from compiler_admin.services.google import USER_ARCHIVE, CallGYBCommand, user_account_name
56

67

7-
def restore(username: str) -> int:
8+
def restore(args: Namespace) -> int:
89
"""Restore an email backup from a prior offboarding.
910
1011
Args:
1112
username (str): the user account with a local email backup to restore.
1213
Returns:
1314
A value indicating if the operation succeeded or failed.
1415
"""
15-
account = user_account_name(username)
16+
if not hasattr(args, "username"):
17+
raise ValueError("username is required")
18+
19+
account = user_account_name(args.username)
1620
backup_dir = f"GYB-GMail-Backup-{account}"
1721

1822
if not pathlib.Path(backup_dir).exists():

compiler_admin/commands/signout.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1+
from argparse import Namespace
2+
13
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
24
from compiler_admin.services.google import CallGAMCommand, user_account_name, user_exists
35

46

5-
def signout(username: str) -> int:
7+
def signout(args: Namespace) -> int:
68
"""Signs the user out from all active sessions.
79
810
Args:
911
username (str): The account to sign out. Must exist already.
1012
Returns:
1113
A value indicating if the operation succeeded or failed.
1214
"""
13-
account = user_account_name(username)
15+
if not hasattr(args, "username"):
16+
raise ValueError("username is required")
17+
18+
account = user_account_name(args.username)
1419

1520
if not user_exists(account):
1621
print(f"User does not exist: {account}")

compiler_admin/main.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,19 @@ def _subcmd(name, help, add_username_arg=True) -> argparse.ArgumentParser:
6666
if args.command == "info":
6767
return info()
6868
elif args.command == "create":
69-
return create(args.username, *extra)
69+
return create(args, *extra)
7070
elif args.command == "convert":
71-
return convert(args.username, args.account_type)
71+
return convert(args)
7272
elif args.command == "delete":
73-
return delete(args.username)
73+
return delete(args)
7474
elif args.command == "init":
75-
return init(args.username, gam=args.gam, gyb=args.gyb)
75+
return init(args)
7676
elif args.command == "offboard":
77-
return offboard(args.username, args.alias)
77+
return offboard(args)
7878
elif args.command == "restore":
79-
return restore(args.username)
79+
return restore(args)
8080
elif args.command == "signout":
81-
return signout(args.username)
81+
return signout(args)
8282

8383

8484
if __name__ == "__main__":

tests/commands/test_convert.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from argparse import Namespace
12
import pytest
23

34
from compiler_admin.commands import RESULT_FAILURE, RESULT_SUCCESS
@@ -64,18 +65,27 @@ def mock_google_user_is_staff_false(mock_google_user_is_staff):
6465
return mock_google_user_is_staff
6566

6667

68+
def test_convert_user_username_required():
69+
args = Namespace()
70+
71+
with pytest.raises(ValueError, match="username is required"):
72+
convert(args)
73+
74+
6775
def test_convert_user_does_not_exists(mock_google_user_exists, mock_google_move_user_ou):
6876
mock_google_user_exists.return_value = False
6977

70-
res = convert("username", "account_type")
78+
args = Namespace(username="username", account_type="account_type")
79+
res = convert(args)
7180

7281
assert res == RESULT_FAILURE
7382
assert mock_google_move_user_ou.call_count == 0
7483

7584

7685
@pytest.mark.usefixtures("mock_google_user_exists_true")
7786
def test_convert_user_exists_bad_account_type(mock_google_move_user_ou):
78-
res = convert("username", "account_type")
87+
args = Namespace(username="username", account_type="account_type")
88+
res = convert(args)
7989

8090
assert res == RESULT_FAILURE
8191
assert mock_google_move_user_ou.call_count == 0
@@ -85,15 +95,17 @@ def test_convert_user_exists_bad_account_type(mock_google_move_user_ou):
8595
"mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_false"
8696
)
8797
def test_convert_contractor(mock_google_move_user_ou):
88-
res = convert("username", "contractor")
98+
args = Namespace(username="username", account_type="contractor")
99+
res = convert(args)
89100

90101
assert res == RESULT_SUCCESS
91102
mock_google_move_user_ou.assert_called_once()
92103

93104

94105
@pytest.mark.usefixtures("mock_google_user_exists_true", "mock_google_user_is_partner_true", "mock_google_user_is_staff_false")
95106
def test_convert_contractor_user_is_partner(mock_google_remove_user_from_group, mock_google_move_user_ou):
96-
res = convert("username", "contractor")
107+
args = Namespace(username="username", account_type="contractor")
108+
res = convert(args)
97109

98110
assert res == RESULT_SUCCESS
99111
assert mock_google_remove_user_from_group.call_count == 2
@@ -102,7 +114,8 @@ def test_convert_contractor_user_is_partner(mock_google_remove_user_from_group,
102114

103115
@pytest.mark.usefixtures("mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_true")
104116
def test_convert_contractor_user_is_staff(mock_google_remove_user_from_group, mock_google_move_user_ou):
105-
res = convert("username", "contractor")
117+
args = Namespace(username="username", account_type="contractor")
118+
res = convert(args)
106119

107120
assert res == RESULT_SUCCESS
108121
mock_google_remove_user_from_group.assert_called_once()
@@ -113,7 +126,8 @@ def test_convert_contractor_user_is_staff(mock_google_remove_user_from_group, mo
113126
"mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_false"
114127
)
115128
def test_convert_staff(mock_google_add_user_to_group, mock_google_move_user_ou):
116-
res = convert("username", "staff")
129+
args = Namespace(username="username", account_type="staff")
130+
res = convert(args)
117131

118132
assert res == RESULT_SUCCESS
119133
mock_google_add_user_to_group.assert_called_once()
@@ -124,7 +138,8 @@ def test_convert_staff(mock_google_add_user_to_group, mock_google_move_user_ou):
124138
def test_convert_staff_user_is_partner(
125139
mock_google_add_user_to_group, mock_google_remove_user_from_group, mock_google_move_user_ou
126140
):
127-
res = convert("username", "staff")
141+
args = Namespace(username="username", account_type="staff")
142+
res = convert(args)
128143

129144
assert res == RESULT_SUCCESS
130145
mock_google_remove_user_from_group.assert_called_once()
@@ -134,7 +149,8 @@ def test_convert_staff_user_is_partner(
134149

135150
@pytest.mark.usefixtures("mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_true")
136151
def test_convert_staff_user_is_staff(mock_google_add_user_to_group, mock_google_move_user_ou):
137-
res = convert("username", "staff")
152+
args = Namespace(username="username", account_type="staff")
153+
res = convert(args)
138154

139155
assert res == RESULT_FAILURE
140156
assert mock_google_add_user_to_group.call_count == 0
@@ -145,7 +161,8 @@ def test_convert_staff_user_is_staff(mock_google_add_user_to_group, mock_google_
145161
"mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_false"
146162
)
147163
def test_convert_partner(mock_google_add_user_to_group, mock_google_move_user_ou):
148-
res = convert("username", "partner")
164+
args = Namespace(username="username", account_type="partner")
165+
res = convert(args)
149166

150167
assert res == RESULT_SUCCESS
151168
mock_google_add_user_to_group.call_count == 2
@@ -154,7 +171,8 @@ def test_convert_partner(mock_google_add_user_to_group, mock_google_move_user_ou
154171

155172
@pytest.mark.usefixtures("mock_google_user_exists_true", "mock_google_user_is_partner_true", "mock_google_user_is_staff_false")
156173
def test_convert_partner_user_is_partner(mock_google_add_user_to_group, mock_google_move_user_ou):
157-
res = convert("username", "partner")
174+
args = Namespace(username="username", account_type="partner")
175+
res = convert(args)
158176

159177
assert res == RESULT_FAILURE
160178
assert mock_google_add_user_to_group.call_count == 0
@@ -163,7 +181,8 @@ def test_convert_partner_user_is_partner(mock_google_add_user_to_group, mock_goo
163181

164182
@pytest.mark.usefixtures("mock_google_user_exists_true", "mock_google_user_is_partner_false", "mock_google_user_is_staff_true")
165183
def test_convert_partner_user_is_staff(mock_google_add_user_to_group, mock_google_move_user_ou):
166-
res = convert("username", "partner")
184+
args = Namespace(username="username", account_type="partner")
185+
res = convert(args)
167186

168187
assert res == RESULT_SUCCESS
169188
mock_google_add_user_to_group.assert_called_once()

tests/commands/test_create.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from argparse import Namespace
12
import pytest
23

34
from compiler_admin.commands import RESULT_FAILURE, RESULT_SUCCESS
@@ -19,18 +20,27 @@ def mock_google_add_user_to_group(mock_google_add_user_to_group):
1920
return mock_google_add_user_to_group(MODULE)
2021

2122

23+
def test_create_user_username_required():
24+
args = Namespace()
25+
26+
with pytest.raises(ValueError, match="username is required"):
27+
create(args)
28+
29+
2230
def test_create_user_exists(mock_google_user_exists):
2331
mock_google_user_exists.return_value = True
2432

25-
res = create("username")
33+
args = Namespace(username="username")
34+
res = create(args)
2635

2736
assert res == RESULT_FAILURE
2837

2938

3039
def test_create_user_does_not_exists(mock_google_user_exists, mock_google_CallGAMCommand, mock_google_add_user_to_group):
3140
mock_google_user_exists.return_value = False
3241

33-
res = create("username")
42+
args = Namespace(username="username")
43+
res = create(args)
3444

3545
assert res == RESULT_SUCCESS
3646

0 commit comments

Comments
 (0)