def main(self, model: db.Base, term: str, match_options: dict = {}) -> typing.Set[int]: self.model = model model_name = db.model_name(self.model) self.term = term with self.models.call() as plg: for p in plg.all(default=True): self._supported_models.update(p) if self.model not in self._supported_models: raise exceptions.CommandError( utils.this_command(self), "Model '{}' is not supported".format(model)) options = get_search_options(match_options) log.d("Match options", options) related_models = db.related_classes(model) sess = constants.db_session() model_count = sess.query(model).count() with self.match_model.call_capture(model_name, model_name, model_name, self.term, options) as plg: for i in plg.all_or_default(): self.matched_ids.update(i) if len(self.matched_ids) == model_count: break has_all = False for m in related_models: if m in self._supported_models: with self.match_model.call_capture(db.model_name(m), model_name, db.model_name(m), self.term, options) as plg: for i in plg.all_or_default(): self.matched_ids.update(i) if len(self.matched_ids) == model_count: has_all = True break if has_all: break self.matched.emit(self.matched_ids) return self.matched_ids
def _namespacetags_orderby(model_name, capture=db.model_name(db.NamespaceTags)): return { ItemSort.NamespaceTagNamespace.value: (db.Namespace.name, db.Tag.name), ItemSort.NamespaceTagTag.value: (db.Tag.name, db.Namespace.name), }
def main(self, model: db.Base, limit: int = 999, filter: str = "", order_by: str = "", offset: int = 0, join: str = "") -> tuple: s = constants.db_session() q = s.query(model) if join: if not isinstance(join, (list, tuple)): join = [join] for j in join: if isinstance(j, str): q = q.join(db.sa_text(j)) else: q = q.join(j) if filter: if isinstance(filter, str): q = q.filter(db.sa_text(filter)) else: q = q.filter(filter) if order_by: q = q.order_by(db.sa_text(order_by)) self.fetched_items = tuple(self._query(q, limit, offset)) self.fetched.emit(db.model_name(model), self.fetched_items) return self.fetched_items
def _match_gallery(parent_model, child_model, term, options, capture=db.model_name(db.Gallery)): get_model = database_cmd.GetModelClass() parent_model = get_model.run(parent_model) child_model = get_model.run(child_model) match_string = PartialModelFilter._match_string_column match_int = PartialModelFilter._match_integer_column term = ParseTerm().run(term) ids = set() s = constants.db_session() if term.namespace: lower_ns = term.namespace.lower() if lower_ns == 'path': ids.update(x[0] for x in s.query(parent_model.id).filter( match_string(db.Gallery.path, term, options)).all()) elif lower_ns in ("rating", "stars"): ids.update(x[0] for x in s.query(parent_model.id).filter( match_int(db.Gallery.rating, term, options)).all()) return ids
def _generate_collection(model, item_id, size, capture=db.model_name(db.Collection)): im_path = "" model = GetModelClass().run(model) page = GetSession().run().query(db.Page.path).join( db.Collection.galleries).join(db.Gallery.pages).filter( db.and_op(db.Collection.id == item_id, db.Page.number == 1)).first() # gallery sorted by insertion: # page = GetSession().run().query( # db.Page.path, db.gallery_collections.c.timestamp.label("timestamp")).join(db.Collection.galleries).join(db.Gallery.pages).filter( # db.and_op( # db.Collection.id == item_id, # db.Page.number == 1)).sort_by("timestamp").first() if page: im_path = page[0] if im_path: im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs) im_path = io_cmd.ImageItem(im_path, im_props).main() return im_path
def _generate_and_add(self, img_hash, old_img_hash, generate, model, item_id, image_size, profile_size): model_name = db.model_name(model) cover = db.Profile() if generate: log.d("Generating new profile", image_size, "for database item", model) with self.generate.call_capture(model_name, model_name, item_id, image_size) as plg: p = plg.first_or_default() if not p: p = "" cover.path = p cover.data = img_hash cover.size = profile_size self.next_progress() if cover.path and generate: log.d("Updating database") self._update_db(cover, item_id, model, old_img_hash) elif not cover.path: cover = None return cover
def _match_tags(parent_model, child_model, term, options, capture=db.model_name(db.Taggable)): get_model = database_cmd.GetModelClass() parent_model = get_model.run(parent_model) child_model = get_model.run(child_model) match_string = PartialModelFilter._match_string_column term = ParseTerm().run(term) ids = set() col_on_parent = db.relationship_column(parent_model, child_model) col_on_child = db.relationship_column(child_model, db.NamespaceTags) col_tag = db.relationship_column(db.NamespaceTags, db.Tag) s = constants.db_session() q = s.query(parent_model.id) if term.namespace: col_ns = db.relationship_column(db.NamespaceTags, db.Namespace) items = q.join(col_on_parent).join(col_on_child).join(col_ns).join( col_tag).filter( db.and_op( match_string(db.Namespace.name, term.namespace, options, whole=True), match_string(db.Tag.name, term.tag, options))).all() else: items = q.join(col_on_parent).join(col_on_child).join( col_tag).filter(match_string(db.Tag.name, term.tag, options)).all() ids.update(x[0] for x in items) return ids
def _aliasname_joins( model_name, capture=tuple(db.model_name(x) for x in (db.Artist, db.Parody))): return { ItemSort.ArtistName.value: (db.Artist.names, ), ItemSort.ParodyName.value: (db.Parody.names, ), }
def _aliasname_names( model_name, capture=tuple(db.model_name(x) for x in (db.Artist, db.Parody))): return { ItemSort.ArtistName.value: "Name", ItemSort.ParodyName.value: "Name", }
def _generate_and_add(self, img_hash, generate, cover_path, model, item_id, image_size): sess = constants.db_session() model_name = db.model_name(model) new = False if cover_path: self.cover = sess.query( db.Profile).filter(db.Profile.data == img_hash).one_or_none() else: self.cover = db.Profile() new = True if generate: with self.generate.call_capture(model_name, model_name, item_id, image_size) as plg: self.cover.path = plg.first() self.cover.data = img_hash self.cover.size = str(tuple(image_size)) if self.cover.path and generate: if new: s = constants.db_session() i = s.query(model).get(item_id) i.profiles.append(self.cover) sess.commit() elif not self.cover.path: self.cover = None return self.cover
def _match_parody(parent_model, child_model, term, options, capture=db.model_name(db.Parody)): get_model = database_cmd.GetModelClass() parent_model = get_model.run(parent_model) child_model = get_model.run(child_model) match_string = PartialModelFilter._match_string_column term = ParseTerm().run(term) ids = set() if term.namespace.lower() == 'parody' or not term.namespace: col_on_parent = db.relationship_column(parent_model, child_model) s = constants.db_session() q = s.query(parent_model.id) if col_on_parent: q = q.join(col_on_parent) ids.update( x[0] for x in q.join( child_model.names).filter( match_string( db.ParodyName.name, term.tag, options)).all()) return ids
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 _match_namemixin(parent_model, child_model, term, options, capture=[ db.model_name(x) for x in _models() if issubclass(x, (db.NameMixin, db.Url)) ]): get_model = database_cmd.GetModelClass() parent_model = get_model.run(parent_model) child_model = get_model.run(child_model) match_string = PartialModelFilter._match_string_column term = ParseTerm().run(term) ids = set() if term.namespace.lower() == child_model.__name__.lower( ) or not term.namespace: col_on_parent = db.relationship_column(parent_model, child_model) s = constants.db_session() q = s.query(parent_model.id) if col_on_parent: q = q.join(col_on_parent) ids.update(x[0] for x in q.filter( match_string(child_model.name, term.tag, options)).all()) return ids
def main(self, model: db.Base, search_filter: str, match_options: dict = {}) -> typing.Set[int]: assert issubclass(model, db.Base) self._model = model model_name = db.model_name(self._model) if search_filter: self.parsesearchfilter = ParseSearch() pieces = self.parsesearchfilter.run(search_filter) options = get_search_options(match_options) include = set() exclude = set() with self.separate.call(pieces) as plg: for p in plg.all(True): if len(p) == 2: include.update(p[0]) exclude.update(p[1]) if options.get("all"): for n, p in enumerate(include): with self.include.call(model_name, {p}, options) as plg: for i in plg.all_or_default(): if n != 0: self.included_ids.intersection_update(i) else: self.included_ids.update(i) else: with self.include.call(model_name, include, options) as plg: for n, i in enumerate(plg.all_or_default()): self.included_ids.update(i) self.included.emit(model_name, self.included_ids) with self.exclude.call(model_name, exclude, options) as plg: for i in plg.all_or_default(): self.excluded_ids.update(i) self.excluded.emit(self._model.__name__, self.excluded_ids) self.matched_ids = self.included_ids self.matched_ids.difference_update(self.excluded_ids) else: with self.empty.call(model_name) as plg: for i in plg.all_or_default(): self.matched_ids.update(i) self.matched.emit(self._model.__name__, self.matched_ids) return self.matched_ids
def _collection_names(model_name, capture=db.model_name(db.Collection)): return { ItemSort.CollectionRandom.value: "Random", ItemSort.CollectionName.value: "Name", ItemSort.CollectionDate.value: "Date Added", ItemSort.CollectionPublished.value: "Date Published", ItemSort.CollectionGalleryCount.value: "Gallery Count", }
def _namespacetags_joins(model_name, capture=db.model_name(db.NamespaceTags)): return { ItemSort.NamespaceTagNamespace.value: (db.NamespaceTags.namespace, db.NamespaceTags.tag), ItemSort.NamespaceTagTag.value: (db.NamespaceTags.tag, db.NamespaceTags.namespace), }
def _generate(model, item_id, size, capture=db.model_name(db.Gallery)): im_path = "" page = GetSession().run().query(db.Page.path).filter( db.and_op(db.Page.gallery_id == item_id, db.Page.number == 1)).one_or_none() if page: im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs) im_path = io_cmd.ImageItem(None, page[0], im_props).main() return im_path
def _collection_orderby(model_name, capture=db.model_name(db.Collection)): return { ItemSort.CollectionRandom.value: (func.random(), ), ItemSort.CollectionName.value: (db.Collection.name, ), ItemSort.CollectionDate.value: (db.Collection.timestamp, ), ItemSort.CollectionPublished.value: (db.Collection.pub_date, ), ItemSort.CollectionGalleryCount.value: (db.func.count(db.Gallery.id), ), }
def _gallery_joins(model_name, capture=db.model_name(db.Gallery)): return { ItemSort.GalleryTitle.value: (db.Gallery.titles, ), ItemSort.GalleryArtist.value: ( db.Gallery.artists, db.Artist.names, ), ItemSort.GalleryPageCount.value: (db.Gallery.pages, ), }
def main(self, model: db.Base, search_filter: str) -> set: assert issubclass(model, db.Base) self._model = model model_name = db.model_name(self._model) if search_filter: self.parsesearchfilter = ParseSearch() pieces = self.parsesearchfilter.run(search_filter) options = get_search_options() include = set() exclude = set() with self.separate.call(pieces) as plg: for p in plg.all(): if len(p) == 2: include.update(p[0]) exclude.update(p[1]) with self.include.call(model_name, include) as plg: for i in plg.all(): if options.get("all"): if self.included_ids: self.included_ids.intersection_update(i) else: self.included_ids.update(i) else: self.included_ids.update(i) self.included.emit(model_name, self.included_ids) with self.exclude.call(model_name, exclude) as plg: for i in plg.all(): self.excluded_ids.update(i) self.excluded.emit(self._model.__name__, self.excluded_ids) self.matched_ids = self.included_ids self.matched_ids.difference_update(self.excluded_ids) else: with self.empty.call(model_name) as plg: for i in plg.all(): self.matched_ids.update(i) self.matched.emit(self._model.__name__, self.matched_ids) return self.matched_ids
def main(self, model: db.Base, item_id: int, image_size: enums.ImageSize) -> db.Profile: self.model = model if image_size == enums.ImageSize.Original: image_size = utils.ImageSize(0, 0) else: image_size = utils.ImageSize( *constants.image_sizes[image_size.name.lower()]) with self.models.call() as plg: for p in plg.all(default=True): self._supported_models.update(p) if self.model not in self._supported_models: raise exceptions.CommandError( utils.this_command(self), "Model '{}' is not supported".format(model)) img_hash = io_cmd.ImageItem.gen_hash(model, image_size, item_id) generate = True sess = constants.db_session() profile_size = str(tuple(image_size)) self.cover = sess.query(db.Profile).filter( db.and_op(db.Profile.data == img_hash, db.Profile.size == profile_size)).first() old_img_hash = None if self.cover: if io_cmd.CoreFS(self.cover.path).exists: generate = False else: old_img_hash = self.cover.data self.next_progress() if not generate: model_name = db.model_name(model) with self.invalidate.call_capture(model_name, model_name, item_id, image_size) as plg: if plg.first_or_default(): generate = True self.next_progress() if generate: constants.task_command.thumbnail_cleaner.wake_up() self.cover = self.run_native(self._generate_and_add, img_hash, old_img_hash, generate, model, item_id, image_size, profile_size).get() self.cover_event.emit(self.cover) return self.cover
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 _gallery_names(model_name, capture=db.model_name(db.Gallery)): return { ItemSort.GalleryRandom.value: "Random", ItemSort.GalleryTitle.value: "Title", ItemSort.GalleryArtist.value: "Artist", ItemSort.GalleryDate.value: "Date Added", ItemSort.GalleryPublished.value: "Date Published", ItemSort.GalleryRead.value: "Last Read", ItemSort.GalleryUpdated.value: "Last Updated", ItemSort.GalleryRating.value: "Rating", ItemSort.GalleryReadCount.value: "Read Count", ItemSort.GalleryPageCount.value: "Page Count", }
def _gallery_orderby(model_name, capture=db.model_name(db.Gallery)): return { ItemSort.GalleryRandom.value: (func.random(), ), ItemSort.GalleryTitle.value: (db.Title.name, ), ItemSort.GalleryArtist.value: (db.ArtistName.name, ), ItemSort.GalleryDate.value: (db.Gallery.timestamp, ), ItemSort.GalleryPublished.value: (db.Gallery.pub_date, ), ItemSort.GalleryRead.value: (db.Gallery.last_read, ), ItemSort.GalleryUpdated.value: (db.Gallery.last_updated, ), ItemSort.GalleryRating.value: (db.Gallery.rating, ), ItemSort.GalleryReadCount.value: (db.Gallery.times_read, ), ItemSort.GalleryPageCount.value: (db.func.count(db.Page.id), ), }
def main(self, model: db.Base, item_id: int, image_size: enums.ImageSize) -> db.Profile: self.model = model if image_size == enums.ImageSize.Original: image_size = utils.ImageSize(0, 0) else: image_size = utils.ImageSize( *constants.image_sizes[image_size.name.lower()]) with self.models.call() as plg: for p in plg.all(default=True): self._supported_models.update(p) if self.model not in self._supported_models: raise exceptions.CommandError( utils.this_command(self), "Model '{}' is not supported".format(model)) img_hash = io_cmd.ImageItem.gen_hash(model, image_size, item_id) generate = True sess = constants.db_session() self.cover = sess.query( db.Profile).filter(db.Profile.data == img_hash).one_or_none() if self.cover: if io_cmd.CoreFS(self.cover.path).exists: generate = False else: self.cover = db.Profile() if generate: model_name = db.model_name(model) with self.generate.call_capture(model_name, model_name, item_id, image_size) as plg: self.cover.path = plg.first() self.cover.data = img_hash self.cover.size = str(tuple(image_size)) if self.cover.path and generate: i = GetModelItemByID().run(model, {item_id})[0] i.profiles.append(self.cover) sess.commit() elif not self.cover.path: self.cover = None self.cover_event.emit(self.cover) return self.cover
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 main(self, model: db.Base, sort_index: int = None, name: bool = False) -> typing.Union[dict, SortTuple]: self.model = model model_name = db.model_name(self.model) items = {} if name: with self.names.call_capture(model_name, model_name) as plg: for x in plg.all(default=True): items.update(x) else: orders = {} with self.orderby.call_capture(model_name, model_name) as plg: for x in plg.all(default=True): orders.update(x) groups = {} with self.groupby.call_capture(model_name, model_name) as plg: for x in plg.all(default=True): groups.update(x) joins = {} with self.joins.call_capture(model_name, model_name) as plg: for x in plg.all(default=True): joins.update(x) for k, v in orders.items(): a = v b = tuple() c = None if k in joins: t = joins[k] if isinstance(t, tuple): b = t if k in groups: c = groups[k] items[k] = self.SortTuple(a, b, c) return items.get(sort_index) if sort_index else items
def main(self, model: db.Base, limit: int = 999, filter: str = "", order_by: str = "", offset: int = 0) -> tuple: s = constants.db_session() q = s.query(model) if filter: q = q.filter(db.sa_text(filter)) if order_by: q = q.order_by(db.sa_text(order_by)) self.fetched_items = tuple(self._query(q, limit, offset)) self.fetched.emit(db.model_name(model), self.fetched_items) return self.fetched_items
def _generate(model, item_id, size, capture=[db.model_name(x) for x in (db.Page, db.Gallery)]): im_path = "" model = GetModelClass().run(model) if model == db.Gallery: page = GetSession().run().query(db.Page.path).filter( db.and_op(db.Page.gallery_id == item_id, db.Page.number == 1)).one_or_none() else: page = GetSession().run().query( db.Page.path).filter(db.Page.id == item_id).one_or_none() if page: im_path = page[0] if im_path: im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs) im_path = io_cmd.ImageItem(None, im_path, im_props).main() return im_path
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