# HG changeset patch # User terom # Date 1200500880 0 # Node ID 6c774496bb0014374e3ef9b529ce78e3f7e1928f # Parent 8d3ffd87cb0b12dd1a19b8536327ca9fdb0cbc2a a rather silly shelve-based tagging thing, commiting before I scrap the code and start over with SQLite diff -r 8d3ffd87cb0b -r 6c774496bb00 de-cgi-bin/tags.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/de-cgi-bin/tags.py Wed Jan 16 16:28:00 2008 +0000 @@ -0,0 +1,93 @@ +#!/usr/bin/env python2.4 +# +# DeGAL - A pretty simple web image gallery +# Copyright (C) 2007 Tero Marttila +# http://marttila.de/~terom/degal/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +import cgi + +import inc +from lib import tags, template, req, shorturl, utils, settings + +tag_list = [tag for tag in req.get_str("tags", "").split("/") if tag] + +tag_db = tags.TagDB() +shorturl_db = shorturl.DB() + +root = len(tag_list) + 1 + +class Tag (object) : + def __init__ (self, name, count) : + self.title = "%s (%d)" % (name, count) + self.name = utils.url(name, trailing=True) + +class TagView (object) : + def __init__ (self, tag_list) : + img_codes = tag_db.imgs(tag_list) + more_tags = tag_db.tags(tag_list) + + self.images = [] + + for index, key in enumerate(img_codes) : + dir, fname = shorturl_db.image_info(key) + + img = Image(key, dir, fname, index) + self.images.append(img) + + self.tags = [Tag(name, count) for (name, count) in more_tags] + + def render (self) : + descr = "" + return template.gallery.render( + stylesheet_url = utils.url("style.css", up=root), + + breadcrumb = [(utils.url(up=root), "Index"), (utils.url(up=root-1), "Tags")] + [(utils.url(up=root-(n+1), trailing=True), tag) for n, tag in enumerate(tag_list)], + + title = "Tags :: %s" % (" » ".join(tag_list) or "All"), + + num_pages = 1, + cur_page = 0, + + dirs = self.tags, + images = self.images, + + description = descr, + + shorturl = None, + shorturl_code = None, + ) + +class Image (object) : + def __init__ (self, key, dir, fname, index) : + self.fname = fname + self.name = utils.url_join(dir, fname, abs=True) + self.html_name = utils.url_join(dir, fname + ".html", abs=True) + self.thumb_name = utils.url_join(dir, settings.THUMB_DIR, fname, abs=True) + self.preview_name = utils.url_join(dir, settings.PREVIEW_DIR, fname, abs=True) + + self.shorturl = key + + self.prev = self.next = None + +tagview = TagView(tag_list) + +print "Content-Type: text/html" +print +print tagview.render() + diff -r 8d3ffd87cb0b -r 6c774496bb00 lib/req.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/req.py Wed Jan 16 16:28:00 2008 +0000 @@ -0,0 +1,50 @@ +# DeGAL - A pretty simple web image gallery +# Copyright (C) 2007 Tero Marttila +# http://marttila.de/~terom/degal/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +import cgi +import Cookie +import os + +vars = cgi.FieldStorage() + +# the cookie with the user's current series +cookie = Cookie.SimpleCookie(os.environ.get('HTTP_COOKIE', None)) + +class token (object) : + pass + +REQUIRED_PARAM = token() + +def get_str (key, default=REQUIRED_PARAM) : + if key in vars : + return vars[key].value + elif default is REQUIRED_PARAM : + raise ValueError("Required param %s" % key) + else : + return default + +def get_int (key, default=REQUIRED_PARAM) : + if key in vars : + return int(vars[key].value) + elif default is REQUIRED_PARAM : + raise ValueError("Required param %s" % key) + else : + return default + diff -r 8d3ffd87cb0b -r 6c774496bb00 lib/shorturl.py --- a/lib/shorturl.py Wed Jan 16 14:58:03 2008 +0000 +++ b/lib/shorturl.py Wed Jan 16 16:28:00 2008 +0000 @@ -124,4 +124,22 @@ raise ValueError("%s is not an img" % key) return dirpath, fname + + def shorturls_for (self, paths) : + ret = [] + for key in self.db.keys() : + if key.startswith('_') : + continue + + type, dir, fname = self.db[key] + path = os.path.join(dir.lstrip('.').lstrip('/'), fname) + if path in paths : + ret.append(key) + paths.remove(path) + + if paths : + raise ValueError("Paths not found: %s" % " ".join(paths)) + + return ret + diff -r 8d3ffd87cb0b -r 6c774496bb00 lib/tags.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/tags.py Wed Jan 16 16:28:00 2008 +0000 @@ -0,0 +1,89 @@ +import shelve + +class TagDB (object) : + _imgs_cache = {} + + def __init__ (self, read_only=True) : + self.img_tags = shelve.open("img_tags", read_only and 'r' or 'c') + self.tag_imgs = shelve.open("tag_imgs", read_only and 'r' or 'c') + + def tag (self, img, tag) : + """ + Associate the given image with the given tag + """ + + if img not in self.img_tags : + self.img_tags[img] = set([tag]) + else : + s = self.img_tags[img] + s.add(tag) + self.img_tags[img] = s + + + if tag not in self.tag_imgs : + self.tag_imgs[tag] = set([img]) + else : + s = self.tag_imgs[tag] + s.add(img) + self.tag_imgs[tag] = s + + print "%s <-> %s" % (img, tag) + + def imgs (self, tags) : + """ + Get the set of images that have the given set of tags + """ + + cache_key = "/".join(tags) + + if cache_key in self._imgs_cache : + return self._imgs_cache[cache_key] + + if not tags : + return set(self.img_tags.keys()) + + img_sets = [self.tag_imgs[tag] for tag in tags] + + res = None + + for img_set in img_sets : + if res : + res = res & img_set + else : + res = img_set + + self._imgs_cache[cache_key] = res + + return res + + def tags (self, tags) : + """ + Get the set of tags that are present in the set of images specified by these tags, sorted by count + + This is currently implemented quite inefficiently... giev SQL db? + """ + + imgs = self.imgs(tags) + + ret = [] + + for tag in self.tag_imgs.keys() : + if tag in tags : + continue + + count = len(self.tag_imgs[tag] & imgs) + + if count : + ret.append((tag, count)) + + def my_cmp ((at, ac), (bt, bc)) : + return cmp((ac, at), (bc, bt)) + + ret.sort(reverse=True) + + return ret + + def close (self) : + self.img_tags.close() + self.tag_imgs.close() + diff -r 8d3ffd87cb0b -r 6c774496bb00 lib/utils.py --- a/lib/utils.py Wed Jan 16 14:58:03 2008 +0000 +++ b/lib/utils.py Wed Jan 16 16:28:00 2008 +0000 @@ -47,8 +47,9 @@ def url (*parts, **kwargs) : abs = kwargs.pop('abs', False) up = kwargs.pop('up', 0) + trailing = kwargs.pop('trailing', False) - return '/'.join(([""]*int(abs)) + ([".."]*up) + list(parts)) + return '/'.join(([""]*int(abs)) + ([".."]*up) + list(parts) + ([""]*int(trailing))) url_join = url