Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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