def get_weblab_user(cached=True): """ Get the current user. If ``cached=True`` it will store it and return the same each time. If you need to get always a different one get it with ``cached=False``. In long tasks, for example, it's normal to call it with ``cached=False`` so it gets updated with whatever information comes from other threads. Two shortcuts exist to this function: * :data:`weblab_user`: it is equivalent to ``get_weblab_user(cached=True)`` * :data:`socket_weblab_user`: it is equivalent to ``get_weblab_user(cached=False)`` Given that the function always returns a :class:`CurrentUser` or :class:`ExpiredUser` or :class:`AnonymousUser`, it's safe to do things like:: if not weblab_user.anonymous: print(weblab_user.username) print(weblab_user.username_unique) :param cached: if this method is called twice in the same thread, it will return the same object. """ if cached and hasattr(g, 'weblab_user'): return g.weblab_user # Cached: then use Redis session_id = _current_session_id() if session_id is None: return _set_weblab_user_cache(AnonymousUser()) user = _current_backend().get_user(session_id) # Store it for next requests in the same call return _set_weblab_user_cache(user)
def __call__(self, *args, **kwargs): """Runs the function in the same way, directly, without catching errors""" session_id = None # only used if unique='user' if self._unique: if self._unique == 'global': locked = self._backend.lock_global_unique_task(self._name) if not locked: raise AlreadyRunningError( "This task ({}) has been sent in parallel and it is still running" .format(self._name)) elif self._unique == 'user': session_id = _current_session_id() locked = self._backend.lock_user_unique_task( self._name, session_id) if not locked: raise AlreadyRunningError( "This task ({}) has been sent in parallel by {} and it is still running" .format(self._name, session_id)) try: return self._func(*args, **kwargs) finally: if self._unique: if self._unique == 'global': self._backend.unlock_global_unique_task(self._name) elif self._unique == 'user': self._backend.unlock_user_unique_task( self._name, session_id)
def store_initial_weblab_user_data(): session_id = _current_session_id() if session_id: backend = _current_backend() current_user = backend.get_user(session_id) if current_user.active: g._initial_data = json.dumps(current_user.data)
def make_poll(response): session_id = _current_session_id() if session_id is None: return response _current_backend().poll(session_id) return response
def delay(self, *args, **kwargs): """ Starts the function in a thread or in another process. It returns a WebLabTask object """ session_id = _current_session_id() task_id = self._backend.new_task(session_id, self._name, args, kwargs) return WebLabTask(self._weblab, task_id)
def running_tasks(self): """ Check which tasks are still running and return them. See also :meth:`WebLab.task` for examples. """ session_id = _current_session_id() tasks = [] for task_id in self._backend.get_unfinished_tasks(session_id): tasks.append(WebLabTask(self, task_id)) return tasks
def tasks(self): """ Return all the tasks created in the current session (completed or not) See also :meth:`WebLab.task` for examples. """ session_id = _current_session_id() tasks = [] for task_id in self._backend.get_all_tasks(session_id): tasks.append(WebLabTask(self, task_id)) return tasks
def logout(): """ Notify WebLab-Deusto that the user left the laboratory, so next user can enter. This process is not real time. What it happens is that WebLab-Deusto periodically is requesting whether the user is still alive or not. If you call logout, weblablib will reply the next time that the user left. So it may take some seconds for WebLab-Deusto to realize of that. You can regulate this time with ``WEBLAB_POLL_INTERVAL`` setting (defaults to 5). """ session_id = _current_session_id() if session_id: _current_backend().force_exit(session_id)
def poll_after_request(response): """ Poll after every request """ if hasattr(g, 'poll_requested'): poll_requested = g.poll_requested else: poll_requested = False # Don't poll twice: if requested manually there is another after_this_request if not poll_requested: session_id = _current_session_id() if session_id: self._backend.poll(session_id) return response
def update_weblab_user_data(response): # If a developer does: # # weblab_user.data["foo"] = "bar" # # Nothing is triggered in Redis. For this reason, after each request # we check that the data has changed or not. # session_id = _current_session_id() backend = _current_backend() if session_id: if weblab_user.active: # If there was no data in the beginning # OR there was data in the beginning and now it is different, # only then modify the current session if not hasattr(g, '_initial_data') or g._initial_data != json.dumps( weblab_user.data): backend.update_data(session_id, weblab_user.data) return response
def get_task(self, identifier): """ Given a task of the current user, return the :class:`WebLabTask` object. The identifier can be: 1. A ``task_id`` 2. A function name 3. A function See also :meth:`WebLab.task` for examples. :param identifier: either a ``task_id``, a function name or a function. """ name = identifier func = False if hasattr(identifier, '__code__'): name = identifier.__name__ func = True if hasattr(identifier, '_func') and hasattr(identifier._func, '__code__'): name = identifier._func.__name__ func = True if not func: task_data = self._backend.get_task(name) if task_data: # Don't return tasks of other users if task_data['session_id'] == _current_session_id(): return WebLabTask(self, task_data['task_id']) if has_app_context(): # if no task_data or func is True: tasks = self.get_tasks(name) if tasks: return tasks[0] return None
def weblab_poll_script(logout_on_close=False, callback=None): """ Create a HTML script that calls poll automatically. """ if self.timeout <= 0: return Markup("<!-- timeout is 0 or negative; no script -->") weblab_timeout = int(1000 * self.timeout / 2) session_id = _current_session_id() if not session_id: return Markup("<!-- session_id not found; no script -->") if logout_on_close: logout_code = """ $(window).bind("beforeunload", function() { $.get("%(url)s"); }); """ % dict(url=url_for('weblab_logout_url', session_id=session_id)) else: logout_code = "" if callback: callback_code = "{}();".format(callback) else: callback_code = "" return Markup("""<script> var WEBLAB_TIMEOUT = null; var WEBLAB_RETRIES = 3; if (window.jQuery !== undefined) { var WEBLAB_INTERVAL_FUNCTION = function(){ $.get("%(url)s").done(function(result) { if(!result.success) { clearInterval(WEBLAB_TIMEOUT); %(callback_code)s } else { WEBLAB_RETRIES = 3; } }).fail(function(errorData) { if (WEBLAB_RETRIES > 0 && (errorData.status == 502 || errorData.status == 503)) { WEBLAB_RETRIES -= 1; setTimeout(WEBLAB_INTERVAL_FUNCTION, 1500); // Force a try-again in 1.5 seconds } else { clearInterval(WEBLAB_TIMEOUT); %(callback_code)s } }); } WEBLAB_TIMEOUT = setInterval(WEBLAB_INTERVAL_FUNCTION, %(timeout)s ); %(logout_code)s } else { var msg = "weblablib error: jQuery not loaded BEFORE {{ weblab_poll_script() }}. Can't poll"; if (console && console.error) { console.error(msg); } else if (console && console.log) { console.log(msg); } else { alert(msg); } } </script>""" % dict(timeout=weblab_timeout, url=url_for('weblab_poll_url', session_id=session_id), logout_code=logout_code, callback_code=callback_code))