Skip to content

Commit

Permalink
Upaded the LMS CLI for the new API.
Browse files Browse the repository at this point in the history
  • Loading branch information
eriq-augustine committed Nov 22, 2023
1 parent 57e309a commit ad7345a
Show file tree
Hide file tree
Showing 19 changed files with 355 additions and 152 deletions.
34 changes: 0 additions & 34 deletions autograder/api/canvas/syncusers.py

This file was deleted.

34 changes: 0 additions & 34 deletions autograder/api/canvas/uploadscores.py

This file was deleted.

40 changes: 29 additions & 11 deletions autograder/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

class APIParam(object):
def __init__(self, key, description,
config_key = None, required = True, hash = False):
config_key = None, required = True, cli_param = True,
parser_options = {'action': 'store', 'type': str},
hash = False):
self.key = str(key)
if ((key is None) or (self.key == '')):
raise autograder.api.error.APIError("APIParam cannot have an empty key.")
Expand All @@ -29,6 +31,8 @@ def __init__(self, key, description,
self.config_key = key

self.required = required
self.cli_param = cli_param
self.parser_options = parser_options
self.hash = hash

def parse_api_config(config, params,
Expand Down Expand Up @@ -171,30 +175,44 @@ def get_argument_parser(
+ " (default: %(default)s).")

for param in params:
if (not param.cli_param):
continue

parser.add_argument(f'--{param.config_key}', dest = param.config_key,
action = 'store', type = str,
help = param.description)
help = param.description,
**param.parser_options)

return parser

# Common API params.

PARAM_ASSIGNMENT_ID = APIParam('assignment-id',
'The ID of the assignment to make this request to.',
config_key = 'assignment', required = True)

PARAM_COURSE_ID = APIParam('course-id',
'The ID of the course to make this request to.',
config_key = 'course', required = True)

PARAM_DRY_RUN = APIParam('dry-run',
'Do not commit/finalize the operation,'
+ ' just do all the steps and state what the result would look like.',
required = False,
parser_options = {'action': 'store_true', 'default': False})

PARAM_SKIP_EMAILS = APIParam('skip-emails',
'Skip sending any emails. Be aware that this may result in inaccessible information.',
required = False,
parser_options = {'action': 'store_true', 'default': False})

PARAM_TARGET_EMAIL = APIParam('target-email',
'The email of the user that is the target of this request.',
required = True)

PARAM_USER_EMAIL = APIParam('user-email',
'The email of the user making this request.',
config_key = 'user', required = True)

PARAM_USER_PASS = APIParam('user-pass',
'The password of the user making this request.',
config_key = 'pass', required = True, hash = True)

PARAM_ASSIGNMENT_ID = APIParam('assignment-id',
'The ID of the assignment to make this request to.',
config_key = 'assignment', required = True)

PARAM_TARGET_EMAIL = APIParam('target-email',
'The email of the user that is the target of this request.',
required = True)
File renamed without changes.
23 changes: 23 additions & 0 deletions autograder/api/lms/syncusers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import autograder.api.common
import autograder.api.config

API_ENDPOINT = 'lms/sync/users'
API_PARAMS = [
autograder.api.config.PARAM_COURSE_ID,
autograder.api.config.PARAM_USER_EMAIL,
autograder.api.config.PARAM_USER_PASS,
autograder.api.config.PARAM_DRY_RUN,
autograder.api.config.PARAM_SKIP_EMAILS,
]

DESCRIPTION = 'Sync autograder users with LMS users.'

def send(arguments, **kwargs):
return autograder.api.common.handle_api_request(arguments, API_PARAMS, API_ENDPOINT, **kwargs)

def _get_parser():
parser = autograder.api.config.get_argument_parser(
description = DESCRIPTION,
params = API_PARAMS)

return parser
29 changes: 29 additions & 0 deletions autograder/api/lms/uploadscores.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import autograder.api.common
import autograder.api.config

API_ENDPOINT = 'lms/upload/scores'
API_PARAMS = [
autograder.api.config.PARAM_COURSE_ID,
autograder.api.config.PARAM_USER_EMAIL,
autograder.api.config.PARAM_USER_PASS,

autograder.api.config.APIParam('assignment-lms-id',
'The LMS ID of the assignment to upload scores to.',
required = True),

autograder.api.config.APIParam('scores',
'A list of scores to upload.',
required = True, cli_param = False),
]

DESCRIPTION = 'Get the information for an LMS user.'

def send(arguments, **kwargs):
return autograder.api.common.handle_api_request(arguments, API_PARAMS, API_ENDPOINT, **kwargs)

def _get_parser():
parser = autograder.api.config.get_argument_parser(
description = DESCRIPTION,
params = API_PARAMS)

return parser
22 changes: 22 additions & 0 deletions autograder/api/lms/userget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import autograder.api.common
import autograder.api.config

API_ENDPOINT = 'lms/user/get'
API_PARAMS = [
autograder.api.config.PARAM_COURSE_ID,
autograder.api.config.PARAM_USER_EMAIL,
autograder.api.config.PARAM_USER_PASS,
autograder.api.config.PARAM_TARGET_EMAIL,
]

DESCRIPTION = 'Get information for an LMS user.'

def send(arguments, **kwargs):
return autograder.api.common.handle_api_request(arguments, API_PARAMS, API_ENDPOINT, **kwargs)

def _get_parser():
parser = autograder.api.config.get_argument_parser(
description = DESCRIPTION,
params = API_PARAMS)

return parser
30 changes: 0 additions & 30 deletions autograder/cli/canvas/sync-users.py

This file was deleted.

61 changes: 61 additions & 0 deletions autograder/cli/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
HEADERS = ['email', 'name', 'role', 'lms-id']
SYNC_HEADERS = HEADERS + ['operation']

SYNC_USERS_KEYS = [
('add-users', 'Added', 'add'),
('mod-users', 'Modified', 'mod'),
('del-users', 'Deleted', 'delete'),
('skip-users', 'Skipped', 'skip'),
]

def list_users(users, table = False):
if (table):
_list_users_table(users)
else:
_list_users(users)

def _list_users(users, indent = ''):
for user in users:
print(indent + "Email:", user['email'])
print(indent + "Name:", user['name'])
print(indent + "Role:", user['role'])
print(indent + "LMS ID:", user['lms-id'])
print()

def _list_users_table(users, header = True, keys = HEADERS):
if (header):
print("\t".join(keys))

for user in users:
row = [user[key] for key in keys]
print("\t".join([str(value) for value in row]))

def list_sync_users(sync_users, table = False):
if (table):
_list_sync_users_table(sync_users)
else:
_list_sync_users(sync_users)

def _list_sync_users(sync_users):
count = (len(sync_users['add-users'])
+ len(sync_users['mod-users'])
+ len(sync_users['del-users']))
print("Synced %d users." % (count))

for (key, label, _) in SYNC_USERS_KEYS:
users = sync_users[key]
if (len(users) == 0):
continue

print("%s Users:" % (label))
_list_users(users, indent = ' ')

def _list_sync_users_table(sync_users):
print("\t".join(SYNC_HEADERS))

for (key, _, op) in SYNC_USERS_KEYS:
users = sync_users[key]
for user in users:
user['operation'] = op

_list_users_table(users, header = False, keys = SYNC_HEADERS)
File renamed without changes.
File renamed without changes.
33 changes: 33 additions & 0 deletions autograder/cli/lms/get-user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import sys

import autograder.api.lms.userget
import autograder.cli.common

def run(arguments):
result = autograder.api.lms.userget.send(arguments, exit_on_error = True)

if (not result['found-autograder-user']):
print("No matching autograder user found.")
return 0

if (not result['found-lms-user']):
print("No matching lms user found.")
return 0

autograder.cli.common.list_users([result['user']], table = arguments.table)
return 0

def main():
return run(_get_parser().parse_args())

def _get_parser():
parser = autograder.api.lms.userget._get_parser()

parser.add_argument('--table', dest = 'table',
action = 'store_true', default = False,
help = 'Output the results as a TSV table with a header (default: %(default)s).')

return parser

if (__name__ == '__main__'):
sys.exit(main())
24 changes: 24 additions & 0 deletions autograder/cli/lms/sync-users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import sys

import autograder.api.lms.syncusers
import autograder.cli.common

def run(arguments):
result = autograder.api.lms.syncusers.send(arguments, exit_on_error = True)
autograder.cli.common.list_sync_users(result, table = arguments.table)
return 0

def main():
return run(_get_parser().parse_args())

def _get_parser():
parser = autograder.api.lms.syncusers._get_parser()

parser.add_argument('--table', dest = 'table',
action = 'store_true', default = False,
help = 'Output the results as a TSV table with a header (default: %(default)s).')

return parser

if (__name__ == '__main__'):
sys.exit(main())
Loading

0 comments on commit ad7345a

Please sign in to comment.