Ejemplo n.º 1
0
    def check_re(self, text):
        """Run re.match in sandbox, because re.match('(x+x+)+y', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        is to resource consuming.

        May be should use https://code.google.com/p/re2/ here.
        """
        if self.match_substring:
            pattern = "{0}({1}){0}".format(r"(.|\n)*", self.pattern)
        else:
            pattern = self.pattern
        global_dict = {'matched': False,
                       'pattern': pattern,
                       'text': text}
        code = textwrap.dedent("""
                import re
                match = re.match(pattern, text, {flags})
                matched = match.group() == text if match else False
                """).format(flags='' if self.case_sensitive else 'flags=re.I')
        try:
            safe_exec.safe_exec(code, global_dict)
        except safe_exec.SafeExecException:
            score = False
        else:
            score = bool(global_dict['matched'])
        return score
Ejemplo n.º 2
0
def main():
    gobble = []
    for i in xrange(int(1e7)):
        print i
        globs = {}
        safe_exec.safe_exec("a = 17", globs)
        assert globs["a"] == 17

        gobble.append("x" * GOBBLE_CHUNK)
Ejemplo n.º 3
0
def is_math_quiz_enabled():
    code = textwrap.dedent("""
        import sympy
        """)
    try:
        safe_exec.safe_exec(code, {})
    except safe_exec.SafeExecException:
        return False
    return True
Ejemplo n.º 4
0
def run_python(request):
    """A page to allow testing the Python sandbox on a production server."""
    if not request.user.is_staff:
        raise Http404
    c = {}
    c['code'] = ''
    c['results'] = None
    if request.method == 'POST':
        py_code = c['code'] = request.POST.get('code')
        g = {}
        try:
            safe_exec(py_code, g)
        except Exception as e:
            c['results'] = traceback.format_exc()
        else:
            c['results'] = pprint.pformat(g)
    return render_to_response("debug/run_python_form.html", c)
Ejemplo n.º 5
0
def run_python(request):
    """A page to allow testing the Python sandbox on a production server."""
    if not request.user.is_staff:
        raise Http404
    c = {}
    c['code'] = ''
    c['results'] = None
    if request.method == 'POST':
        py_code = c['code'] = request.POST.get('code')
        g = {}
        try:
            safe_exec(py_code, g)
        except Exception as e:
            c['results'] = traceback.format_exc()
        else:
            c['results'] = pprint.pformat(g)
    return render_to_response("debug/run_python_form.html", c)
Ejemplo n.º 6
0
def attempt_safe(dataset, answer_query, verify_query, is_ordered, query):
    """
    Attempt a SqlProblem, using codejail to sandbox the execution.
    """
    results = {
        'answer_query': answer_query,
        'dataset': dataset,
        'verify_query': verify_query,
        'is_ordered': is_ordered,
        'query': query
    }
    code = """
from sql_grader.problem import SqlProblem
submission_result, answer_result, error, comparison = SqlProblem(
    answer_query=answer_query,
    dataset=dataset,
    verify_query=verify_query,
    is_ordered=is_ordered
).attempt(query)

"""
    # example from edx-platform's use of codejail:
    # https://github.com/edx/edx-platform/blob/master/common/lib/capa/capa/capa_problem.py#L887
    # we have to include the path to the entire sql_grader package.
    python_path = [
        os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))
    ]

    try:
        safe_exec(code, results, python_path=python_path, slug='sql_grader')
    except SafeExecException:
        log.exception(query)
        # how should resource limits be communicated to the user?
        results = {
            'submission_result': None,
            'answer_result': None,
            'error': _("We could not execute your query; please try again."),
            'comparison': None,
        }
    return (
        results['submission_result'],
        results['answer_result'],
        results['error'],
        results['comparison'],
    )
Ejemplo n.º 7
0
 def check_re(self, text):
     if self.match_substring:
         pattern = "{0}({1}){0}".format(r"(.|\n)*", self.pattern)
     else:
         pattern = self.pattern
     global_dict = {'matched': False, 'pattern': pattern, 'text': text}
     code = textwrap.dedent("""
             import re
             match = re.match(pattern, text, {flags})
             matched = match.group() == text if match else False
             """).format(flags='' if self.case_sensitive else 'flags=re.I')
     try:
         safe_exec.safe_exec(code, global_dict)
     except safe_exec.SafeExecException:
         score = False
     else:
         score = bool(global_dict['matched'])
     return score
Ejemplo n.º 8
0
    def check(self, reply, clue):
        global_dict = {'matched': False,
                       'hint': '',
                       'answer': self.answer,
                       'reply': reply}
        code = textwrap.dedent("""
        from sympy.parsing.sympy_parser import parse_expr
        from sympy.utilities.randtest import test_numerically
        from sympy import latex

        def compare(reply, answer):
            if (reply - answer).simplify() == 0:
                return True

            n_tries = 3
            return all(test_numerically(reply, answer) for _ in range(n_tries))

        def to_expr(s):
            return parse_expr(s.replace("^", "**"))


        answer = to_expr(answer)
        try:
            reply = to_expr(reply)
        except Exception:
            matched = False
            hint = 'failed to parse expression'
        else:
            hint = "understood answer as ${}$".format(latex(reply))
            if not answer.free_symbols >= reply.free_symbols:
                matched = False
            else:
                matched = compare(reply, answer)
        """)
        try:
            safe_exec.safe_exec(code, global_dict)
        except safe_exec.SafeExecException:
            return False

        score = bool(global_dict['matched'])
        hint = ''
        if score == 0:
            hint = str(global_dict['hint'])
        return score, hint
Ejemplo n.º 9
0
 def check_re(self, text):
     if self.match_substring:
         pattern = "{0}({1}){0}".format(r"(.|\n)*", self.pattern)
     else:
         pattern = self.pattern
     global_dict = {'matched': False,
                    'pattern': pattern,
                    'text': text}
     code = textwrap.dedent("""
             import re
             match = re.match(pattern, text, {flags})
             matched = match.group() == text if match else False
             """).format(flags='' if self.case_sensitive else 'flags=re.I')
     try:
         safe_exec.safe_exec(code, global_dict)
     except safe_exec.SafeExecException:
         score = False
     else:
         score = bool(global_dict['matched'])
     return score
Ejemplo n.º 10
0
    def async_init(self):
        global_dict = {'answer': self.answer}
        code = textwrap.dedent("""
        from sympy.core.compatibility import exec_
        from sympy.parsing.sympy_parser import parse_expr

        exclude_symbols = ['N']

        def to_expr(s):
            global_dict = {}
            exec_('from sympy import *', global_dict)
            for symbol in exclude_symbols:
                global_dict.pop(symbol)
            return parse_expr(s.replace("^", "**"), global_dict=global_dict)

        answer = to_expr(answer)
        """)
        try:
            safe_exec.safe_exec(code, global_dict, limits=self.LIMITS)
        except safe_exec.SafeExecException:
            raise FormatError('Failed to parse correct answer.')
Ejemplo n.º 11
0
    def generate(self):
        self._random_context()
        self._random_variables()
        dataset = {'task': self.task}

        global_dict = {
            'solve': self.solve,
            'variables': self.variables,
            'clue': ''
        }
        code = textwrap.dedent("""
        from sympy import sympify
        import re

        str_exp = ' ' + str(solve) + ' '
        for variable in variables:
            replace_value = variable['value']
            if float(replace_value) < 0:
                replace_value = '({})'.format(replace_value)
            str_exp = re.sub(r'(?P<left>\W)%s(?P<right>\W)' % variable['name'],
                             r'\g<left>%s\g<right>' % replace_value,
                             str_exp)
        expr = sympify(str(str_exp))
        clue = str(expr.evalf())
        """)
        try:
            safe_exec.safe_exec(code, global_dict)
        except safe_exec.SafeExecException:
            return False, 'Cannot generate check function. Perhaps solve expression is wrong.'

        try:
            clue = float(parse_decimal(str(global_dict['clue']), 'dummy'))
        except FormatError:
            raise FormatError(
                "Error in solve expression. Perhaps one or more variable is not declared"
            )

        return dataset, clue
Ejemplo n.º 12
0
    def check_re(self, text):
        """Run re.match in sandbox, because re.match('(x+x+)+y', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        is to resource consuming.

        May be should use https://code.google.com/p/re2/ here.
        """
        if self.match_substring:
            pattern = "{0}({1}){0}".format(r"(.|\n)*", self.pattern)
        else:
            pattern = self.pattern
        global_dict = {'matched': False, 'pattern': pattern, 'text': text}
        code = textwrap.dedent("""
                import re
                match = re.match(pattern, text, {flags})
                matched = match.group() == text if match else False
                """).format(flags='' if self.case_sensitive else 'flags=re.I')
        try:
            safe_exec.safe_exec(code, global_dict)
        except safe_exec.SafeExecException:
            score = False
        else:
            score = bool(global_dict['matched'])
        return score
Ejemplo n.º 13
0
 def safe_exec(self, *args, **kwargs):
     safe_exec.safe_exec(*args, **kwargs)
Ejemplo n.º 14
0
 def safe_exec(self, *args, **kwargs):
     safe_exec.safe_exec(*args, **kwargs)
Ejemplo n.º 15
0
    def check(self, reply, clue):
        global_dict = {'matched': False,
                       'hint': '',
                       'answer': self.answer,
                       'z_re_min': self.z_re_min,
                       'z_re_max': self.z_re_max,
                       'z_im_min': self.z_im_min,
                       'z_im_max': self.z_im_max,
                       'max_error': self.max_error,
                       'integer_only': self.integer_only,
                       'reply': reply}

        # Below we use our own test_numerically function, because the original function
        # sympy.utilities.randtest.test_numerically has the following problems:
        # (1) it uses the relative error for comparison, that does not work well for very large values;
        # (2) it uses random real numbers, that does not work well some formulas.
        # see https://vyahhi.myjetbrains.com/youtrack/issue/EDY-4078 for more details.

        code = textwrap.dedent("""
        from random import randint, uniform

        from sympy import I, Tuple, Symbol, latex
        from sympy.core.compatibility import exec_
        from sympy.parsing.sympy_parser import parse_expr
        from sympy.utilities.randtest import comp

        exclude_symbols = ['N']

        def random_number():
            if integer_only:
                A, B = randint(z_re_min, z_re_max), randint(z_im_min, z_im_max)
            else:
                A, B = uniform(z_re_min, z_re_max), uniform(z_im_min, z_im_max)
            return A + I*B

        def test_numerically(f, g, z=None):
            f, g, z = Tuple(f, g, z)
            z = [z] if isinstance(z, Symbol) else (f.free_symbols | g.free_symbols)
            reps = list(zip(z, [random_number() for zi in z]))
            z1 = f.subs(reps).n()
            z2 = g.subs(reps).n()
            return comp(z1 - z2, 0, max_error)

        def compare(reply, answer):
            if answer.is_Relational:
                if not reply.is_Relational:
                    return False, "The answer must be an inequality"
                return compare_inequalities(reply, answer)
            if reply.is_Relational:
                return False, "The answer must not be an inequality"
            return compare_expressions(reply, answer)

        def compare_expressions(reply, answer):
            if (reply - answer).simplify() == 0:
                return True

            if reply.is_Number and answer.is_Number:
                return bool(abs(reply - answer) <= max_error)

            n_tries = 10
            return all(test_numerically(reply, answer) for _ in range(n_tries))

        def compare_inequalities(reply, answer):
            # Compare two single inequalities
            reversed_rel_op = {'<': '>', '<=': '>=', '>': '<', '>=': '<='}
            if reply.rel_op == answer.rel_op:
                return compare_expressions(reply.lhs - reply.rhs, answer.lhs - answer.rhs)
            elif reversed_rel_op.get(reply.rel_op) == answer.rel_op:
                return compare_expressions(reply.rhs - reply.lhs, answer.lhs - answer.rhs)
            return False

        def to_expr(s):
            global_dict = {}
            exec_('from sympy import *', global_dict)
            for symbol in exclude_symbols:
                global_dict.pop(symbol)
            return parse_expr(s.replace("^", "**"), global_dict=global_dict)


        answer = to_expr(answer)
        try:
            reply = to_expr(reply)
        except Exception:
            matched = False
            hint = 'Failed to parse expression.'
        else:
            hint = "Understood answer as ${}$.".format(latex(reply))
            if not answer.free_symbols >= reply.free_symbols:
                matched = False
            else:
                try:
                    matched = compare(reply, answer)
                except Exception:
                    matched = False
                    hint += '\\nCannot check answer. Perhaps syntax is wrong.'
                else:
                    if isinstance(matched, tuple):
                        matched, feedback = matched
                        hint += '\\n' + feedback
        """)
        try:
            safe_exec.safe_exec(code, global_dict, limits=self.LIMITS)
        except safe_exec.SafeExecException:
            return False, ('Timed out while checking the answer. '
                           'Perhaps it is wrong or too complex.')

        score = bool(global_dict['matched'])
        hint = ''
        if score == 0:
            hint = str(global_dict['hint'])
            notation_feedback = []
            for symbol, correct_symbol in SYMPY_NOTATION_MAP.items():
                if re.search(r'\b{symbol}\b'.format(symbol=symbol), reply):
                    notation_feedback.append('You wrote "{}", maybe you meant to write "{}".'
                                             .format(symbol, correct_symbol))
            if hint and notation_feedback:
                hint += '\n'
            hint += '\n'.join(notation_feedback)
        return score, hint