def get_items( item_type: enums.ItemType = enums.ItemType.Gallery, limit: int = 100, offset: int = None, ): """ Get a list of items Args: item_type: type of item to get limit: limit the amount of items returned offset: offset the results by n items Returns: .. code-block:: guess [ item message object, ... ] """ item_type = enums.ItemType.get(item_type) db_msg, db_model = item_type._msg_and_model() items = database_cmd.GetModelItems().run(db_model, limit=limit, offset=offset) item_list = message.List(db.model_name(db_model), db_msg) [item_list.append(db_msg(i)) for i in items] return item_list
def library_view(item_type: enums.ItemType = enums.ItemType.Gallery, item_id: int = None, related_type: enums.ItemType = None, page: int = 0, limit: int = 100, sort_by: enums.ItemSort = None, sort_desc: bool=False, search_query: str = "", search_options: dict = {}, filter_id: int = None, view_filter: enums.ViewType = enums.ViewType.Library): """ Fetch items from the database. Provides pagination. Args: item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Collection`, :py:attr:`.ItemType.Grouping` page: current page (zero-indexed) sort_by: either a :py:class:`.ItemSort` or a sort index sort_desc: order descending (default is ascending) limit: amount of items per page search_query: filter item by search terms search_options: options to apply when filtering, see :ref:`Settings` for available search options filter_id: current :py:attr:`.ItemType.GalleryFilter` item id view_filter: type of view, set ``None`` to not apply any filter related_type: child item item_id: id of parent item Returns: .. code-block:: guess [ item message object, ... ] .. seealso:: :func:`.get_sort_indexes` """ view_filter, item_type, db_msg, db_model, model_ids, filter_op, join_exp, metatag_name = _view_helper( item_type, search_query, filter_id, view_filter, item_id, related_type, search_options) items = message.List(db_model.__name__.lower(), db_msg) order_exp, group_exp, sort_joins = helpers._sort_helper(sort_by, sort_desc, db_model) if sort_joins: join_exp.extend(sort_joins) # need unique but ordered results, cannot use set so we make use with this join_exp = tuple(OrderedDict([(x, None) for x in join_exp]).keys()) [items.append(db_msg(x)) for x in database_cmd.GetModelItems().run( db_model, model_ids, limit=limit, offset=page * limit, filter=filter_op, join=join_exp, order_by=order_exp, group_by=group_exp)] return items
def advance(self, buffer): """ Advance the loop for this client Params: buffer -- data buffer to be parsed """ try: if constants.server_ready: function_list = message.List("function", message.Function) functions = self.parse(buffer) if functions is None: return if isinstance(functions, enums.ServerCommand): if functions == enums.ServerCommand.RequestAuth: self.handshake() return functions for func, func_args, ctx in functions: log.d("Calling function", func, "with args", func_args) func_msg = message.Function(func.__name__) try: if ctx: func_args['ctx'] = self.context msg = func(**func_args) else: msg = func(**func_args) assert isinstance(msg, message.CoreMessage) or None func_msg.set_data(msg) except exceptions.CoreError as e: func_msg.set_error(message.Error(e.code, e.msg)) function_list.append(func_msg) # bad functions for fname, e in self.errors: function_list.append( message.Function(fname, error=message.Error(e.code, e.msg))) self.errors.clear() self.send(function_list.serialize(session_id=self.session.id)) else: self.on_wait() except exceptions.CoreError as e: log.d("Sending exception to client:", e) self.on_error(e) except BaseException: if not constants.dev: log.exception("An unknown critical error has occurred") self.on_error( exceptions.HappypandaError( "An unknown critical error has occurred") ) # TODO: include traceback else: raise
def get_related_items( item_type: enums.ItemType = enums.ItemType.Gallery, item_id: int = 0, related_type: enums.ItemType = enums.ItemType.Page, limit: int = 100, offset: int = None, ): """ Get item related to given item Args: item_type: parent item item_id: id of parent item related_type: child item limit: limit the amount of items returned offset: offset the results by n items Returns: .. code-block:: guess [ related item message object, ... ] """ if not item_id: raise exceptions.APIError(utils.this_function(), "item_id must be a valid item id") item_type = enums.ItemType.get(item_type) related_type = enums.ItemType.get(related_type) _, parent_model = item_type._msg_and_model() child_msg, child_model = related_type._msg_and_model() col = db.relationship_column(parent_model, child_model) if not col: raise exceptions.APIError( utils.this_function(), "{} has no relationship with {}".format(related_type, item_type)) s = constants.db_session() q = s.query(child_model.id).join(col).filter(parent_model.id == item_id) if offset: q = q.offset(offset) item_ids = q.limit(limit).all() items = database_cmd.GetModelItems().run(child_model, {x[0] for x in item_ids}) item_list = message.List(db.model_name(child_model), child_msg) [item_list.append(child_msg(x)) for x in items] return item_list
def _get_similar(kwargs, similar_items): item_list = message.List(db.model_name(kwargs['db_model']), kwargs['db_msg']) items = [] if similar_items: similar_items = similar_items[:kwargs['limit']] db_items = {} # needed to sort them the way they came in for g in database_cmd.GetModelItems().run(kwargs['db_model'], set(similar_items)): db_items[g.id] = g [items.append(db_items[x]) for x in similar_items if x in db_items] [item_list.append(kwargs['db_msg'](x)) for x in items] return item_list
def get_sort_indexes(item_type: enums.ItemType = None, translate: bool = True, locale: str = None): """ Get a list of available sort item indexes and names Args: item_type: return applicable indexes for a specific item type translate: translate the sort expression name locale: locale to get translations from (will override default locale) Returns: .. code-block:: guess [ { 'index' : int, 'name': str, 'item_type': int value of :py:class:`.ItemType` }, ... ] """ db_sort = database_cmd.GetDatabaseSort() if item_type: item_type = enums.ItemType.get(item_type) items = [item_type] else: items = list(enums.ItemType) sort_indexes = message.List("indexes", dict) for i in items: _, db_model = i._msg_and_model() for idx, name in db_sort.run(db_model, name=True).items(): if translate: try: name = i18n.t("general.sort-idx-{}".format(idx), default=name, locale=helpers._get_locale(locale)) except Exception: pass sort_indexes.append({ 'index': int(idx), 'name': name, 'item_type': i.value }) return sort_indexes
def list_plugins(state: enums.PluginState=None): """ Get a list plugins Args: state: filter list by plugin state Returns: .. code-block:: guess { } """ l = message.List('plugins', message.Plugin) for n in constants.plugin_manager._nodes: l.append(message.Plugin(n)) return l
def library_view(item_type: enums.ItemType = enums.ItemType.Gallery, page: int = 0, limit: int = 100, sort_by: str = "", search_query: str = "", filter_id: int = None, view_filter: enums.ViewType = enums.ViewType.Library, ctx=None): """ Fetch items from the database. Provides pagination. Args: item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Collection`, :py:attr:`.ItemType.Grouping` page: current page (zero-indexed) sort_by: name of column to order by ... limit: amount of items per page search_query: filter item by search terms filter_id: current filter list id view_filter: ... Returns: list of item message objects """ utils.require_context(ctx) view_filter = enums.ViewType.get(view_filter) item_type = enums.ItemType.get(item_type) db_msg, db_model = item_type._msg_and_model( (enums.ItemType.Gallery, enums.ItemType.Collection, enums.ItemType.Grouping)) items = message.List(db_model.__name__.lower(), db_msg) model_ids = search_cmd.ModelFilter().run(db_model, search_query) [ items.append(db_msg(x)) for x in database_cmd.GetModelItemByID().run( db_model, model_ids, limit=limit, offset=page * limit) ] return items
def get_items(item_type: enums.ItemType = enums.ItemType.Gallery, limit: int = 100): """ Get a list of items Args: item_type: type of item to get limit: limit the amount of items returned Returns: list of item message objects """ item_type = enums.ItemType.get(item_type) db_msg, db_model = item_type._msg_and_model() items = database_cmd.GetModelItems().run(db_model, limit=limit) item_list = message.List(db.model_name(db_model), db_msg) [item_list.append(db_msg(i)) for i in items] return item_list
def search_item( item_type: enums.ItemType = enums.ItemType.Gallery, search_query: str = "", search_options: dict = {}, sort_by: enums.ItemSort = None, sort_desc: bool = False, full_search: bool = True, limit: int = 100, offset: int = None, ): """ Search for item Args: item_type: all of :py:attr:`.ItemType` except :py:attr:`.ItemType.Page` and :py:attr:`.ItemType.GalleryFilter` search_query: filter item by search terms search_options: options to apply when filtering, see :ref:`Settings` for available search options sort_by: either a :py:class:`.ItemSort` or a sort index sort_desc: order descending (default is ascending) limit: amount of items offset: offset the results by n items Returns: .. code-block:: guess [ item message object, ... ] .. seealso:: :func:`.get_sort_indexes` """ item_type = enums.ItemType.get(item_type) if search_options: search_option_names = [ x.name for x in search_cmd._get_search_options() ] for n in search_options: if n not in search_option_names: raise exceptions.APIError( utils.this_function(), "Invalid search option name '{}'".format(n)) if item_type in (enums.ItemType.Page, enums.ItemType.GalleryFilter): raise exceptions.APIError(utils.this_function(), "Unsupported itemtype {}".format(item_type)) db_msg, db_model = item_type._msg_and_model() model_ids = set() if full_search: model_ids = search_cmd.ModelFilter().run(db_model, search_query, search_options) items = message.List("items", db_msg) order_exp, group_exp, join_exp = helpers._sort_helper( sort_by, sort_desc, db_model) [ items.append(db_msg(x)) for x in database_cmd.GetModelItems().run(db_model, model_ids, limit=limit, offset=offset, join=join_exp, order_by=order_exp, group_by=group_exp) ] return items
def advance(self, buffer): """ Advance the loop for this client Params: buffer -- data buffer to be parsed """ with db.cleanup_session(): try: if constants.server_ready: try: buffer = gzip.decompress(buffer) except (zlib.error, OSError) as e: raise exceptions.ParsingError(utils.this_function(), str(e)) function_list = message.List("function", message.Function) functions = self.parse(buffer) if functions is None: return if isinstance(functions, enums.ServerCommand): return functions for func, func_args in functions: log.d("Calling function", func, "with args", func_args) func_msg = message.Function(func.__name__) try: msg = func(**func_args) assert isinstance( msg, message.CoreMessage) or msg is None func_msg.set_data(msg) except exceptions.CoreError as e: log.w(f"Error on func '{func.__name__}':", e) func_msg.set_error(message.Error(e.code, e.msg)) function_list.append(func_msg) # bad functions for fname, e in self.errors: function_list.append( message.Function(fname, error=message.Error( e.code, e.msg))) self.errors.clear() self.send( function_list.serialize(session_id=self.session.id)) else: self.on_wait() except exceptions.CoreError as e: log.w("Sending exception to client:", e) self.on_error(e) except Exception as e: if not constants.dev: log.exception("An unhandled critical error has occurred") if isinstance(e, (PermissionError, FileNotFoundError, NotImplementedError)): self.on_error(exceptions.HappypandaError(str(e))) else: self.on_error( exceptions.HappypandaError( f"An unhandled critical error has occurred: {e.__class__.__name__}" )) else: log.exception("An unhandled critical error has occurred") raise