def run_query(self, query):
        try:
            error = None

            code = compile_restricted(query, '<string>', 'exec')

            safe_builtins["_write_"] = self.custom_write
            safe_builtins["__import__"] = self.custom_import
            safe_builtins["_getattr_"] = getattr
            safe_builtins["getattr"] = getattr
            safe_builtins["_setattr_"] = setattr
            safe_builtins["setattr"] = setattr
            safe_builtins["_getitem_"] = self.custom_get_item
            safe_builtins["_getiter_"] = self.custom_get_iter
            safe_builtins["_print_"] = self._custom_print

            restricted_globals = dict(__builtins__=safe_builtins)
            restricted_globals["get_query_result"] = self.get_query_result
            restricted_globals["execute_query"] = self.execute_query
            restricted_globals["add_result_column"] = self.add_result_column
            restricted_globals["add_result_row"] = self.add_result_row
            restricted_globals["disable_print_log"] = self._custom_print.disable
            restricted_globals["enable_print_log"] = self._custom_print.enable

            # Supported data types
            restricted_globals["TYPE_DATETIME"] = TYPE_DATETIME
            restricted_globals["TYPE_BOOLEAN"] = TYPE_BOOLEAN
            restricted_globals["TYPE_INTEGER"] = TYPE_INTEGER
            restricted_globals["TYPE_STRING"] = TYPE_STRING
            restricted_globals["TYPE_DATE"] = TYPE_DATE
            restricted_globals["TYPE_FLOAT"] = TYPE_FLOAT

            restricted_globals["sorted"] = sorted
            restricted_globals["reversed"] = reversed
            restricted_globals["min"] = min
            restricted_globals["max"] = max

            # TODO: Figure out the best way to have a timeout on a script
            #       One option is to use ETA with Celery + timeouts on workers
            #       And replacement of worker process every X requests handled.

            exec(code) in restricted_globals, self._script_locals

            result = self._script_locals['result']
            result['log'] = self._custom_print.lines
            json_data = json.dumps(result)
        except __HOLE__:
            error = "Query cancelled by user."
            json_data = None
        except Exception as e:
            error = str(e)
            json_data = None

        return json_data, error
dataset/ETHPy150Open getredash/redash/redash/query_runner/python.py/Python.run_query