summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/utils.py35
-rw-r--r--public/utils.py38
2 files changed, 48 insertions, 25 deletions
diff --git a/main/utils.py b/main/utils.py
index 2ca69bc..81f689e 100644
--- a/main/utils.py
+++ b/main/utils.py
@@ -91,4 +91,39 @@ def set_created_field(sender, **kwargs):
if hasattr(obj, 'created') and not obj.created:
obj.created = datetime.utcnow()
+def groupby_preserve_order(iterable, keyfunc):
+ '''Take an iterable and regroup using keyfunc to determine whether items
+ belong to the same group. The order of the iterable is preserved and
+ similar keys do not have to be consecutive. This means the earliest
+ occurrence of a given key will determine the order of the lists in the
+ returned list.'''
+ seen_keys = {}
+ result = []
+ for item in iterable:
+ key = keyfunc(item)
+
+ group = seen_keys.get(key, None)
+ if group is None:
+ group = []
+ seen_keys[key] = group
+ result.append(group)
+
+ group.append(item)
+
+ return result
+
+class PackageStandin(object):
+ '''Resembles a Package object, and has a few of the same fields, but is
+ really a link to a pkgbase that has no package with matching pkgname.'''
+ def __init__(self, package):
+ self.package = package
+ self.pkgname = package.pkgbase
+
+ def __getattr__(self, name):
+ return getattr(self.package, name)
+
+ def get_absolute_url(self):
+ return '/packages/%s/%s/%s/' % (
+ self.repo.name.lower(), self.arch.name, self.pkgbase)
+
# vim: set ts=4 sw=4 et:
diff --git a/public/utils.py b/public/utils.py
index 0be3eba..5900c67 100644
--- a/public/utils.py
+++ b/public/utils.py
@@ -1,7 +1,7 @@
from operator import attrgetter
from main.models import Arch, Package, Repo
-from main.utils import cache_function
+from main.utils import cache_function, groupby_preserve_order, PackageStandin
class RecentUpdate(object):
def __init__(self, packages):
@@ -35,18 +35,12 @@ class RecentUpdate(object):
for package in self.packages:
yield package
else:
- # time to fake out the template, this is a tad dirty
- arches = set(pkg.arch for pkg in self.others)
- for arch in arches:
- url = '/packages/%s/%s/%s/' % (
- self.repo.name.lower(), arch.name, self.pkgbase)
- package_stub = {
- 'pkgname': self.pkgbase,
- 'arch': arch,
- 'repo': self.repo,
- 'get_absolute_url': url
- }
- yield package_stub
+ # fake out the template- this is slightly hacky but yields one
+ # 'package-like' object per arch which is what the normal loop does
+ arches = set()
+ for package in self.others:
+ if package.arch not in arches and not arches.add(package.arch):
+ yield PackageStandin(package)
@cache_function(300)
def get_recent_updates(number=15):
@@ -59,20 +53,14 @@ def get_recent_updates(number=15):
for arch in Arch.objects.all():
pkgs += list(Package.objects.normal().filter(
arch=arch).order_by('-last_update')[:fetch])
- pkgs.sort(key=attrgetter('last_update'))
+ pkgs.sort(key=attrgetter('last_update'), reverse=True)
- updates = []
- while len(pkgs) > 0:
- pkg = pkgs.pop()
-
- in_group = lambda x: pkg.repo == x.repo and pkg.pkgbase == x.pkgbase
- samepkgs = [other for other in pkgs if in_group(other)]
- samepkgs.append(pkg)
+ same_pkgbase_key = lambda x: (x.repo.name, x.pkgbase)
+ grouped = groupby_preserve_order(pkgs, same_pkgbase_key)
- # now remove all the packages we just pulled out
- pkgs = [other for other in pkgs if other not in samepkgs]
-
- update = RecentUpdate(samepkgs)
+ updates = []
+ for group in grouped:
+ update = RecentUpdate(group)
updates.append(update)
return updates[:number]