Move package utility functions

We now have a few of them, so move them to their own file like we do in the
other applications.

Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Dan McGee 2010-08-28 10:53:27 -05:00
parent 4c3100ab90
commit 2750b94345
3 changed files with 111 additions and 102 deletions

103
packages/utils.py Normal file
View File

@ -0,0 +1,103 @@
from django.db import connection
from django.db.models import Count, Max
from operator import itemgetter
from main.models import Package
from main.utils import cache_function
from .models import PackageGroup
@cache_function(300)
def get_group_info():
raw_groups = PackageGroup.objects.values_list(
'name', 'pkg__arch__name').order_by('name').annotate(
cnt=Count('pkg'), last_update=Max('pkg__last_update'))
# now for post_processing. we need to seperate things out and add
# the count in for 'any' to all of the other architectures.
group_mapping = {}
for grp in raw_groups:
arch_groups = group_mapping.setdefault(grp[1], {})
arch_groups[grp[0]] = {'name': grp[0], 'arch': grp[1],
'count': grp[2], 'last_update': grp[3]}
# we want to promote the count of 'any' packages in groups to the
# other architectures, and also add any 'any'-only groups
if 'any' in group_mapping:
any_groups = group_mapping['any']
del group_mapping['any']
for arch, arch_groups in group_mapping.iteritems():
for grp in any_groups.itervalues():
if grp['name'] in arch_groups:
found = arch_groups[grp['name']]
found['count'] += grp['count']
if grp['last_update'] > found['last_update']:
found['last_update'] = grp['last_update']
else:
new_g = grp.copy()
# override the arch to not be 'any'
new_g['arch'] = arch
arch_groups[grp['name']] = new_g
# now transform it back into a sorted list
groups = []
for val in group_mapping.itervalues():
groups.extend(val.itervalues())
return sorted(groups, key=itemgetter('name', 'arch'))
@cache_function(300)
def get_differences_info(arch_a, arch_b):
# This is a monster. Join packages against itself, looking for packages in
# our non-'any' architectures only, and not having a corresponding package
# entry in the other table (or having one with a different pkgver). We will
# then go and fetch all of these packages from the database and display
# them later using normal ORM models.
sql = """
SELECT p.id, q.id
FROM packages p
LEFT JOIN packages q
ON (
p.pkgname = q.pkgname
AND p.repo_id = q.repo_id
AND p.arch_id != q.arch_id
AND p.id != q.id
)
WHERE p.arch_id IN (%s, %s)
AND (
q.id IS NULL
OR
p.pkgver != q.pkgver
OR
p.pkgrel != q.pkgrel
)
"""
cursor = connection.cursor()
cursor.execute(sql, [arch_a.id, arch_b.id])
results = cursor.fetchall()
to_fetch = []
for row in results:
# column A will always have a value, column B might be NULL
to_fetch.append(row[0])
# fetch all of the necessary packages
pkgs = Package.objects.in_bulk(to_fetch)
# now build a list of tuples containing differences
differences = []
for row in results:
pkg_a = pkgs.get(row[0])
pkg_b = pkgs.get(row[1])
# We want arch_a to always appear first
# pkg_a should never be None
if pkg_a.arch == arch_a:
item = (pkg_a.pkgname, pkg_a.repo, pkg_a, pkg_b)
else:
# pkg_b can be None in this case, so be careful
name = pkg_a.pkgname if pkg_a else pkg_b.pkgname
repo = pkg_a.repo if pkg_a else pkg_b.repo
item = (name, repo, pkg_b, pkg_a)
if item not in differences:
differences.append(item)
# now sort our list by repository, package name
differences.sort(key=lambda a: (a[1].name, a[0]))
return differences
# vim: set ts=4 sw=4 et:

View File

@ -11,17 +11,17 @@
from django.views.decorators.cache import never_cache
from django.views.decorators.vary import vary_on_headers
from django.views.generic import list_detail
from django.db.models import Count, Max, Q
from django.db.models import Q
from datetime import datetime
from operator import itemgetter
import string
from main.models import Package, PackageFile
from main.models import Arch, Repo, Signoff
from main.models import MirrorUrl
from main.utils import cache_function, make_choice
from packages.models import PackageGroup, PackageRelation
from main.utils import make_choice
from .models import PackageGroup, PackageRelation
from .utils import get_group_info, get_differences_info
def opensearch(request):
if request.is_secure():
@ -85,45 +85,8 @@ def details(request, name='', repo='', arch=''):
return HttpResponseRedirect("/packages/?arch=%s&repo=%s&q=%s" % (
arch.lower(), repo.title(), name))
@cache_function(300)
def get_group_information():
raw_groups = PackageGroup.objects.values_list(
'name', 'pkg__arch__name').order_by('name').annotate(
cnt=Count('pkg'), last_update=Max('pkg__last_update'))
# now for post_processing. we need to seperate things out and add
# the count in for 'any' to all of the other architectures.
group_mapping = {}
for g in raw_groups:
arch_groups = group_mapping.setdefault(g[1], {})
arch_groups[g[0]] = {'name': g[0], 'arch': g[1],
'count': g[2], 'last_update': g[3]}
# we want to promote the count of 'any' packages in groups to the
# other architectures, and also add any 'any'-only groups
if 'any' in group_mapping:
any_groups = group_mapping['any']
del group_mapping['any']
for arch, arch_groups in group_mapping.iteritems():
for g in any_groups.itervalues():
if g['name'] in arch_groups:
found = arch_groups[g['name']]
found['count'] += g['count']
if g['last_update'] > found['last_update']:
found['last_update'] = g['last_update']
else:
new_g = g.copy()
# override the arch to not be 'any'
new_g['arch'] = arch
arch_groups[g['name']] = new_g
# now transform it back into a sorted list
groups = []
for v in group_mapping.itervalues():
groups.extend(v.itervalues())
return sorted(groups, key=itemgetter('name', 'arch'))
def groups(request):
groups = get_group_information()
groups = get_group_info()
return render_to_response('packages/groups.html',
RequestContext(request, {'groups': groups}))
@ -400,68 +363,11 @@ def download(request, name='', repo='', arch=''):
url = string.Template('${host}${repo}/os/${arch}/${file}').substitute(details)
return HttpResponseRedirect(url)
@cache_function(300)
def get_differences_information(arch_a, arch_b):
from django.db import connection
# This is a monster. Join packages against itself, looking for packages in
# our non-'any' architectures only, and not having a corresponding package
# entry in the other table (or having one with a different pkgver). We will
# then go and fetch all of these packages from the database and display
# them later using normal ORM models.
sql = """
SELECT p.id, q.id
FROM packages p
LEFT JOIN packages q
ON (
p.pkgname = q.pkgname
AND p.repo_id = q.repo_id
AND p.arch_id != q.arch_id
AND p.id != q.id
)
WHERE p.arch_id IN (%s, %s)
AND (
q.id IS NULL
OR
p.pkgver != q.pkgver
OR
p.pkgrel != q.pkgrel
)
"""
cursor = connection.cursor()
cursor.execute(sql, [arch_a.id, arch_b.id])
results = cursor.fetchall()
to_fetch = []
for row in results:
# column A will always have a value, column B might be NULL
to_fetch.append(row[0])
# fetch all of the necessary packages
pkgs = Package.objects.in_bulk(to_fetch)
# now build a list of tuples containing differences
differences = []
for row in results:
pkg_a = pkgs.get(row[0])
pkg_b = pkgs.get(row[1])
# We want arch_a to always appear first
# pkg_a should never be None
if pkg_a.arch == arch_a:
item = (pkg_a.pkgname, pkg_a.repo, pkg_a, pkg_b)
else:
# pkg_b can be None in this case, so be careful
name = pkg_a.pkgname if pkg_a else pkg_b.pkgname
repo = pkg_a.repo if pkg_a else pkg_b.repo
item = (name, repo, pkg_b, pkg_a)
if item not in differences:
differences.append(item)
# now sort our list by repository, package name
differences.sort(key=lambda a: (a[1].name, a[0]))
return differences
def arch_differences(request):
# TODO: we have some hardcoded magic here with respect to the arches.
arch_a = Arch.objects.get(name='i686')
arch_b = Arch.objects.get(name='x86_64')
differences = get_differences_information(arch_a, arch_b)
differences = get_differences_info(arch_a, arch_b)
context = {
'arch_a': arch_a,
'arch_b': arch_b,

View File

@ -1,6 +1,6 @@
from django.contrib.sitemaps import Sitemap
from main.models import Package, News
from packages.views import get_group_information
from packages.views import get_group_info
class PackagesSitemap(Sitemap):
changefreq = "weekly"
@ -30,7 +30,7 @@ class PackageGroupsSitemap(Sitemap):
priority = "0.4"
def items(self):
return get_group_information()
return get_group_info()
def lastmod(self, obj):
return obj['last_update']