def perform_oauth(code_fn, *args, **kwargs): try: access_token, expires_in, refresh_token = code_fn(*args, **kwargs) except UnicodeDecodeError as e: with format.block('-'): print("Authentication error\n:{}".format(HOSTNAME_ERROR_MESSAGE)) except OAuthException as e: with format.block('-'): print("Authentication error: {}".format(e.error.replace('_', ' '))) if e.error_description: print(e.error_description) else: update_storage(access_token, expires_in, refresh_token) return access_token
def prompt_with_prob(self, orig_response=None, prob=None): """Ask for rationale with a specific level of probability. """ # Disable opt-out. # if self.assignment.cmd_args.no_experiments: # log.info("Skipping prompt due to --no-experiments") # return "Skipped due to --no-experiments" if self.load_error: return 'Failed to read guidance config file' if hasattr(self.assignment, 'is_test'): log.info("Skipping prompt due to test mode") return "Test response" if prob is None: prob = self.prompt_probability if random.random() > prob: log.info("Did not prompt for rationale: Insufficient Probability") return "Did not prompt for rationale" with format.block(style="-"): rationale = prompt.explanation_msg( EXPLANTION_PROMPT, short_msg=CONFIRM_BLANK_EXPLANATION) if prob is None: # Reduce future prompt likelihood self.prompt_probability = 0 if orig_response: print('Thanks! Your original response was: {}'.format( '\n'.join(orig_response))) return rationale
def perform_oauth(code_fn, *args, **kwargs): try: access_token, expires_in, refresh_token = code_fn(*args, **kwargs) except OAuthException as e: with format.block('-'): print("Authentication error: {}".format(e.error.replace('_', ' '))) if e.error_description: print(e.error_description) return None update_storage(access_token, expires_in, refresh_token) return access_token
def run(self, messages): """Determine if a student is elgible to recieve a hint. Based on their state, poses reflection questions. After more attempts, ask if students would like hints. If so, query the server. """ if self.args.local: return # Only run hinting protocol on supported assignments. if self.assignment.endpoint not in self.SUPPORTED_ASSIGNMENTS: message = "{0} does not support hinting".format(self.assignment.endpoint) log.info(message) if self.args.hint: print(message) return if 'analytics' not in messages: log.info('Analytics Protocol is required for hint generation') return if 'file_contents' not in messages: log.info('File Contents needed to generate hints') return if self.args.no_experiments: messages['hinting'] = {'disabled': 'user'} return messages['hinting'] = {} history = messages['analytics'].get('history', {}) questions = history.get('questions', []) current_q = history.get('question', {}) messages['hinting']['flagged'] = self.args.hint for question in current_q: if question not in questions: continue stats = questions[question] is_solved = stats['solved'] == True messages['hinting'][question] = {'prompts': {}, 'reflection': {}} hint_info = messages['hinting'][question] # Determine a users elgibility for a prompt # If the user just solved this question, provide a reflection prompt if is_solved: hint_info['elgible'] = False hint_info['disabled'] = 'solved' if self.args.hint: print("This question has already been solved.") continue elif stats['attempts'] < self.SMALL_EFFORT: log.info("Question %s is not elgible: Attempts: %s, Solved: %s", question, stats['attempts'], is_solved) hint_info['elgible'] = False if self.args.hint: hint_info['disabled'] = 'attempt-count' print("You need to make a few more attempts before the hint system is enabled") continue else: # Only prompt every WAIT_ATTEMPTS attempts to avoid annoying user if stats['attempts'] % self.WAIT_ATTEMPTS != 0: hint_info['disabled'] = 'timer' hint_info['elgible'] = False log.info('Waiting for %d more attempts before prompting', stats['attempts'] % self.WAIT_ATTEMPTS) else: hint_info['elgible'] = not is_solved if not self.args.hint: if hint_info['elgible']: with format.block("-"): print("To get hints, try using python3 ok --hint -q {}".format(question)) hint_info['suggested'] = True continue hint_info['accept'] = True with format.block("-"): print(("Thinking of a hint for {}".format(question) + "... (This could take up to 30 seconds)")) pre_hint = random.choice(PRE_HINT_MESSAGES) print("In the meantime, consider: \n{}".format(pre_hint)) hint_info['pre-prompt'] = pre_hint log.info('Prompting for hint on %s', question) try: response = self.query_server(messages, question) except (requests.exceptions.RequestException, requests.exceptions.BaseHTTPError): log.debug("Network error while fetching hint", exc_info=True) hint_info['fetch_error'] = True print("\r\nNetwork Error while generating hint. Try again later") response = None continue if response: hint_info['response'] = response hint = response.get('message') pre_prompt = response.get('pre-prompt') post_prompt = response.get('post-prompt') system_error = response.get('system-error') log.info("Hint server response: {}".format(response)) if not hint: if system_error: print("{}".format(system_error)) else: print("Sorry. No hints found for the current code. Try again making after some changes") continue # Provide padding for the the hint print("\n{}".format(hint.rstrip())) if post_prompt: results['prompts'][query] = prompt.explanation_msg(post_prompt)
def run(self, messages, env=None): """Run gradeable tests and print results and return analytics. """ if not self.args.trace: return tests = self.assignment.specified_tests messages['tracing'] = { 'begin': get_time(), } if not self.args.question: with format.block('*'): print("Could not trace: Please specify a question to trace.") print("Example: python3 ok --trace -q <name>") return test = tests[0] data = test.get_code() if not data: with format.block('*'): print("This test is not traceable.") return if isinstance(test, doctest_models.Doctest): # Directly handle case (for doctests) question = self.args.question[0] if question not in data: with format.block('*'): eligible_questions = ','.join( [str(i) for i in data.keys()]) print("The following doctests can be traced: {}".format( eligible_questions)) usage_base = "Usage: python3 ok -q {} --trace" print(usage_base.format(eligible_questions[0])) return suite = [data[question]] elif hasattr(test, 'suites'): # Handle ok_tests if not self.args.suite: eligible_suite_nums = ','.join([str(i) for i in data.keys()]) with format.block('*'): print("Please specify a specific suite to test.") print("The following suites can be traced: {}".format( eligible_suite_nums)) usage_base = "Usage: python3 ok -q {} --suite {} --trace" print( usage_base.format(self.args.question[0], eligible_suite_nums[0])) return suite_idx = int(self.args.suite) if suite_idx not in data: with format.block('*'): print("Suite {} is not traceable.".format(self.args.suite)) return suite = data[suite_idx] # only trace this one suite case_arg = self.args.case if case_arg: case_num = case_arg[0] - 1 if not (case_arg[0] - 1 not in range(len(suite))): with format.block('*'): print("You can specify a specific case to test.") print("Cases: 1-{}".format(len(suite))) usage_base = "Usage: python3 ok -q {} --suite {} --case 1 --trace" print( usage_base.format(self.args.question[0], self.args.suite)) return suite = [suite[case_arg[0] - 1]] else: with format.block('*'): print("This test is not traceable.") return # Setup and teardown are shared among cases within a suite. setup, test_script, _ = suite_to_code(suite) log.info("Starting program trace...") messages['tracing']['start-trace'] = get_time() modules = { k.replace('.py', '').replace('/', '.'): v for k, v in messages['file_contents'].items() } data = generate_trace.run_logger(test_script, setup, modules) or "{}" messages['tracing']['end-trace'] = get_time() messages['tracing']['trace-len'] = len( json.loads(data).get('trace', [])) # includes the code since data is a str data = json.dumps(remove_unused_globals(json.loads(data))) if data and self.args.trace_print: print(data) elif data: messages['tracing']['start-server'] = get_time() # Open Python Tutor Browser Window with this trace server.run_server(data) messages['tracing']['end-server'] = get_time() else: print("There was an internal error while generating the trace.") messages['tracing']['error'] = True