aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2007-11-11 00:40:56 +0000
committerRobin H. Johnson <robbat2@gentoo.org>2007-11-11 00:40:56 +0000
commitf4173c6c46bb3abd299da838ce01a6bb3c254176 (patch)
treecab56e2d280e8d05d81533611fda80d8383329e7 /web
parentCleanup. (diff)
downloadpackages-f4173c6c46bb3abd299da838ce01a6bb3c254176.tar.gz
packages-f4173c6c46bb3abd299da838ce01a6bb3c254176.tar.bz2
packages-f4173c6c46bb3abd299da838ce01a6bb3c254176.zip
Split up the code a bit more.
Diffstat (limited to 'web')
-rw-r--r--web/controller.py15
-rw-r--r--web/lib/changelog_formatter.py37
-rw-r--r--web/lib/headers.py32
-rw-r--r--web/lib/links.py32
-rw-r--r--web/lib/query_filter.py74
-rw-r--r--web/lib/template.py80
-rw-r--r--web/model.py84
-rw-r--r--web/templates/layout.html5
8 files changed, 188 insertions, 171 deletions
diff --git a/web/controller.py b/web/controller.py
index f7f4ef7..62d8676 100644
--- a/web/controller.py
+++ b/web/controller.py
@@ -6,10 +6,9 @@ import os, sys, math
import cherrypy
from web.model import latest_per_day, \
- build_centerpkg_list, \
- lastmodified_httpheader, \
- lastmodified_rightcontent
-
+ build_centerpkg_list
+from web.lib.headers import lastmodified_httpheader, \
+ lastmodified_rightcontent
from web.lib.query_filter import sanitize_query_string
from web.lib import template, filters
from pkgcore.ebuild.cpv import CPV
@@ -31,21 +30,21 @@ class Root(object):
def f():
entry_filter = filters.EntryFilters(self.database)
return entry_filter.unfiltered()
- return self.database._mc_wrap('cache_latest', f, time=300)
+ return self.database.mc_wrap('cache_latest', f, time=300)
@property
def cache_newpkgs(self):
def f():
entry_filter = filters.EntryFilters(self.database)
return entry_filter.newpkgs_filter()
- return self.database._mc_wrap('cache_newpkgs', f, time=300)
+ return self.database.mc_wrap('cache_newpkgs', f, time=300)
@property
def cache_verbumps(self):
def f():
entry_filter = filters.EntryFilters(self.database)
return entry_filter.verbumps_filter()
- return self.database._mc_wrap('cache_verbumps', f, time=300)
+ return self.database.mc_wrap('cache_verbumps', f, time=300)
@cherrypy.expose
@template.expire_on_30_min()
@@ -273,7 +272,7 @@ class Root(object):
sums['pkgs'] += cat[1]
sums['ebuilds'] += cat[2]
else:
- row.append((None,-1,-1))
+ row.append((None, -1, -1))
rows.append(row)
day_list = latest_per_day(latest_entries, left_daycount)
diff --git a/web/lib/changelog_formatter.py b/web/lib/changelog_formatter.py
index 1dc187d..aca1f62 100644
--- a/web/lib/changelog_formatter.py
+++ b/web/lib/changelog_formatter.py
@@ -1,14 +1,12 @@
import re
from cherrypy.lib.tidy import html_break
-from web.lib.links import viewcvs_link, bugzilla_bug_link, \
- bugzilla_search_link, ciavc_link
+from web.lib.links import viewcvs_link, \
+ bugzilla_bug_link, \
+ ciavc_link
-"""Given a changelog snippet, make it look nice with HTML:
- - Make the body HTML-safe via entities.
- - Replace the author email with a CIA.vc link
- - Link the changed files to ViewCVS
- - Link any bug# entries to Bugzilla"""
+# We use short variable names!
+# pylint: disable-msg=C0103
re_author = re.compile(r' 200\d; ([^<]+)? ?<([^@]+)@[^>]')
re_author2 = re.compile(r' ([^@ ]+)@')
@@ -169,3 +167,28 @@ def pretty_changelog(cat, pn, changelog):
# Done!
return (changelog, authorname, authorid)
+def optimal_collapse(atom, pnlength, pvlength, ellipsis = '^'):
+ """Shrink the PN-PV string using well-placed ellipsis characters so
+ that the maximum length of the string does not exceed the sum of
+ the max specified PN and PV lengths. Retain the maximum amount of
+ information."""
+ # TP[PN] = target length
+ maxlength = pnlength + pvlength + 1
+ npn = pn = atom.package
+ npv = pv = atom.fullver
+ tlpn = len(pn)
+ tlpv = len(pv)
+ pnpv = "%s-%s" % (npn, npv)
+ i = 0
+ while len(pnpv) > maxlength and i < 25:
+ if tlpv > pvlength:
+ tlpv -= 1
+ npv = pv[0:tlpv-1] + '@'
+ elif tlpn > pnlength:
+ tlpn -= 1
+ npn = pn[0:tlpn-1] + '@'
+ pnpv = "%s-%s" % (npn, npv)
+ i += 1
+ return pnpv.replace('@', ellipsis)
+
+# vim:ts=4 et ft=python:
diff --git a/web/lib/headers.py b/web/lib/headers.py
new file mode 100644
index 0000000..9cb5220
--- /dev/null
+++ b/web/lib/headers.py
@@ -0,0 +1,32 @@
+from time import strftime, gmtime, time, localtime
+
+def _lastmodified_strftime(format, latest_entry):
+ """return a formatted timestamp of latest entry
+ with the specified strftime"""
+ return strftime(format, localtime(latest_entry[1]))
+
+def lastmodified_rightcontent(latest_entry):
+ """return a formatted timestamp of latest entry (being last change)"""
+ fmt = '%d %b %Y<br />%H:%M %Z'
+ return _lastmodified_strftime(fmt, latest_entry)
+
+def lastmodified_httpheader(latest_entry):
+ """return a HTTP Last-Modified value of the latest entry"""
+ fmt = '%a, %d %b %Y %H:%M:%S UTC'
+ return _lastmodified_strftime(fmt, latest_entry)
+
+def pageexpire_timestamp():
+ expire_ts = int(time())
+ # Work out when the LAST 30 minute window was
+ expire_ts = expire_ts - expire_ts % (30*60)
+ # Now find the next one
+ expire_ts += (30*60)
+ # And allow 5 minutes for processing changes
+ expire_ts += (5*60)
+ return expire_ts
+
+def httpheader_expires():
+ expire_ts = pageexpire_timestamp()
+ return strftime('%a, %d %b %Y %H:%M:%S UTC', gmtime(expire_ts))
+
+# vim:ts=4 et ft=python:
diff --git a/web/lib/links.py b/web/lib/links.py
index be83d7c..7bae06f 100644
--- a/web/lib/links.py
+++ b/web/lib/links.py
@@ -1,3 +1,32 @@
+import cherrypy
+from web.lib.query_filter import format_query
+
+# We use short variable names!
+# pylint: disable-msg=C0103
+
+def absurl(path='', qs=None, script_name=None):
+ """Better version of cherrypy.url. Generates absolute URLs."""
+
+ if qs is None:
+ qs = {}
+ return cherrypy.url(
+ path=path,
+ qs=format_query(qs),
+ script_name=script_name,
+ base=None,
+ relative=False)
+
+def relurl(path='', qs=None, script_name=None):
+ """Better version of cherrypy.url. Generates relative URLs."""
+ if qs is None:
+ qs = {}
+ return cherrypy.url(
+ path=path,
+ qs=format_query(qs),
+ script_name=script_name,
+ base='',
+ relative=False)
+
def viewcvs_link(path,
repo = 'gentoo-x86',
sitebase = 'sources.gentoo.org/viewcvs.py'):
@@ -34,5 +63,6 @@ def bugzilla_search_link(searchstring,
def ciavc_link(username):
"""Given a username, give link to the relevant CIA.vc entry"""
-
return 'http://cia.vc/stats/author/%s' % (username)
+
+# vim:ts=4 et ft=python:
diff --git a/web/lib/query_filter.py b/web/lib/query_filter.py
index 5c8144e..fb32fe6 100644
--- a/web/lib/query_filter.py
+++ b/web/lib/query_filter.py
@@ -1,4 +1,7 @@
-"""Query filters"""
+import cherrypy
+
+# We use short variable names!
+# pylint: disable-msg=C0103
def sanitize_query_string(qsargs=None):
"""Allow ONLY the query arguments that are completely safe to pass.
@@ -39,3 +42,72 @@ def format_query(query_string=None):
new_qs.append('%s%s' % (key, val))
query_string = '&'.join(new_qs)
return query_string
+
+def check_page_variables(kwds=None):
+ if kwds is None:
+ kwds = {}
+ # We must have this for safety
+ assert 'safeqs' in kwds, \
+ 'safe query arguments not available!'
+
+ if 'safeqs_arches' not in kwds:
+ qsd = {}
+ for i in ['all', 'exotic', 'common']:
+ qsd[i] = kwds['safeqs'].copy()
+ qsd[i]['arches'] = i
+ # arches=common is the default
+ if i is 'common':
+ del qsd[i]['arches']
+ kwds['safeqs_arches'] = qsd
+
+ if 'cherrypy' not in kwds:
+ kwds['cherrypy'] = cherrypy
+ if 'self' not in kwds:
+ kwds['self'] = cherrypy.request.path_info.replace('/feed','')
+ if 'mainrss' not in kwds:
+ kwds['mainrss'] = '/feed/'
+ if 'pagerss_reltitle' not in kwds:
+ (rss, title) = create_rel(cherrypy.request.path_info)
+ kwds['pagerss_reltitle'] = title
+ kwds['pagerss'] = rss
+ return kwds
+
+def create_rel(path):
+ # This is a switch structure
+ # pylint: disable-msg=R0912
+ t = ''
+ if path.startswith('/feed/'):
+ path = path.replace('/feed','')
+
+ # Strip trailing slash
+ if len(path) > 1 and path[-1] == '/':
+ path = path[0:-1]
+
+ rsspath = '/feed'+path
+
+ if path == '/':
+ pass
+ elif path.startswith('/category'):
+ t = 'This category'
+ elif path.startswith('/package'):
+ t = 'This package'
+ elif path.startswith('/arch'):
+ m = path.split('/')
+ if len(m) == 3:
+ t = m[2]
+ elif len(m) == 4:
+ t = '%s %s' % (m[3], m[2])
+ elif path.startswith('/verbump'):
+ t = 'Version bumps'
+ elif path.startswith('/newpackage'):
+ t = 'New packages'
+ elif path.startswith('/faq'):
+ t = 'FAQ'
+ rsspath = None
+ elif path.startswith('/categories'):
+ t = 'Category List'
+ rsspath = None
+ else:
+ raise Exception('Unknown page!')
+ return (rsspath, t)
+
diff --git a/web/lib/template.py b/web/lib/template.py
index 0034144..c842353 100644
--- a/web/lib/template.py
+++ b/web/lib/template.py
@@ -8,6 +8,8 @@ from genshi.core import Stream
from genshi.output import encode, get_serializer
from genshi.template import Context, TemplateLoader
from web.lib import ajax
+from web.lib.query_filter import check_page_variables
+from web.lib.headers import httpheader_expires
loader = TemplateLoader(
os.path.join(os.path.dirname(__file__), '..', 'templates'),
@@ -34,35 +36,6 @@ def output(filename, method='html', encoding='utf-8', **options):
return wrapper
return decorate
-def check_page_variables(kwds=None):
- if kwds is None:
- kwds = {}
- # We must have this for safety
- assert 'safeqs' in kwds, \
- 'safe query arguments not available!'
-
- if 'safeqs_arches' not in kwds:
- from string import capitalize
- qsd = {}
- for i in ['all', 'exotic', 'common']:
- qsd[i] = kwds['safeqs'].copy()
- qsd[i]['arches'] = i
- # arches=common is the default
- if i is 'common':
- del qsd[i]['arches']
- kwds['safeqs_arches'] = qsd
-
- if 'cherrypy' not in kwds:
- kwds['cherrypy'] = cherrypy
- if 'self' not in kwds:
- kwds['self'] = cherrypy.request.path_info.replace('/feed','')
- if 'mainrss' not in kwds:
- kwds['mainrss'] = '/feed/'
- if 'pagerss_reltitle' not in kwds:
- (rss, title) = create_rel(cherrypy.request.path_info)
- kwds['pagerss_reltitle'] = title
- kwds['pagerss'] = rss
- return kwds
def render(*args, **kwargs):
"""Function to render the given data to the template specified via the
@@ -87,57 +60,10 @@ def expire_on_30_min():
"""
def decorate(func):
def newfunc(*args, **kwargs):
- expiretime = int(time.time())
- # Work out when the LAST 30 minute window was
- expiretime = expiretime - expiretime % (30*60)
- # Now find the next one
- expiretime += (30*60)
- # And allow 5 minutes for processing changes
- expiretime += (5*60)
- expirestr = time.strftime('%a, %d %b %Y %H:%M:%S GMT',time.gmtime(expiretime))
- cherrypy.response.headers['Expires'] = expirestr
+ cherrypy.response.headers['Expires'] = httpheader_expires()
cherrypy.response.headers['Cache-Control'] = 'max-age=1800, public, s-maxage=1800'
return func(*args,**kwargs)
return newfunc
return decorate
-def create_rel(path):
- t = ''
- if path.startswith('/feed/'):
- path = path.replace('/feed','')
-
- # Strip trailing slash
- if len(path) > 1 and path[-1] == '/':
- path = path[0:-1]
-
- rsspath = '/feed'+path
-
- if path == '/':
- pass
- elif path.startswith('/category'):
- t = 'This category'
- elif path.startswith('/package'):
- t = 'This package'
- elif path.startswith('/arch'):
- m = path.split('/')
- if len(m) == 3:
- t = m[2]
- elif len(m) == 4:
- t = '%s %s' % (m[3],m[2])
- elif path.startswith('/verbump'):
- t = 'Version bumps'
- elif path.startswith('/newpackage'):
- t = 'New packages'
- elif path.startswith('/faq'):
- t = 'FAQ'
- rsspath = None
- elif path.startswith('/categories'):
- t = 'Category List'
- rsspath = None
- else:
- raise Exception('Unknown page!')
- return (rsspath, t)
-
-
-
# vim:ts=4 et ft=python:
diff --git a/web/model.py b/web/model.py
index fc0634c..062ca02 100644
--- a/web/model.py
+++ b/web/model.py
@@ -8,40 +8,12 @@ from DBUtils.PersistentDB import PersistentDB
from DBUtils.PooledDB import PooledDB
from etc.const_data import ConstData
-from web.lib import query_filter
-from web.lib.changelog_formatter import pretty_changelog
+from web.lib.changelog_formatter import pretty_changelog, optimal_collapse
from web.lib.links import viewcvs_link, bugzilla_search_link
-import cherrypy
# We use short variable names!
# pylint: disable-msg=C0103
-cache_package_details = {}
-cache_package_keywords = {}
-
-def absurl(path='', qs=None, script_name=None):
- """Better version of cherrypy.url. Generates absolute URLs."""
-
- if qs is None:
- qs = {}
- return cherrypy.url(
- path=path,
- qs=query_filter.format_query(qs),
- script_name=script_name,
- base=None,
- relative=False)
-
-def relurl(path='', qs=None, script_name=None):
- """Better version of cherrypy.url. Generates relative URLs."""
- if qs is None:
- qs = {}
- return cherrypy.url(
- path=path,
- qs=query_filter.format_query(qs),
- script_name=script_name,
- base='',
- relative=False)
-
def latest_per_day(cpvlist, daycount, pkgcount = 110):
"""generate list of sets with days and pv's as value"""
@@ -70,45 +42,6 @@ def latest_per_day(cpvlist, daycount, pkgcount = 110):
result.append([last_day, last_day_cpvs])
return result
-def optimal_collapse(atom, pnlength, pvlength, ellipsis = '^'):
- """Shrink the PN-PV string using well-placed ellipsis characters so
- that the maximum length of the string does not exceed the sum of
- the max specified PN and PV lengths. Retain the maximum amount of
- information."""
- # TP[PN] = target length
- maxlength = pnlength + pvlength + 1
- npn = pn = atom.package
- npv = pv = atom.fullver
- tlpn = len(pn)
- tlpv = len(pv)
- pnpv = "%s-%s" % (npn, npv)
- i = 0
- while len(pnpv) > maxlength and i < 25:
- if tlpv > pvlength:
- tlpv -= 1
- npv = pv[0:tlpv-1] + '@'
- elif tlpn > pnlength:
- tlpn -= 1
- npn = pn[0:tlpn-1] + '@'
- pnpv = "%s-%s" % (npn, npv)
- i += 1
- return pnpv.replace('@', ellipsis)
-
-def _lastmodified_strftime(format, latest_entry):
- """return a formatted timestamp of latest entry
- with the specified strftime"""
- return strftime(format, localtime(latest_entry[1]))
-
-def lastmodified_rightcontent(latest_entry):
- """return a formatted timestamp of latest entry (being last change)"""
- fmt = '%d %b %Y<br />%H:%M %Z'
- return _lastmodified_strftime(fmt, latest_entry)
-
-def lastmodified_httpheader(latest_entry):
- """return a HTTP Last-Modified value of the latest entry"""
- fmt = '%a, %d %b %Y %H:%M:%S UTC'
- return _lastmodified_strftime(fmt, latest_entry)
-
def build_centerpkg_list(latest_entries,
get_package_details_cpv,
count, **kwds):
@@ -160,7 +93,7 @@ class PackageDB(object):
import memcache
servers = config['memcached']['servers']
args = config['memcached']['args']
- mc = memcache.Client(servers,debug=1)
+ mc = memcache.Client(servers, **args)
dummy = mc.get_stats()
if dummy and len(dummy) > 0:
self.mc = mc
@@ -195,7 +128,10 @@ class PackageDB(object):
self.sql[k] = s
#sql = FrozenDict(sql)
- def _mc_wrap(self, key, func, **kwopts):
+ def mc_wrap(self, key, func, **kwopts):
+ # Do not complain about correct usage of ** magic
+ # pylint: disable-msg=W0142
+
obj = None
if self.mc:
obj = self.mc.get(key)
@@ -479,7 +415,7 @@ class PackageDB(object):
key = 'pkg_details_%s/%s' % (cat, pn)
def f():
return self._get_package_details(cat, pn)
- return self._mc_wrap(key, f, time=300)
+ return self.mc_wrap(key, f, time=300)
sql['SELECT_get_package_details_metadata'] = """
SELECT license, homepage, description, changelog
@@ -539,7 +475,7 @@ class PackageDB(object):
key = 'pkg_keywords_%s' % (query, )
def f():
return self._get_package_keywords(query)
- return self._mc_wrap(key, f, time=300)
+ return self.mc_wrap(key, f, time=300)
sql['SELECT_get_package_keywords_cat_pn'] = """
SELECT __CPV__, arches.arch, mode
@@ -562,9 +498,6 @@ class PackageDB(object):
def _get_package_keywords(self, query):
"""return cpv keywords (uncached)"""
- if query in cache_package_keywords:
- return cache_package_keywords[query]
-
if query.fullver:
sql = self.sql['SELECT_get_package_keywords_cat_pn_pv']
params = (query.category, query.package, query.fullver)
@@ -575,6 +508,7 @@ class PackageDB(object):
cursor.execute(sql, params)
last_cpv = None
ret_list = []
+ pkg = {}
for row in cursor.fetchall():
cpv = str(row[0])
arch = str(row[1])
diff --git a/web/templates/layout.html b/web/templates/layout.html
index 4ba3d18..154238b 100644
--- a/web/templates/layout.html
+++ b/web/templates/layout.html
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?python from genshi import HTML ?>
<?python import web.model as model ?>
+<?python import web.lib.links as links ?>
<?python
def absurl(path='',qs=''):
if qs == '':
qs = safeqs
- return model.absurl(path, qs)
+ return links.absurl(path, qs)
def relurl(path='',qs=''):
if qs == '':
qs = safeqs
- return model.relurl(path, qs)
+ return links.relurl(path, qs)
def full_cat_url(baseurl):
qs_full_cat = safeqs.copy()
qs_full_cat['full_cat'] = ''