예제 #1
0
    def test_runtime_error_inputs(self):
        student_code = dedent('''
                    def x():
                        value = input("Gimme a number")
                        return 7 % value
                    x
                ''')
        student = Sandbox()
        set_source(student_code)
        student.run()
        result = student.call("x", inputs=["0"])
        print([[c.kind, c.inputs] for c in student._context])

        self.assertEqual(
            """A TypeError occurred:

    Unsupported operand type(s) for %: 'int' and 'str'

I ran the code:
    x()

And I entered as input:
    0

The traceback was:
Line 4 of file answer.py in x
        return 7 % value


Type errors occur when you use an operator or function on the wrong type of value. For example, using `+` to add to a list (instead of `.append`), or dividing a string by a number.

Suggestion: To fix a type error, you should trace through your code. Make sure each expression has the type you expect it to have.
""".strip(), student.feedback.message)
예제 #2
0
    def test_error_context(self):
        student_code = dedent('''
                    def get_input():
                        return int(input("Gimme the number"))
                ''')
        set_source(student_code, "student.py")
        student = Sandbox()
        student.run()
        result = student.call("get_input", inputs="Banana")
        print("--", [c.inputs for c in student._context])
        self.assertEqual(3, student.feedback.location.line)
        self.assertEqual(
            dedent("""A ValueError occurred:

    Invalid literal for int() with base 10: 'banana'

I ran the code:
    get_input()

And I entered as input:
    Banana

The traceback was:
Line 3 of file student.py in get_input
        return int(input("Gimme the number"))


A ValueError occurs when you pass the wrong type of value to a function. For example, you try to convert a string without numbers to an integer (like `int('Five')`).

Suggestion: Read the error message to see which function had the issue. Check what type the function expects. Then trace your code to make sure you pass in that type."""
                   ).strip(), student.feedback.message)
예제 #3
0
    def test_improved_exceptions(self):
        TEST_FILENAME = here + '_sandbox_test_student.py'
        with open(TEST_FILENAME) as student_file:
            student_code = student_file.read()
        student = Sandbox()
        student.run(student_code, filename=TEST_FILENAME)
        self.assertIsNotNone(student.exception)
        self.assertIsInstance(student.exception, TypeError)
        self.assertEqual(1, student.feedback.location.line)
        self.assertEqual(
            dedent("""A TypeError occurred:

    Unsupported operand type(s) for +: 'int' and 'str'

I ran the file _sandbox_test_student.py.

The traceback was:
Line 1 of file _sandbox_test_student.py
    1+'0'


Type errors occur when you use an operator or function on the wrong type of value. For example, using `+` to add to a list (instead of `.append`), or dividing a string by a number.

Suggestion: To fix a type error, you should trace through your code. Make sure each expression has the type you expect it to have.
""".format(filename=TEST_FILENAME)).strip(), student.feedback.message)
예제 #4
0
 def test_oo(self):
     # Load the "bank.py" code
     student_code = dedent('''
         class Bank:
             def __init__(self, balance):
                 self.balance = balance
             def save(self, amount):
                 self.balance += amount
                 return self.balance > 0
             def take(self, amount):
                 self.balance -= amount
                 return self.balance > 0''')
     student = Sandbox()
     student.run(student_code, filename='bank.py')
     # Check that we created the class
     self.assertIn('Bank', student.data)
     # Now let's try making an instance
     student.call('Bank', 50, target='bank')
     self.assertIsInstance(student.data['bank'], student.data['Bank'])
     # Can we save money?
     student.call('bank.save', 32)
     self.assertTrue(student.result)
     # What about extracting money?
     student.data['bank'].balance += 100
     student.call('bank.take', 100)
     self.assertTrue(student.result)
예제 #5
0
 def test_normal_run(self):
     student = Sandbox()
     student.run('a=0\nprint(a)', filename='student.py')
     self.assertIn('a', student.data)
     self.assertEqual(student.data['a'], 0)
     self.assertEqual(len(student.output), 1)
     self.assertIn('0', student.output[0])
예제 #6
0
 def test_improved_exceptions(self):
     student_code = '0+"1"'
     student = Sandbox()
     student.run(student_code, _as_filename='student.py')
     self.assertIsNotNone(student.exception)
     self.assertIsInstance(student.exception, TypeError)
     self.assertEqual(student.exception_position, {'line': 1})
예제 #7
0
 def test_sandboxing_open(self):
     student_code = dedent('''
         print(open("test_sandbox.py").read())
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception),
                      "The filename you passed to 'open' is restricted.")
예제 #8
0
 def test_weird_module_behavior(self):
     student_code = dedent('''
                 import pprint
                 pprint.pprint(5)
             ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertIsNone(student.exception)
예제 #9
0
 def test_sandboxing_pedal(self):
     student_code = dedent('''
         from pedal.report import MAIN_REPORT
         print(MAIN_REPORT)
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception), "You cannot import pedal!")
예제 #10
0
 def test_sandboxing_devious_open1(self):
     student_code = dedent('''
         __builtins__['globals']()['open']("test_sandbox.py")
         # Fine to import anything else
         
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception),
                      "You are not allowed to call 'globals'.")
예제 #11
0
 def test_coverage(self):
     test_filename = here + '_sandbox_test_coverage.py'
     with open(test_filename) as student_file:
         student_code = student_file.read()
     contextualize_report(student_code)
     student = Sandbox()
     student.tracer_style = 'coverage'
     student.run(student_code, filename=test_filename)
     self.assertIsNone(student.exception)
     self.assertEqual(student.trace.pc_covered, 80.0)
     self.assertEqual(student.trace.lines, {1, 2, 4, 7, 10, 11, 12, 13})
예제 #12
0
 def test_matplotlib(self):
     student_code = dedent('''
         import matplotlib.pyplot as plt
         plt.plot([1,2,3])
         plt.title("My line plot")
         plt.show()
     ''')
     student = Sandbox()
     student.run(student_code, _as_filename='student.py')
     self.assertIn('matplotlib.pyplot', student.modules)
     plt = student.modules['matplotlib.pyplot']
     self.assertEqual(len(plt.plots), 1)
예제 #13
0
 def test_mock_turtle(self):
     student_code = dedent('''
         import turtle
         turtle.forward(100)
         turtle.mainloop()
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertIsNone(student.exception)
     self.assertEqual(student.modules.turtles.calls[0][0], 'forward')
     self.assertEqual(student.modules.turtles.calls[0][1][0], 100)
예제 #14
0
 def test_calls(self):
     student_code = dedent('''
         def x(n):
             if n > 0:
                 return x(n-1)
             return 0
         x(5)
     ''')
     student = Sandbox()
     student.tracer_style = 'calls'
     student.run(student_code, filename='student.py')
     self.assertEqual(len(student.trace.calls['x']), 6)
예제 #15
0
 def test_coverage(self):
     test_filename = here + '_sandbox_test_coverage.py'
     with open(test_filename) as student_file:
         student_code = student_file.read()
     contextualize_report(student_code)
     student = Sandbox()
     student.tracer_style = 'native'
     student.run(student_code, filename=test_filename)
     self.assertIsNone(student.exception)
     #self.assertEqual(round(student.trace.pc_covered), 85)
     self.assertEqual(student.trace.lines,
                      [1, 2, 3, 4, 6, 9, 12, 16, 14, 15, 17])
예제 #16
0
 def test_sandboxing_sys_modules(self):
     clear_report()
     student_code = dedent('''
         import sys
         # Might try to bypass us
         del sys.modules['pedal']
         from pedal.report import MAIN_REPORT
         print(MAIN_REPORT)
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception), "You cannot import pedal!")
예제 #17
0
 def test_get_by_types(self):
     student_code = dedent('''
         my_int = 0
         my_other_int = 5
         my_str = "Hello there!"
         response_str = "General Kenobi!"
         a_list = [1,2,3]
         another_list = [4,5,6]
     ''')
     student = Sandbox()
     student.run(student_code, filename='student.py')
     # ints
     ints = student.get_names_by_type(int)
     self.assertEqual(len(ints), 2)
     self.assertIn('my_int', ints)
     self.assertIn('my_other_int', ints)
     # lists
     lists = student.get_names_by_type(list)
     self.assertEqual(len(lists), 2)
     self.assertIn('a_list', lists)
     self.assertIn('another_list', lists)
     # strs
     strs = student.get_values_by_type(str)
     self.assertEqual(len(strs), 2)
     self.assertIn('Hello there!', strs)
     self.assertIn('General Kenobi!', strs)
예제 #18
0
 def test_coverage_native(self):
     test_filename = here + '_sandbox_test_coverage.py'
     with open(test_filename) as student_file:
         student_code = student_file.read()
     contextualize_report(student_code)
     student = Sandbox()
     student.tracer_style = 'native'
     student.run(student_code, filename=test_filename)
     self.assertIsNone(student.exception)
     self.assertEqual(student.trace.lines,
                      [1, 2, 3, 4, 6, 9, 12, 16, 14, 15, 17])
     self.assertEqual(student.trace.calls, {
         'z': [{
             'args': (0, ),
             'banana': 2,
             'kwargs': {
                 'apple': 8
             },
             'p': 3
         }]
     })
예제 #19
0
 def test_call(self):
     student_code = "def average(a,b):\n return (a+b)/2"
     student = Sandbox()
     student.run(student_code, filename='student.py')
     student.call('average', 10, 12)
예제 #20
0
 def test_sandboxing_open(self):
     student_code = dedent('''
         print(open("test_sandbox.py").read())
     ''')
     set_source(student_code)
     student = Sandbox()
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception),
                      "The filename you passed to 'open' is restricted.")
     # Then can we turn it back on?
     student.allow_function('open')
     student.run(student_code, filename='student.py')
     self.assertIsNone(student.exception)
     # And off again
     student.block_function('open')
     student.run(student_code, filename='student.py')
     self.assertEqual(str(student.exception),
                      "You are not allowed to call 'open'.")
예제 #21
0
 def test_input(self):
     student = Sandbox()
     student.run('b = input("Give me something:")\nprint(b)',
                 inputs=['Hello World!'])
     self.assertIn('b', student.data)
     self.assertEqual(student.data['b'], 'Hello World!')
예제 #22
0
    def test_unittest(self):
        student_code = dedent('''
            x = 0
        ''')
        student = Sandbox()
        student.run(student_code)
        student.call('x')
        self.assertIsNotNone(student.exception)

        student_code = dedent('''
        class Fruit:
            def __init__(self, name, weight=0):
                self.name = name
                self.weight = weight
        def do_math(a, b):
            return a + b - 5
        def weigh_fruits(fruits):
            return sum(fruit.weight for fruit in fruits)    
        ''')
        student.report.contextualize(Submission(main_code=student_code))
        student = Sandbox()
        student.run()
        result = student.call('do_math', 15, 20)
        self.assertEqual(result, 30)
        self.assertEqual(['do_math(15, 20)'],
                         [context.code for context in student.get_context()])
        banana = student.call('Fruit', "Banana")
        self.assertIsInstance(banana, student.data['Fruit'])
        self.assertEqual(["Fruit('Banana')"],
                         [context.code for context in student.get_context()])
        student.start_grouping_context()
        student.run()
        orange = student.call("Fruit", "Orange", 30, target="orange")
        self.assertIsInstance(orange, student.data['Fruit'])
        student.call("Fruit", "Pineapple", 60, target="pineapple")
        student.run("fruits = [orange, pineapple]")
        total_weight = student.call('weigh_fruits', args_locals=["fruits"])
        self.assertEqual(total_weight, 90)
        self.assertEqual([
            student_code, "orange = Fruit('Orange', 30)",
            "pineapple = Fruit('Pineapple', 60)",
            "fruits = [orange, pineapple]", "weigh_fruits(fruits)"
        ], [context.code for context in student.get_context()])
예제 #23
0
import sys
from pprint import pprint


from pedal.sandbox import Sandbox

student = Sandbox()
student.run("""
def add_together(a, b):
    return -7
print(add_together)
""", as_filename='student.py')
#pprint(student.data)
print(student.data)
print(student.output)


from pedal.assertions import assertEqual, phase

#assertEqual(student.data['a'], 2)

result = student.call("add_together", 2, 2)
#as_int = str(result)
#print("Result was:", as_int)
assertEqual(result, 4)

@phase('input_tryit')
def try_it():
    print("Executed")

from pedal.resolvers import simple