diff options
-rw-r--r-- | packages/utils.py | 103 | ||||
-rw-r--r-- | packages/views.py | 106 | ||||
-rw-r--r-- | sitemaps.py | 4 |
3 files changed, 111 insertions, 102 deletions
diff --git a/packages/utils.py b/packages/utils.py new file mode 100644 index 00000000..204e5bf2 --- /dev/null +++ b/packages/utils.py @@ -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: diff --git a/packages/views.py b/packages/views.py index cef7828f..4fd34edf 100644 --- a/packages/views.py +++ b/packages/views.py @@ -11,17 +11,17 @@ from django.contrib.admin.widgets import AdminDateWidget 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, diff --git a/sitemaps.py b/sitemaps.py index 584e3b3b..cc8db94b 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -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'] |