autograder .cli .users .upsert-file
Upsert server users from a TSV file.
usage: python3 -m autograder.cli.users.upsert-file [-h] [--version]
[--server SERVER]
[--user USER] [--pass PASS]
[--dry-run]
[--skip-inserts]
[--skip-updates]
[--send-emails]
[--testing-mode]
PATH
Upsert server users from a TSV file.
positional arguments:
PATH Path to a TSV file where each line contains up to seven
columns: [email, pass, name, role, course, course-role,
lms-id]. Only the email is required. Leading and trailing
whitespace is stripped from all fields, including pass.
If pass is empty, a password will be randomly generated
and emailed to the user.
options:
-h, --help show this help message and exit
--version show program's version number and exit
command-specific options:
--server SERVER The URL of the autograder server to communicate with.
--user USER The email of the user making this request.
--pass PASS The password of the user making this request.
--dry-run Do not commit/finalize the operation, just do all the
steps and state what the result would look like.
--skip-inserts Skip insert operations.
--skip-updates Skip update operations.
--send-emails Send any relevant emails to users affected by this
operation (e.g., a user being enrolled in a course).
testing options:
--testing-mode Run as if a test is being run (default: False).
1# pylint: disable=invalid-name 2 3""" 4Upsert server users from a TSV file. 5""" 6 7import argparse 8import sys 9import typing 10 11import edq.util.hash 12 13import autograder.api.config 14import autograder.model.user 15import autograder.api.users.upsert 16import autograder.cli.parser 17import autograder.util.load 18 19API_PARAMS: typing.List[autograder.api.config.APIParam] = [ 20 autograder.api.config.PARAM_SERVER, 21 autograder.api.config.PARAM_USER_EMAIL, 22 autograder.api.config.PARAM_USER_PASS, 23 24 autograder.api.config.PARAM_DRY_RUN, 25 autograder.api.config.PARAM_SKIP_INSERTS, 26 autograder.api.config.PARAM_SKIP_UPDATES, 27 28 autograder.api.config.PARAM_SEND_EMAILS, 29 30 autograder.api.config.PARAM_RAW_SERVER_USERS, 31] 32 33def run_cli(args: argparse.Namespace) -> int: 34 """ Run the CLI. """ 35 36 config = args._config_info.application_config 37 config.raw_server_users = _load_users(args.path) 38 39 result = autograder.api.users.upsert.send(config, exit_on_error = True) 40 print(edq.util.json.dumps(result, indent = 4)) 41 42 return 0 43 44def _load_users(path: str) -> typing.List[typing.Dict[str, str]]: 45 """ Load raw user entries from a TSV file. """ 46 47 users = [] 48 49 rows = autograder.util.load.load_tsv(path, 7) 50 for (lineno, row) in enumerate(rows): 51 email = row.pop(0) 52 53 password = '' 54 if (len(row) > 0): 55 password = row.pop(0) 56 if (password != ''): 57 password = edq.util.hash.sha256_hex(password) 58 59 name = '' 60 if (len(row) > 0): 61 name = row.pop(0) 62 63 role = 'user' 64 if (len(row) > 0): 65 role = row.pop(0) 66 role = role.lower() 67 68 if (not autograder.model.user.ServerRole.has_value(role)): 69 raise ValueError(f"File ('{path}') line ({lineno}) has an invalid role '{role}'.") 70 71 course = '' 72 if (len(row) > 0): 73 course = row.pop(0) 74 75 course_role = 'unknown' 76 if (len(row) > 0): 77 course_role = row.pop(0) 78 course_role = course_role.lower() 79 80 if (not autograder.model.user.CourseRole.has_value(course_role)): 81 raise ValueError(f"File ('{path}') line ({lineno}) has an invalid course role '{course_role}'.") 82 83 course_lms_id = '' 84 if (len(row) > 0): 85 course_lms_id = row.pop(0) 86 87 users.append({ 88 'email': email, 89 'pass': password, 90 'name': name, 91 'role': role, 92 'course': course, 93 'course-role': course_role, 94 'course-lms-id': course_lms_id, 95 }) 96 97 return users 98 99def main() -> int: 100 """ Get a parser, parse the args, and call run. """ 101 102 return run_cli(_get_parser().parse_args()) 103 104def _get_parser() -> argparse.ArgumentParser: 105 """ Get a parser for this operation. """ 106 107 parser = autograder.cli.parser.get_parser( 108 __doc__.strip(), 109 API_PARAMS) 110 111 parser.add_argument('path', metavar = 'PATH', 112 action = 'store', type = str, 113 help = 'Path to a TSV file where each line contains up to seven columns:' 114 + ' [email, pass, name, role, course, course-role, lms-id].' 115 + ' Only the email is required. Leading and trailing whitespace is stripped' 116 + ' from all fields, including pass. If pass is empty, a password will be' 117 + ' randomly generated and emailed to the user.') 118 119 return parser 120 121if (__name__ == '__main__'): 122 sys.exit(main())
API_PARAMS: List[autograder.api.config.APIParam] =
[<autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>, <autograder.api.config.APIParam object>]
def
run_cli(args: argparse.Namespace) -> int:
34def run_cli(args: argparse.Namespace) -> int: 35 """ Run the CLI. """ 36 37 config = args._config_info.application_config 38 config.raw_server_users = _load_users(args.path) 39 40 result = autograder.api.users.upsert.send(config, exit_on_error = True) 41 print(edq.util.json.dumps(result, indent = 4)) 42 43 return 0
Run the CLI.
def
main() -> int:
100def main() -> int: 101 """ Get a parser, parse the args, and call run. """ 102 103 return run_cli(_get_parser().parse_args())
Get a parser, parse the args, and call run.