def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) if args.version: print("okpy=={}".format(client.__version__)) exit(0) elif args.update: print("Current version: {}".format(client.__version__)) software_update.check_version(args.server, client.__version__, client.FILE_NAME, timeout=10) exit(0) assign = None try: if args.authenticate: auth.authenticate(True) # Instantiating assignment assign = assignment.load_config(args.config, args) assign.load() if args.tests: print('Available tests:') for name in assign.test_map: print(' ' + name) exit(0) msgs = messages.Messages() for name, proto in assign.protocol_map.items(): log.info('Execute {}.run()'.format(name)) proto.run(msgs) msgs['timestamp'] = str(datetime.now()) except ex.LoadingException as e: log.warning('Assignment could not load', exc_info=True) print('Error loading assignment: ' + str(e)) except ex.OkException as e: log.warning('General OK exception occurred', exc_info=True) print('Error: ' + str(e)) except KeyboardInterrupt: log.info('KeyboardInterrupt received.') finally: if not args.no_update: try: software_update.check_version(args.server, client.__version__, client.FILE_NAME) except KeyboardInterrupt: pass if assign: assign.dump_tests()
def run(self, messages): """If the --restore flag is present, allow users to select a backup to restore from. """ if not self.args.restore: return self.access_token = auth.authenticate(self.args.authenticate) print("Loading backups...") response = self.request("user") if not response: print("Could not connect to server.") return user = response["data"]["results"][0] email = user["email"][0] assign_id = self.get_assign_id(self.assignment.endpoint) backups = self.get_backups(email, assign_id) current_time = datetime.now() print("0: Cancel Restore") for current in range(0, len(backups)): backup = backups[current] time_diff = get_time_diff(backup["timestamp"], current_time) print("{0}: {1} by {2}".format(current + 1, time_diff, backup["submitter"])) response = input("Backup #: ") selection = int(response) - 1 if selection < 0 or selection >= len(backups): print("Invalid option for restoring backups.") return self.restore_backup(backups[selection])
def run(self, messages): if self.args.local or self.args.restore: print("Cannot backup when running ok with --local.") return if self.args.revise: action = 'Revise' elif self.args.submit: action = 'Submission' else: action = 'Backup' message_list = self.load_unsent_messages() access_token = auth.authenticate(False) log.info('Authenticated with access token') log.info('Sending unsent messages') if not access_token: print("Not authenticated. Cannot send {} to server".format(action)) self.dump_unsent_messages(message_list) return # Messages from the current backup to send first is_send_first = self.args.submit or self.args.revise subm_messages = [messages] if is_send_first else [] if is_send_first: response = self.send_all_messages(access_token, subm_messages, current=True) if message_list: self.send_all_messages(access_token, message_list, current=False) else: message_list.append(messages) response = self.send_all_messages(access_token, message_list, current=False) prefix = 'http' if self.args.insecure else 'https' base_url = '{0}://{1}'.format(prefix, self.args.server) + '/{}/{}/{}' if isinstance(response, dict): print('{action} successful for user: {email}'.format(action=action, email=response['data']['email'])) submission_type = 'submissions' if self.args.submit else 'backups' url = base_url.format(response['data']['assignment'], submission_type, response['data']['key']) if self.args.submit or self.args.backup: print('URL: {0}'.format(url)) if self.args.backup: print('NOTE: this is only a backup. ' 'To submit your assignment, use:\n' '\tpython3 ok --submit') self.dump_unsent_messages(message_list + subm_messages) print()
def run(self, messages): """If the --restore flag is present, allow users to select a backup to restore from. """ if not self.args.restore: return self.access_token = auth.authenticate(self.args.authenticate) print('Loading backups...') response = self.request('user') if not response: print('Could not connect to server.') return user = response['data']['results'][0] email = user['email'][0] assign_id = self.get_assign_id(self.assignment.endpoint) backups = self.get_backups(email, assign_id) current_time = datetime.now() print('0: Cancel Restore') for current in range(0, len(backups)): backup = backups[current] time_diff = get_time_diff(backup['timestamp'], current_time) print('{0}: {1} by {2}'.format(current + 1, time_diff, backup['submitter'])) response = input('Backup #: ') selection = int(response) - 1 if selection < 0 or selection >= len(backups): print("Invalid option for restoring backups.") return self.restore_backup(backups[selection])
def run(self, messages): if self.args.local or self.args.export or self.args.restore: return message_list = self.load_unsent_messages() message_list.append(messages) self.check_ssl() access_token = auth.authenticate(False) log.info('Authenticated with access token %s', access_token) response = self.send_all_messages(access_token, message_list) if isinstance(response, dict): print('Backup successful for user: '******'{0}'.format(response['data']['email'])) if self.args.submit or self.args.backup: print('URL: https://ok-server.appspot.com/#/' '{0}/submission/{1}'.format(response['data']['course'], response['data']['key'])) if self.args.backup: print('NOTE: this is only a backup. ' 'To submit your assignment, use:\n' '\tpython3 ok --submit') self.dump_unsent_messages(message_list) print()
def run(self, messages): return if self.args.local or self.args.export or self.args.restore: return message_list = self.load_unsent_messages() message_list.append(messages) self.check_ssl() access_token = auth.authenticate(False) log.info('Authenticated with access token %s', access_token) response = self.send_all_messages(access_token, message_list) if isinstance(response, dict): print('Backup successful for user: '******'{0}'.format(response['data']['email'])) if self.args.submit or self.args.backup: print('URL: https://ok-server.appspot.com/#/' '{0}/submission/{1}'.format(response['data']['course'], response['data']['key'])) if self.args.backup: print('NOTE: this is only a backup. ' 'To submit your assignment, use:\n' '\tpython3 ok --submit') self.dump_unsent_messages(message_list) print()
def authenticate(self, force=False, inline=False): if not inline: return auth.authenticate(self.cmd_args, endpoint=self.endpoint, force=force) else: return auth.notebook_authenticate(self.cmd_args, force=force)
def run(self, messages): """If the --export parameter was used, downloads all submissions for the current assignment from the server and then exits """ if not self.args.export: return self.access_token = auth.authenticate(self.args.authenticate) log.info('Authenticated with access token %s', self.access_token) data = None try: data = pickle.load(open(EXPORT_CACHE, "rb")) except IOError: data = { 'endpoint': self.assignment.endpoint } data['assign'], data['course'] = self.get_ids(data['endpoint']) data['students'] = self.get_students(data['course']) if not data['students']: return data['current'] = 0 current_student = 0 try: if not os.path.exists(SUBMISSION_DIR): os.makedirs(SUBMISSION_DIR) downloads_left = len(data['students']) - data['current'] print("{0} submissions left to download.".format(downloads_left)) for current_student in range(data['current'], len(data['students'])): student = data['students'][current_student] try: self.download_submission(student, data['assign']) except (IOError, error.HTTPError): data['current'] = current_student abort(data, len(data['students']), current_student) return data['current'] = current_student + 1 except KeyboardInterrupt: pickle.dump(data, open("export_cache.pkl", "wb")) abort(data, len(data['students']), current_student) return print("Submissions downloaded.") if os.path.exists(EXPORT_CACHE): os.remove(EXPORT_CACHE)
def run(self, messages): """Responsible for unlocking each test. The unlocking process can be aborted by raising a KeyboardInterrupt or an EOFError. RETURNS: dict; mapping of test name (str) -> JSON-serializable object. It is up to each test to determine what information is significant for analytics. """ if not self.args.unlock: return if not self.args.local: self.access_token = auth.authenticate(False) format.print_line('~') print('Unlocking tests') print() print('At each "{}", type what you would expect the output to be.'. format(self.PROMPT)) print('Type {} to quit'.format(self.EXIT_INPUTS[0])) print() for test in self.assignment.specified_tests: log.info('Unlocking test {}'.format(test.name)) self.current_test = test.name try: test.unlock(self.interact) except (KeyboardInterrupt, EOFError): try: # TODO(albert): When you use Ctrl+C in Windows, it # throws two exceptions, so you need to catch both # of them. Find a cleaner fix for this. print() print('-- Exiting unlocker --') except (KeyboardInterrupt, EOFError): pass print() break messages['unlock'] = self.analytics
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) # Checking user's Python bit version bit_v = (8 * struct.calcsize("P")) log.debug("Python {} ({}bit)".format(sys.version, bit_v)) if args.version: print("okpy=={}".format(client.__version__)) exit(0) elif args.update: print("Current version: {}".format(client.__version__)) did_update = software_update.check_version(args.server, client.__version__, client.FILE_NAME, timeout=10) exit(not did_update) # exit with error if ok failed to update assign = None try: if args.get_token: if args.nointeract: print_error( "Cannot pass in --get-token and --nointeract, the only way to get a token is by interaction" ) exit(1) access_token = auth.authenticate(args, force=True) print("Token: {}".format(access_token)) exit(not access_token) # exit with error if no access_token # Instantiating assignment assign = assignment.load_assignment(args.config, args) if assign.decryption_keypage: # do not allow running locally if decryption keypage is provided args.local = False if args.autobackup_actual_run_sync: assign.autobackup(run_sync=True) # do not dump tests back out, this overwrites any changes that may have been made assign = None exit(0) if args.generate_encryption_key: assign.generate_encryption_key(args.generate_encryption_key) exit(0) if args.encrypt: assign.encrypt(args.encrypt, args.encrypt_padding) # do not dump tests back out, this overwrites any changes that may have been made assign = None exit(0) if args.decrypt is not None: raise ex.ForceDecryptionException(args.decrypt) if args.tests: print('Available tests:') for name in assign.test_map: print(' ' + name) exit(0) if args.autobackup: assign.autobackup(run_sync=False) exit(0) force_authenticate = args.authenticate retry = True while retry: retry = False if force_authenticate: if args.nointeract: print_error( "Cannot pass in --authenticate and --nointeract") exit(1) # Authenticate and check for success if not assign.authenticate(force=True): exit(1) try: msgs = messages.Messages() for name, proto in assign.protocol_map.items(): log.info('Execute {}.run()'.format(name)) proto.run(msgs) msgs['timestamp'] = str(datetime.now()) except ex.AuthenticationException as e: if not force_authenticate: force_authenticate = True retry = True elif not args.no_browser: args.no_browser = True retry = True if retry: msg = "without a browser" if args.no_browser else "with a browser" log.warning( 'Authentication exception occurred; will retry {0}'. format(msg), exc_info=True) print_error( 'Authentication error; will try to re-authenticate {0}...' .format(msg)) else: raise # outer handler will be called except ex.ForceDecryptionException as e: assign.decrypt(e.keys) # begin an autobackup assign.autobackup(run_sync=False) # do not dump tests back out, this could overwrite any changes that may have been made assign = None exit(0) except ex.LoadingException as e: log.warning('Assignment could not load', exc_info=True) print_error('Error loading assignment: ' + str(e)) except ex.AuthenticationException as e: log.warning('Authentication exception occurred', exc_info=True) print_error('Authentication error: {0}'.format(e)) except ex.EarlyExit as e: log.warning('OK exited early (non-error)') print_error(str(e)) except ex.OkException as e: log.warning('General OK exception occurred', exc_info=True) print_error('Error: ' + str(e)) except KeyboardInterrupt: log.info('KeyboardInterrupt received.') finally: if not args.no_update and not args.local: try: software_update.check_version(args.server, client.__version__, client.FILE_NAME) except KeyboardInterrupt: pass if assign: assign.dump_tests()
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() logging.basicConfig(format=LOGGING_FORMAT) log = logging.getLogger(__name__) if args.debug: log.setLevel(logging.INFO) else: log.setLevel(logging.ERROR) log.info(args) if args.version: print("okpy=={}".format(client.__version__)) exit(0) if not args.local and not args.insecure: try: import ssl except: log.warning('Error importing ssl', stack_info=True) sys.exit("SSL Bindings are not installed. You can install python3 SSL bindings or \nrun ok locally with python3 ok --local") server_thread, timer_thread = None, None try: print("You are running version {0} of ok.py".format(client.__version__)) cases = {case.type: case for case in core.get_testcases(config.cases)} assignment = None try: assignment = loading.load_tests(args.tests, cases) except exceptions.OkException as e: print('Error:', e) exit(1) log.info('Replacing stdout with OutputLogger') output_logger = sys.stdout = output.OutputLogger() log.info('Instantiating protocols') protocols = [p(args, assignment, output_logger, log) for p in protocol.get_protocols(config.protocols)] messages = dict() msg_list= [] try: with open(BACKUP_FILE, 'rb') as fp: msg_list = pickle.load(fp) log.info('Loaded %d backed up messages from %s', len(msg_list), BACKUP_FILE) except (IOError, EOFError) as e: log.info('Error reading from ' + BACKUP_FILE \ + ', assume nothing backed up') for proto in protocols: log.info('Execute %s.on_start()', proto.name) messages[proto.name] = proto.on_start() messages['timestamp'] = str(datetime.now()) interact_msg = {} for proto in protocols: log.info('Execute %s.on_interact()', proto.name) interact_msg[proto.name] = proto.on_interact() interact_msg['timestamp'] = str(datetime.now()) # TODO(denero) Print server responses. if not args.local: msg_list.append(interact_msg) try: access_token = auth.authenticate(args.authenticate) log.info('Authenticated with access token %s', access_token) msg_list.append(messages) print("Attempting to send files to server...") network.dump_to_server(access_token, msg_list, assignment['name'], args.server, args.insecure, client.__version__, log, send_all=args.submit) except error.URLError as ex: log.warning('on_start messages not sent to server: %s', str(e)) with open(BACKUP_FILE, 'wb') as fp: log.info('Save %d unsent messages to %s', len(msg_list), BACKUP_FILE) pickle.dump(msg_list, fp) os.fsync(fp) if len(msg_list) == 0: print("Server submission successful") except KeyboardInterrupt: print("Quitting ok.") finally: if assignment: log.info('Dump tests for %s to %s', assignment['name'], args.tests) loading.dump_tests(args.tests, assignment, log)
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) # Checking user's Python bit version bit_v = (8 * struct.calcsize("P")) log.debug("Python {} ({}bit)".format(sys.version, bit_v)) if args.version: print("okpy=={}".format(client.__version__)) exit(0) elif args.update: print("Current version: {}".format(client.__version__)) did_update = software_update.check_version( args.server, client.__version__, client.FILE_NAME, timeout=10) exit(not did_update) # exit with error if ok failed to update assign = None try: if args.get_token: access_token = auth.authenticate(args, force=True) print("Token: {}".format(access_token)) exit(not access_token) # exit with error if no access_token # Instantiating assignment assign = assignment.load_assignment(args.config, args) if args.authenticate: # Authenticate and check for success if not assign.authenticate(force=True): exit(1) if args.tests: print('Available tests:') for name in assign.test_map: print(' ' + name) exit(0) msgs = messages.Messages() for name, proto in assign.protocol_map.items(): log.info('Execute {}.run()'.format(name)) proto.run(msgs) msgs['timestamp'] = str(datetime.now()) except ex.LoadingException as e: log.warning('Assignment could not load', exc_info=True) print('Error loading assignment: ' + str(e)) except ex.AuthenticationException as e: log.warning('Authentication exception occurred', exc_info=True) print('Authentication error: {0}'.format(e)) except ex.OkException as e: log.warning('General OK exception occurred', exc_info=True) print('Error: ' + str(e)) except KeyboardInterrupt: log.info('KeyboardInterrupt received.') finally: if not args.no_update and not args.local: try: software_update.check_version(args.server, client.__version__, client.FILE_NAME) except KeyboardInterrupt: pass if assign: assign.dump_tests()
import sys import os from local_server import open_in_browser from client.utils import auth from client.cli.ok import parse_input args = parse_input() args.parsons = True if not auth.authenticate(args): exit(1) open_in_browser(args)
def authenticate(self, force=False, inline=False, nointeract=False): nointeract = nointeract or self.cmd_args.nointeract if not inline: return auth.authenticate(self.cmd_args, endpoint=self.endpoint, force=force, nointeract=nointeract) else: return auth.notebook_authenticate(self.cmd_args, force=force, nointeract=nointeract)
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) # Checking user's Python bit version bit_v = (8 * struct.calcsize("P")) log.debug("Python {} ({}bit)".format(sys.version, bit_v)) if args.version: print("okpy=={}".format(client.__version__)) exit(0) elif args.update: print("Current version: {}".format(client.__version__)) did_update = software_update.check_version( args.server, client.__version__, client.FILE_NAME, timeout=10) exit(not did_update) # exit with error if ok failed to update assign = None try: if args.get_token: access_token = auth.authenticate(args, force=True) print("Token: {}".format(access_token)) exit(not access_token) # exit with error if no access_token # Instantiating assignment assign = assignment.load_assignment(args.config, args) if args.authenticate: # Authenticate and check for success if not assign.authenticate(force=True): exit(1) if args.tests: print('Available tests:') for name in assign.test_map: print(' ' + name) exit(0) msgs = messages.Messages() for name, proto in assign.protocol_map.items(): log.info('Execute {}.run()'.format(name)) proto.run(msgs) msgs['timestamp'] = str(datetime.now()) except ex.LoadingException as e: log.warning('Assignment could not load', exc_info=True) print('Error loading assignment: ' + str(e)) except ex.AuthenticationException as e: log.warning('Authentication exception occurred', exc_info=True) print('Authentication error: {0}'.format(e)) except ex.EarlyExit as e: log.warning('OK exited early (non-error)') print(str(e)) except ex.OkException as e: log.warning('General OK exception occurred', exc_info=True) print('Error: ' + str(e)) except KeyboardInterrupt: log.info('KeyboardInterrupt received.') finally: if not args.no_update and not args.local: try: software_update.check_version(args.server, client.__version__, client.FILE_NAME) except KeyboardInterrupt: pass if assign: assign.dump_tests()
) with open('ok', 'rb') as f: github_asset = post_request( 'https://uploads.github.com/repos/{}/releases/{}/assets'.format( GITHUB_REPO, github_release['id']), params={'name': 'ok'}, headers={ 'Authorization': 'token ' + github_token, 'Content-Type': 'application/octet-stream', }, data=f, ) print('Updating version on {}...'.format(OK_SERVER_URL)) args = assignment.Settings(server=OK_SERVER_URL) access_token = auth.authenticate(args, force=True) post_request( 'https://{}/api/v3/version/ok-client'.format(OK_SERVER_URL), headers={ 'Authorization': 'Bearer ' + access_token, }, json={ 'current_version': new_release, 'download_link': github_asset['browser_download_url'], }, ) print('Uploading release to PyPI...') shell('python setup.py sdist bdist_wheel upload') print()
github_asset = post_request( 'https://uploads.github.com/repos/{}/releases/{}/assets'.format( GITHUB_REPO, github_release['id']), params={ 'name': 'ok' }, headers={ 'Authorization': 'token ' + github_token, 'Content-Type': 'application/octet-stream', }, data=f, ) print('Updating version on {}...'.format(OK_SERVER_URL)) args = assignment.Settings(server=OK_SERVER_URL) access_token = auth.authenticate(args) post_request('https://{}/api/v3/version/ok-client'.format(OK_SERVER_URL), headers={ 'Authorization': 'Bearer ' + access_token, }, json={ 'current_version': new_release, 'download_link': github_asset['browser_download_url'], }, ) print('Uploading release to PyPI...') shell('python setup.py sdist bdist_wheel upload') print() print('Released okpy=={}'.format(new_release))
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) if args.version: print("okpy=={}".format(client.__version__)) exit(0) # Check if ssl is available if not args.local and not args.insecure: try: import ssl except: log.warning('Error importing ssl', stack_info=True) sys.exit("SSL Bindings are not installed. You can install python3 SSL bindings or \nrun ok locally with python3 ok --local") # Load assignment try: assign = assignment.load_config(args.config, args) except (ex.LoadingException, ex.SerializeException) as e: print(str(e)) exit(1) except KeyboardInterrupt: print("Quitting ok.") # Load backup files try: with open(BACKUP_FILE, 'rb') as fp: msg_list = pickle.load(fp) log.info('Loaded %d backed up messages from %s', len(msg_list), BACKUP_FILE) except (IOError, EOFError) as e: log.info('Error reading from ' + BACKUP_FILE \ + ', assume nothing backed up') msg_list = [] except KeyboardInterrupt: print("Quitting ok.") try: # Run protocol.on_start start_messages = dict() for name, proto in assign.protocol_map.items(): log.info('Execute {}.on_start()'.format(name)) start_messages[name] = proto.on_start() start_messages['timestamp'] = str(datetime.now()) # Run protocol.on_interact interact_msg = {} for name, proto in assign.protocol_map.items(): log.info('Execute {}.on_interact()'.format(name)) interact_msg[name] = proto.on_interact() interact_msg['timestamp'] = str(datetime.now()) except KeyboardInterrupt: print("Quitting ok.") finally: # Running protocols is the only task that modifies the assignment, so # dumping is only necessary here. assign.dump_tests() # Send request to server try: # TODO(denero) Print server responses. if not args.local: msg_list.append(interact_msg) try: access_token = auth.authenticate(args.authenticate) log.info('Authenticated with access token %s', access_token) msg_list.append(start_messages) print("Backing up your work...") response = network.dump_to_server(access_token, msg_list, assign.endpoint, args.server, args.insecure, client.__version__, log, send_all=args.submit) if response: # Hardcode course id- we need to return it from the server at some point... print("Back-up successful: https://ok-server.appspot.com/#/5165212546105344/submission/{0}".format(response['data']['key'])) except error.URLError as e: log.warning('on_start messages not sent to server: %s', str(e)) with open(BACKUP_FILE, 'wb') as fp: log.info('Save %d unsent messages to %s', len(msg_list), BACKUP_FILE) pickle.dump(msg_list, fp) os.fsync(fp) if len(msg_list) == 0: print("Server submission successful") except KeyboardInterrupt: print("Quitting ok.")
def start_firebase(self, messages): access_token = auth.authenticate(False) email = auth.get_student_email(access_token) identifier = auth.get_identifier(token=access_token, email=email) firebase = pyrebase.initialize_app(self.FIREBASE_CONFIG) self.fire_auth = firebase.auth() self.fire_db = firebase.database() self.user_email = email self.hostname = platform.node() data = { 'access_token': access_token, 'email': email, 'identifier': identifier, 'assignment': self.assignment.endpoint, 'file_contents': messages.get('file_contents'), 'analytics': messages.get('analytics'), } # Check for existing sessions first - TBD Future # existing_sessions = self.send_messages(data, endpoint='/collab/list') # response = self.prompt_for_existing_session(existing_sessions.get('sessions')) # if response: # data['desired_session'] = response # Send data to collaborate server response_data = self.send_messages(data, self.LONG_TIMEOUT) if 'error' in response_data or 'session' not in response_data: print("There was an error while starting the session: {} Try again later" .format(response_data.get('error'))) log.warning("Error: {}".format(response_data.get('error'))) return self.session_id = response_data['session'] self.short_url = response_data['short_url'] self.login_user = response_data.get('login_user') # Login as the firebase user email, password = response_data.get('login_user'), response_data.get('password') try: self.fire_user = self.fire_auth.sign_in_with_email_and_password(email, password) self.fire_uid = self.fire_user['localId'] except (ValueError, KeyError) as e: log.warning("Could not login", exc_info=True) print("Could not login to the collaboration server.") return self.stream = (self.get_firebase() .child('actions').stream(self.stream_listener, self.fire_user['idToken'])) self.presence = (self.get_firebase() .child('clients').push({'computer': platform.node(), 'uid': self.fire_uid, 'owner': self.user_email, 'email': self.user_email}, self.fire_user['idToken'])) # Parse response_url if response_data: open_url = response_data['url'] if 'access_token' not in open_url: open_url = open_url + "?access_token={}".format(access_token) could_open = webbrowser.open_new(open_url) if not could_open: print("Could not open browser. Go to {}".format(open_url)) else: log.error("There was an error with the server. Please try again later!") return print("Tell your group members or course staff to go to {}" .format(self.short_url)) while True: data = input("[{}] Type exit to disconnect: ".format(self.short_url)) if data.strip().lower() == 'exit': raise ValueError('Done with session')
def main(): """Run all relevant aspects of ok.py.""" args = parse_input() log.setLevel(logging.DEBUG if args.debug else logging.ERROR) log.debug(args) if args.version: print("okpy=={}".format(client.__version__)) exit(0) # Instantiating assignment try: assign = assignment.load_config(args.config, args) except ex.LoadingException as e: log.warning('Assignment could not instantiate', exc_info=True) print('Error: ' + str(e).strip()) exit(1) # Load backup files msg_list = [] try: with open(BACKUP_FILE, 'rb') as fp: msg_list = pickle.load(fp) log.info('Loaded %d backed up messages from %s', len(msg_list), BACKUP_FILE) except (IOError, EOFError) as e: log.info('Error reading from ' + BACKUP_FILE \ + ', assume nothing backed up') except KeyboardInterrupt: log.warning('Backup messages were not loaded due to KeyboardInterrupt') try: # Load tests and protocols assign.load() if args.tests: print('Available tests:') for name in assign.test_map: print(' ' + name) exit(0) # Run protocol.on_start start_messages = dict() for name, proto in assign.protocol_map.items(): log.info('Execute {}.on_start()'.format(name)) start_messages[name] = proto.on_start() # TODO(albert): doesn't AnalyticsProtocol store the timestamp? start_messages['timestamp'] = str(datetime.now()) msg_list.append(start_messages) # Run protocol.on_interact interact_msg = {} for name, proto in assign.protocol_map.items(): log.info('Execute {}.on_interact()'.format(name)) interact_msg[name] = proto.on_interact() # TODO(albert): doesn't AnalyticsProtocol store the timestamp? interact_msg['timestamp'] = str(datetime.now()) msg_list.append(interact_msg) except ex.LoadingException as e: log.warning('Assignment could not load', exc_info=True) print('Error loading assignment: ' + str(e)) except ex.OkException as e: log.warning('General OK exception occurred', exc_info=True) print('Error: ' + str(e)) except KeyboardInterrupt: log.info('Quitting protocols') assign.dump_tests() else: assign.dump_tests() if args.local: return # Send request to server try: # TODO(denero) Print server responses. # Check if ssl is available if not args.insecure: try: import ssl except: log.warning('Error importing ssl', stack_info=True) sys.exit("SSL Bindings are not installed. You can install python3 SSL bindings or \nrun ok locally with python3 ok --local") try: access_token = auth.authenticate(args.authenticate) log.info('Authenticated with access token %s', access_token) print("Backing up your work...") response = network.dump_to_server(access_token, msg_list, assign.endpoint, args.server, args.insecure, client.__version__, log, send_all=args.submit or args.backup) if isinstance(response, dict): print("Backup successful for user: {0}".format(response['data']['email'])) if args.submit or args.backup: print("URL: https://ok-server.appspot.com/#/{0}/submission/{1}".format(response['data']['course'], response['data']['key'])) if args.backup: print('NOTE: this is only a backup. ' 'To submit your assignment, run ok with --submit.') else: print('Unable to complete backup.') log.warning('network.dump_to_server returned {}'.format(response)) except error.URLError as e: log.warning('on_start messages not sent to server: %s', str(e)) with open(BACKUP_FILE, 'wb') as fp: log.info('Save %d unsent messages to %s', len(msg_list), BACKUP_FILE) pickle.dump(msg_list, fp) os.fsync(fp) except KeyboardInterrupt: print("Quitting ok.")