Example #1
0
    def _execute_with_timeout(self, code, filename, kind):
        """
        Execute the given code, but stop after `self.allowed_time`.
        Args:
            code (str):
            filename (str):
            kind (:py:class:`pedal.sandbox.sandbox_mixins.SandboxContextKind`):

        Returns:
            :py:class:`pedal.sandbox.sandbox.Sandbox`
        """
        try:
            return timeout(self.allowed_time, self._execute, code, filename,
                           kind, False)
        except TimeoutError as timeout_exception:
            self._stop_patches()
            self._capture_exception(timeout_exception, sys.exc_info(), code,
                                    filename)
            return self
Example #2
0
    def run(self,
            code,
            as_filename=None,
            modules=None,
            inputs=None,
            threaded=None,
            report_exceptions=True,
            context=False):
        """
        Execute the given string of code in this sandbox.
        
        Args:
            code (str): The string of code to be executed.
            as_filename (str): The filename to use when executing the code -
                this is cosmetic, technically speaking, it has no relation
                to anything on disk. It will be present in tracebacks.
                Defaults to Source's filename.
            modules (dict[str:Module]): Modules to mock.
            inputs (list[str]): The inputs to give from STDIN, as a list of
                strings. You can also give a function that emulates the
                input function; e.g., consuming a prompt (str) and producing
                strings. This could be used to make a more interactive input
                system.
            context (str): The context to give any exceptions.
                If None, then the recorded context will be used. If a string,
                tracebacks will be shown with the given context. If False,
                no context will be given (the default).
            threaded (bool): whether or not to run this code in a separate
                thread. Defaults to :attribute:`Sandbox.threaded`.
            report_exceptions (bool): Whether or not to capture exceptions.
        """
        # Handle any threading if necessary
        if threaded is None:
            threaded = self.threaded
        if threaded:
            try:
                return timeout(self.allowed_time, self.run, code, as_filename,
                               modules, inputs, False, report_exceptions,
                               context)
            except TimeoutError as timeout_exception:
                self._capture_exception(timeout_exception, sys.exc_info(),
                                        report_exceptions)
                return self
        if as_filename is None:
            as_filename = os.path.basename(self.report['source']['filename'])
        if inputs is None:
            if self.inputs is None:
                inputs = mocked._make_inputs('0', repeat='0')
            else:
                inputs = self.inputs
        if isinstance(inputs, (tuple, list)):
            inputs = mocked._make_inputs(*inputs)
        elif isinstance(inputs, str):
            inputs = mocked._make_inputs(inputs)
        inputs = self._track_inputs(inputs)
        # Override builtins and mock stuff out
        mocked_functions = self.mocked_functions.copy()
        mocked_functions['input'] = inputs
        mocked_functions['raw_input'] = inputs
        mocked_functions['sys'] = sys
        mocked_functions['os'] = os
        mocked._override_builtins(self.data, mocked_functions)

        self.exception = None
        self.exception_position = None
        self.exception_formatted = None

        # Patch in dangerous built-ins
        capture_stdout = io.StringIO()
        self._start_patches(patch('sys.stdout', capture_stdout),
                            patch('time.sleep', return_value=None),
                            patch.dict('sys.modules', self.mocked_modules))
        # Compile and run student code
        try:
            compiled_code = compile(code, as_filename, 'exec')
            with self.trace._as_filename(as_filename, code):
                exec(compiled_code, self.data)
        except Exception as user_exception:
            self._capture_exception(user_exception, sys.exc_info(),
                                    report_exceptions, context)
        finally:
            self._stop_patches()
            self.append_output(capture_stdout.getvalue())
        if context is None:
            self.call_contexts[self.call_id].append(code)
        elif isinstance(context, str):
            self.call_contexts[self.call_id].append(context)
        elif context is not False:
            self.call_contexts[self.call_id] = context
        return self
Example #3
0
    def run(self, code, as_filename=None, modules=None, inputs=None,
            threaded=None, report_exceptions=True, context=False):
        """
        Execute the given string of code in this sandbox.
        
        Args:
            code (str): The string of code to be executed.
            as_filename (str): The filename to use when executing the code -
                this is cosmetic, technically speaking, it has no relation
                to anything on disk. It will be present in tracebacks.
                Defaults to Source's filename.
            modules (dict[str:Module]): Modules to mock.
            inputs (list[str]): The inputs to give from STDIN, as a list of
                strings. You can also give a function that emulates the
                input function; e.g., consuming a prompt (str) and producing
                strings. This could be used to make a more interactive input
                system.
            context (str): The context to give any exceptions.
                If None, then the recorded context will be used. If a string,
                tracebacks will be shown with the given context. If False,
                no context will be given (the default).
            threaded (bool): whether or not to run this code in a separate
                thread. Defaults to :attribute:`Sandbox.threaded`.
            report_exceptions (bool): Whether or not to capture exceptions.
        """
        # Handle any threading if necessary
        if threaded is None:
            threaded = self.threaded
        if threaded:
            try:
                return timeout(self.allowed_time, self.run, code, as_filename,
                               modules, inputs, False,
                               report_exceptions, context)
            except TimeoutError as timeout_exception:
                self._capture_exception(timeout_exception, sys.exc_info(),
                                        report_exceptions)
                return self
        if as_filename is None:
            as_filename = os.path.basename(self.report['source']['filename'])
        if inputs is None:
            if self.inputs is None:
                inputs = mocked._make_inputs('0', repeat='0')
            else:
                inputs = self.inputs
        if isinstance(inputs, (tuple, list)):
            inputs = mocked._make_inputs(*inputs)
        elif isinstance(inputs, str):
            inputs = mocked._make_inputs(inputs)
        inputs = self._track_inputs(inputs)
        # Override builtins and mock stuff out
        mocked_functions = self.mocked_functions.copy()
        mocked_functions['input'] = inputs
        mocked_functions['raw_input'] = inputs
        mocked_functions['sys'] = sys
        mocked_functions['os'] = os
        mocked._override_builtins(self.data, mocked_functions)
        

        self.exception = None
        self.exception_position = None
        self.exception_formatted = None

        # Patch in dangerous built-ins
        capture_stdout = io.StringIO()
        self._start_patches(
            patch('sys.stdout', capture_stdout),
            patch('time.sleep', return_value=None),
            patch.dict('sys.modules', self.mocked_modules)
        )
        # Compile and run student code
        try:
            compiled_code = compile(code, as_filename, 'exec')
            with self.trace._as_filename(as_filename, code):
                exec(compiled_code, self.data)
        except Exception as user_exception:
            self._capture_exception(user_exception, sys.exc_info(),
                                    report_exceptions, context)
        finally:
            self._stop_patches()
            self.append_output(capture_stdout.getvalue())
        if context is None:
            self.call_contexts[self.call_id].append(code)
        elif isinstance(context, str):
            self.call_contexts[self.call_id].append(context)
        elif context is not False:
            self.call_contexts[self.call_id] = context
        return self