diff options
43 files changed, 191 insertions, 155 deletions
diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py index d0e5ef3d..3eaa6110 100644 --- a/devel/management/commands/reporead.py +++ b/devel/management/commands/reporead.py @@ -22,6 +22,7 @@ import tarfile import logging from datetime import datetime from optparse import make_option +from pytz import utc from django.core.management.base import BaseCommand, CommandError from django.db import connections, router, transaction @@ -29,8 +30,10 @@ from django.db.utils import IntegrityError from devel.utils import UserFinder from main.models import Arch, Package, PackageDepend, PackageFile, Repo +from main.utils import utc_now from packages.models import Conflict, Provision, Replacement + logging.basicConfig( level=logging.WARNING, format='%(asctime)s -> %(levelname)s: %(message)s', @@ -115,7 +118,8 @@ class RepoPackage(object): self.epoch = int(match.group(2)) elif k == 'builddate': try: - self.builddate = datetime.utcfromtimestamp(int(v[0])) + builddate = datetime.utcfromtimestamp(int(v[0])) + self.builddate = builddate.replace(tzinfo=utc) except ValueError: try: self.builddate = datetime.strptime(v[0], @@ -275,33 +279,21 @@ def populate_files(dbpkg, repopkg, force=False): delete_pkg_files(dbpkg) logger.info("adding %d files for package %s", len(repopkg.files), dbpkg.pkgname) + pkg_files = [] for f in repopkg.files: dirname, filename = f.rsplit('/', 1) if filename == '': filename = None - # this is basically like calling dbpkg.packagefile_set.create(), - # but much faster as we can skip a lot of the repeated code paths - # TODO use Django 1.4 bulk_create pkgfile = PackageFile(pkg=dbpkg, is_directory=(filename is None), directory=dirname + '/', filename=filename) - pkgfile.save(force_insert=True) - dbpkg.files_last_update = datetime.utcnow() + pkg_files.append(pkgfile) + PackageFile.objects.bulk_create(pkg_files) + dbpkg.files_last_update = utc_now() dbpkg.save() -def select_pkg_for_update(dbpkg): - database = router.db_for_write(Package, instance=dbpkg) - connection = connections[database] - if 'sqlite' in connection.settings_dict['ENGINE'].lower(): - return dbpkg - new_pkg = Package.objects.raw( - 'SELECT * FROM packages WHERE id = %s FOR UPDATE', - [dbpkg.id]) - return list(new_pkg)[0] - - def update_common(archname, reponame, pkgs, sanity_check=True): # If isolation level is repeatable-read, we need to ensure each package # update starts a new transaction and re-queries the database as @@ -368,7 +360,7 @@ def db_update(archname, reponame, pkgs, force=False): dbpkg = Package(pkgname=pkg.name, arch=architecture, repo=repository) try: with transaction.commit_on_success(): - populate_pkg(dbpkg, pkg, timestamp=datetime.utcnow()) + populate_pkg(dbpkg, pkg, timestamp=utc_now()) except IntegrityError: logger.warning("Could not add package %s; " "not fatal if another thread beat us to it.", @@ -395,14 +387,13 @@ def db_update(archname, reponame, pkgs, force=False): if not force and pkg_same_version(pkg, dbpkg): continue elif not force: - timestamp = datetime.utcnow() + timestamp = utc_now() # The odd select_for_update song and dance here are to ensure # simultaneous updates don't happen on a package, causing # files/depends/all related items to be double-imported. with transaction.commit_on_success(): - # TODO Django 1.4 select_for_update() will work once released - dbpkg = select_pkg_for_update(dbpkg) + dbpkg = Package.objects.select_for_update().get(id=dbpkg.id) if not force and pkg_same_version(pkg, dbpkg): logger.debug("Package %s was already updated", pkg.name) continue @@ -433,8 +424,7 @@ def filesonly_update(archname, reponame, pkgs, force=False): elif not force and dbpkg.files_last_update > dbpkg.last_update: logger.debug("Files for %s are up to date", pkg.name) continue - # TODO Django 1.4 select_for_update() will work once released - dbpkg = select_pkg_for_update(dbpkg) + dbpkg = Package.objects.select_for_update().get(id=dbpkg.id) logger.debug("Checking files for package %s", pkg.name) populate_files(dbpkg, pkg, force=force) diff --git a/devel/urls.py b/devel/urls.py index 07cb321b..31afc86b 100644 --- a/devel/urls.py +++ b/devel/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('devel.views', (r'^admin_log/$','admin_log'), diff --git a/devel/views.py b/devel/views.py index 36d0cccf..f2c3949c 100644 --- a/devel/views.py +++ b/devel/views.py @@ -1,3 +1,10 @@ +from datetime import datetime, timedelta +import operator +import pytz +import random +from string import ascii_letters, digits +import time + from django import forms from django.http import HttpResponseRedirect from django.contrib.auth.decorators import \ @@ -16,19 +23,13 @@ from django.views.generic.simple import direct_to_template from django.utils.http import http_date from main.models import Package, PackageDepend, PackageFile, TodolistPkg -from main.models import Arch, Repo -from main.models import UserProfile +from main.models import Arch, Repo, UserProfile +from main.utils import utc_now from packages.models import PackageRelation from packages.utils import get_signoff_groups from todolists.utils import get_annotated_todolists from .utils import get_annotated_maintainers -from datetime import datetime, timedelta -import operator -import pytz -import random -from string import ascii_letters, digits -import time @login_required def index(request): @@ -85,22 +86,14 @@ def clock(request): devs = User.objects.filter(is_active=True).order_by( 'first_name', 'last_name').select_related('userprofile') - now = datetime.now() - utc_now = datetime.utcnow().replace(tzinfo=pytz.utc) - # now annotate each dev object with their current time - for dev in devs: - tz = pytz.timezone(dev.userprofile.time_zone) - dev.current_time = utc_now.astimezone(tz) - + now = utc_now() page_dict = { 'developers': devs, - 'now': now, - 'utc_now': utc_now, + 'utc_now': now, } response = direct_to_template(request, 'devel/clock.html', page_dict) if not response.has_header('Expires'): - # why this works only with the non-UTC date I have no idea... expire_time = now.replace(second=0, microsecond=0) expire_time += timedelta(minutes=1) expire_time = time.mktime(expire_time.timetuple()) @@ -168,12 +161,12 @@ def report(request, report_name, username=None): if report_name == 'old': title = 'Packages last built more than two years ago' - cutoff = datetime.utcnow() - timedelta(days=365 * 2) + cutoff = utc_now() - timedelta(days=365 * 2) packages = packages.filter( build_date__lt=cutoff).order_by('build_date') elif report_name == 'long-out-of-date': title = 'Packages marked out-of-date more than 90 days ago' - cutoff = datetime.utcnow() - timedelta(days=90) + cutoff = utc_now() - timedelta(days=90) packages = packages.filter( flag_date__lt=cutoff).order_by('flag_date') elif report_name == 'big': @@ -1,10 +1,10 @@ +import hashlib import pytz from django.contrib.sites.models import Site from django.contrib.syndication.views import Feed from django.db.models import Q from django.utils.feedgenerator import Rss201rev2Feed -from django.utils.hashcompat import md5_constructor from django.views.decorators.http import condition from main.utils import retrieve_latest @@ -32,7 +32,7 @@ class GuidNotPermalinkFeed(Rss201rev2Feed): def package_etag(request, *args, **kwargs): latest = retrieve_latest(Package) if latest: - return md5_constructor(str(kwargs) + str(latest)).hexdigest() + return hashlib.md5(str(kwargs) + str(latest)).hexdigest() return None def package_last_modified(request, *args, **kwargs): @@ -108,7 +108,7 @@ class PackageFeed(Feed): def news_etag(request, *args, **kwargs): latest = retrieve_latest(News) if latest: - return md5_constructor(str(latest)).hexdigest() + return hashlib.md5(str(latest)).hexdigest() return None def news_last_modified(request, *args, **kwargs): diff --git a/main/migrations/0050_auto__chg_field_package_compressed_size__chg_field_package_installed_s.py b/main/migrations/0050_auto__chg_field_package_compressed_size__chg_field_package_installed_s.py index 7aa09596..8368ae2e 100644 --- a/main/migrations/0050_auto__chg_field_package_compressed_size__chg_field_package_installed_s.py +++ b/main/migrations/0050_auto__chg_field_package_compressed_size__chg_field_package_installed_s.py @@ -1,5 +1,6 @@ # encoding: utf-8 import datetime +from pytz import utc from south.db import db from south.v2 import SchemaMigration from django.db import models @@ -9,7 +10,9 @@ class Migration(SchemaMigration): def forwards(self, orm): db.alter_column('packages', 'compressed_size', self.gf('main.models.PositiveBigIntegerField')(default=0)) db.alter_column('packages', 'installed_size', self.gf('main.models.PositiveBigIntegerField')(default=0)) - db.alter_column('packages', 'last_update', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2000, 1, 1))) + old_date = datetime.datetime(2000, 1, 1) + old_date = old_date.replace(tzinfo=utc) + db.alter_column('packages', 'last_update', self.gf('django.db.models.fields.DateTimeField')(default=old_date)) def backwards(self, orm): db.alter_column('packages', 'compressed_size', self.gf('django.db.models.fields.BigIntegerField')(null=True)) diff --git a/main/migrations/0054_auto__add_field_donor_created.py b/main/migrations/0054_auto__add_field_donor_created.py index f4d5b157..c96c0f5d 100644 --- a/main/migrations/0054_auto__add_field_donor_created.py +++ b/main/migrations/0054_auto__add_field_donor_created.py @@ -1,5 +1,6 @@ # encoding: utf-8 import datetime +from pytz import utc from south.db import db from south.v2 import SchemaMigration from django.db import models @@ -8,7 +9,9 @@ class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'Donor.created' - db.add_column('donors', 'created', self.gf('django.db.models.fields.DateTimeField')(default=datetime.date(2000, 1, 1)), keep_default=False) + old_date = datetime.datetime(2000, 1, 1) + old_date = old_date.replace(tzinfo=utc) + db.add_column('donors', 'created', self.gf('django.db.models.fields.DateTimeField')(default=old_date), keep_default=False) def backwards(self, orm): diff --git a/main/models.py b/main/models.py index 4f2d64ea..7d017242 100644 --- a/main/models.py +++ b/main/models.py @@ -9,7 +9,7 @@ from django.contrib.auth.models import User from django.contrib.sites.models import Site from .fields import PositiveBigIntegerField, PGPKeyField -from .utils import cache_function, make_choice, set_created_field +from .utils import cache_function, make_choice, set_created_field, utc_now class UserProfile(models.Model): @@ -515,7 +515,7 @@ class TodolistPkg(models.Model): def set_todolist_fields(sender, **kwargs): todolist = kwargs['instance'] if not todolist.date_added: - todolist.date_added = datetime.utcnow() + todolist.date_added = utc_now() # connect signals needed to keep cache in line with reality from main.utils import refresh_latest diff --git a/main/utils.py b/main/utils.py index 81f689e7..e7e47c53 100644 --- a/main/utils.py +++ b/main/utils.py @@ -4,20 +4,24 @@ except ImportError: import pickle from datetime import datetime +import hashlib +from pytz import utc from django.core.cache import cache -from django.utils.hashcompat import md5_constructor + CACHE_TIMEOUT = 1800 INVALIDATE_TIMEOUT = 10 CACHE_LATEST_PREFIX = 'cache_latest_' + def cache_function_key(func, args, kwargs): raw = [func.__name__, func.__module__, args, kwargs] pickled = pickle.dumps(raw, protocol=pickle.HIGHEST_PROTOCOL) - key = md5_constructor(pickled).hexdigest() + key = hashlib.md5(pickled).hexdigest() return 'cache_function.' + func.__name__ + '.' + key + def cache_function(length): """ A variant of the snippet posted by Jeff Wheeler at @@ -43,6 +47,7 @@ def cache_function(length): return inner_func return decorator + def clear_cache_function(func, args, kwargs): key = cache_function_key(func, args, kwargs) cache.delete(key) @@ -50,6 +55,7 @@ def clear_cache_function(func, args, kwargs): # utility to make a pair of django choices make_choice = lambda l: [(str(m), str(m)) for m in l] + # These are in here because we would be jumping around in some import circles # and hoops otherwise. The only thing currently using these keys is the feed # caching stuff. @@ -65,6 +71,7 @@ def refresh_latest(**kwargs): # will be valid again. See "Scaling Django" by Mike Malone, slide 30. cache.set(cache_key, None, INVALIDATE_TIMEOUT) + def retrieve_latest(sender): # we could break this down based on the request url, but it would probably # cost us more in query time to do so. @@ -84,12 +91,19 @@ def retrieve_latest(sender): pass return None + +def utc_now(): + '''Returns a timezone-aware UTC date representing now.''' + return datetime.utcnow().replace(tzinfo=utc) + + def set_created_field(sender, **kwargs): - '''This will set the 'created' field on any object to datetime.utcnow() if - it is unset. For use as a pre_save signal handler.''' + '''This will set the 'created' field on any object to the current UTC time + if it is unset. For use as a pre_save signal handler.''' obj = kwargs['instance'] if hasattr(obj, 'created') and not obj.created: - obj.created = datetime.utcnow() + obj.created = utc_now() + def groupby_preserve_order(iterable, keyfunc): '''Take an iterable and regroup using keyfunc to determine whether items @@ -112,6 +126,7 @@ def groupby_preserve_order(iterable, keyfunc): 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.''' @@ -1,16 +1,12 @@ #!/usr/bin/env python2 +import os +import sys -from django.core.management import execute_manager +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") -try: - import settings # Assumed to be in the same directory. -except ImportError: - import sys - sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) - sys.exit(1) + from django.core.management import execute_from_command_line -if __name__ == "__main__": - execute_manager(settings) + execute_from_command_line(sys.argv) # vim: set ts=4 sw=4 et: - diff --git a/mirrors/management/commands/mirrorcheck.py b/mirrors/management/commands/mirrorcheck.py index 8eb8b010..c2928e67 100644 --- a/mirrors/management/commands/mirrorcheck.py +++ b/mirrors/management/commands/mirrorcheck.py @@ -21,9 +21,11 @@ import sys import time from threading import Thread import types +from pytz import utc from Queue import Queue, Empty import urllib2 +from main.utils import utc_now from mirrors.models import MirrorUrl, MirrorLog logging.basicConfig( @@ -50,7 +52,7 @@ class Command(NoArgsCommand): def check_mirror_url(mirror_url): url = mirror_url.url + 'lastsync' logger.info("checking URL %s", url) - log = MirrorLog(url=mirror_url, check_time=datetime.utcnow()) + log = MirrorLog(url=mirror_url, check_time=utc_now()) try: start = time.time() result = urllib2.urlopen(url, timeout=10) @@ -61,6 +63,7 @@ def check_mirror_url(mirror_url): parsed_time = None try: parsed_time = datetime.utcfromtimestamp(int(data)) + parsed_time = parsed_time.replace(tzinfo=utc) except ValueError: # it is bad news to try logging the lastsync value; # sometimes we get a crazy-encoded web page. diff --git a/mirrors/urls.py b/mirrors/urls.py index fed9c807..f002e9d6 100644 --- a/mirrors/urls.py +++ b/mirrors/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('mirrors.views', (r'^$', 'mirrors', {}, 'mirror-list'), diff --git a/mirrors/urls_mirrorlist.py b/mirrors/urls_mirrorlist.py index 70bc18d2..e0f44c78 100644 --- a/mirrors/urls_mirrorlist.py +++ b/mirrors/urls_mirrorlist.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('mirrors.views', (r'^$', 'generate_mirrorlist', {}, 'mirrorlist'), diff --git a/mirrors/utils.py b/mirrors/utils.py index f05ffc77..0f8fef84 100644 --- a/mirrors/utils.py +++ b/mirrors/utils.py @@ -1,11 +1,12 @@ +from datetime import timedelta + from django.db.models import Avg, Count, Max, Min, StdDev -from main.utils import cache_function +from main.utils import cache_function, utc_now from .models import MirrorLog, MirrorProtocol, MirrorUrl -import datetime -default_cutoff = datetime.timedelta(hours=24) +default_cutoff = timedelta(hours=24) def annotate_url(url, delays): '''Given a MirrorURL object, add a few more attributes to it regarding @@ -13,7 +14,7 @@ def annotate_url(url, delays): url.completion_pct = float(url.success_count) / url.check_count if url.id in delays: url_delays = delays[url.id] - url.delay = sum(url_delays, datetime.timedelta()) / len(url_delays) + url.delay = sum(url_delays, timedelta()) / len(url_delays) hours = url.delay.days * 24.0 + url.delay.seconds / 3600.0 if url.completion_pct > 0: @@ -28,7 +29,7 @@ def annotate_url(url, delays): @cache_function(123) def get_mirror_statuses(cutoff=default_cutoff): - cutoff_time = datetime.datetime.utcnow() - cutoff + cutoff_time = utc_now() - cutoff protocols = list(MirrorProtocol.objects.filter(is_download=True)) # I swear, this actually has decent performance... urls = MirrorUrl.objects.select_related('mirror', 'protocol').filter( @@ -82,7 +83,7 @@ def get_mirror_statuses(cutoff=default_cutoff): @cache_function(117) def get_mirror_errors(cutoff=default_cutoff): - cutoff_time = datetime.datetime.utcnow() - cutoff + cutoff_time = utc_now() - cutoff errors = MirrorLog.objects.filter( is_success=False, check_time__gte=cutoff_time, url__mirror__active=True, url__mirror__public=True).values( diff --git a/news/models.py b/news/models.py index 33d958e0..95026e1d 100644 --- a/news/models.py +++ b/news/models.py @@ -1,9 +1,10 @@ -from datetime import datetime - from django.db import models from django.contrib.auth.models import User from django.contrib.sites.models import Site +from main.utils import utc_now + + class News(models.Model): slug = models.SlugField(max_length=255, unique=True) author = models.ForeignKey(User, related_name='news_author', @@ -28,7 +29,7 @@ class News(models.Model): def set_news_fields(sender, **kwargs): news = kwargs['instance'] - now = datetime.utcnow() + now = utc_now() news.last_modified = now if not news.postdate: news.postdate = now diff --git a/news/urls.py b/news/urls.py index d938ef58..10020f31 100644 --- a/news/urls.py +++ b/news/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('news.views', (r'^$', 'news_list', {}, 'news-list'), diff --git a/packages/management/commands/signoff_report.py b/packages/management/commands/signoff_report.py index f822c8ad..70152cdb 100644 --- a/packages/management/commands/signoff_report.py +++ b/packages/management/commands/signoff_report.py @@ -17,12 +17,13 @@ from django.db.models import Count from django.template import loader, Context from collections import namedtuple -from datetime import datetime, timedelta +from datetime import timedelta import logging from operator import attrgetter import sys from main.models import Repo +from main.utils import utc_now from packages.models import Signoff from packages.utils import get_signoff_groups @@ -65,7 +66,7 @@ def generate_report(email, repo_name): new_hours = 24 old_days = 14 - now = datetime.utcnow() + now = utc_now() new_cutoff = now - timedelta(hours=new_hours) old_cutoff = now - timedelta(days=old_days) diff --git a/packages/migrations/0007_auto__add_field_packagerelation_created.py b/packages/migrations/0007_auto__add_field_packagerelation_created.py index 37321fdb..b030909e 100644 --- a/packages/migrations/0007_auto__add_field_packagerelation_created.py +++ b/packages/migrations/0007_auto__add_field_packagerelation_created.py @@ -1,5 +1,6 @@ # encoding: utf-8 import datetime +from pytz import utc from south.db import db from south.v2 import SchemaMigration from django.db import models @@ -7,7 +8,9 @@ from django.db import models class Migration(SchemaMigration): def forwards(self, orm): - db.add_column('packages_packagerelation', 'created', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.utcnow()), keep_default=False) + old_date = datetime.datetime(2000, 1, 1) + old_date = old_date.replace(tzinfo=utc) + db.add_column('packages_packagerelation', 'created', self.gf('django.db.models.fields.DateTimeField')(default=old_date), keep_default=False) def backwards(self, orm): db.delete_column('packages_packagerelation', 'created') diff --git a/packages/urls.py b/packages/urls.py index 4be56297..9a063f43 100644 --- a/packages/urls.py +++ b/packages/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import include, patterns +from django.conf.urls import include, patterns package_patterns = patterns('packages.views', (r'^$', 'details'), diff --git a/packages/urls_groups.py b/packages/urls_groups.py index d609944b..49ced145 100644 --- a/packages/urls_groups.py +++ b/packages/urls_groups.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('packages.views', (r'^$', 'groups', {}, 'groups-list'), diff --git a/packages/views/flag.py b/packages/views/flag.py index e87cef69..31eeda2d 100644 --- a/packages/views/flag.py +++ b/packages/views/flag.py @@ -1,5 +1,3 @@ -from datetime import datetime - from django import forms from django.conf import settings from django.contrib.auth.decorators import permission_required @@ -12,6 +10,7 @@ from django.views.decorators.cache import never_cache from ..models import FlagRequest from main.models import Package +from main.utils import utc_now def flaghelp(request): @@ -61,7 +60,7 @@ def flag(request, name, repo, arch): @transaction.commit_on_success def perform_updates(): - now = datetime.utcnow() + now = utc_now() pkgs.update(flag_date=now) # store our flag request flag_request = FlagRequest(created=now, diff --git a/packages/views/signoff.py b/packages/views/signoff.py index e3daf0dd..cf00b0b9 100644 --- a/packages/views/signoff.py +++ b/packages/views/signoff.py @@ -1,4 +1,3 @@ -from datetime import datetime from operator import attrgetter from django import forms @@ -13,6 +12,7 @@ from django.views.decorators.cache import never_cache from django.views.generic.simple import direct_to_template from main.models import Package, Arch, Repo +from main.utils import utc_now from ..models import SignoffSpecification, Signoff from ..utils import (get_signoff_groups, approved_by_signoffs, PackageSignoffGroup) @@ -45,7 +45,7 @@ def signoff_package(request, name, repo, arch, revoke=False): package, request.user, False) except Signoff.DoesNotExist: raise Http404 - signoff.revoked = datetime.utcnow() + signoff.revoked = utc_now() signoff.save() created = False else: diff --git a/releng/management/commands/syncisos.py b/releng/management/commands/syncisos.py index 270c6c34..62f005ff 100644 --- a/releng/management/commands/syncisos.py +++ b/releng/management/commands/syncisos.py @@ -1,4 +1,3 @@ -from datetime import datetime import re import urllib from HTMLParser import HTMLParser, HTMLParseError @@ -6,8 +5,10 @@ from HTMLParser import HTMLParser, HTMLParseError from django.conf import settings from django.core.management.base import BaseCommand, CommandError +from main.utils import utc_now from releng.models import Iso + class IsoListParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) @@ -53,7 +54,7 @@ class Command(BaseCommand): existing.active = True existing.removed = None existing.save() - now = datetime.utcnow() + now = utc_now() # and then mark all other names as no longer active Iso.objects.filter(active=True).exclude(name__in=active_isos).update( active=False, removed=now) diff --git a/releng/urls.py b/releng/urls.py index 239ad02b..8d1b8f24 100644 --- a/releng/urls.py +++ b/releng/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import include, patterns +from django.conf.urls import include, patterns feedback_patterns = patterns('releng.views', (r'^$', 'test_results_overview', {}, 'releng-test-overview'), diff --git a/requirements.txt b/requirements.txt index 2a159a9a..aa424ec7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -Django==1.3.1 +Django==1.4 Markdown>=2.1.1 -South>=0.7.3 +South>=0.7.4 pgpdump>=1.1 -pytz>=2011n +pytz>=2012b diff --git a/requirements_prod.txt b/requirements_prod.txt index 5870d42f..80fa2b5b 100644 --- a/requirements_prod.txt +++ b/requirements_prod.txt @@ -1,8 +1,8 @@ -Django==1.3.1 +Django==1.4 Markdown>=2.1.1 psycopg2 -South>=0.7.3 +South>=0.7.4 pgpdump>=1.1 pyinotify>=0.9.2 python-memcached>=1.48 -pytz>=2011n +pytz>=2012b diff --git a/settings.py b/settings.py index 44ee9255..41571f43 100644 --- a/settings.py +++ b/settings.py @@ -18,9 +18,13 @@ NOTIFICATIONS = ['dev@lists.parabolagnulinux.org'] # Full path to the data directory DEPLOY_PATH = os.path.dirname(os.path.realpath(__file__)) -# Local time zone for this installation. All choices can be found here: -# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE -TIME_ZONE = 'US/Eastern' +# If you set this to False, Django will not use timezone-aware datetimes. +USE_TZ = True + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +TIME_ZONE = 'UTC' # Language code for this installation. All choices can be found here: # http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes diff --git a/sitemaps.py b/sitemaps.py index 177555ff..8e9ba36f 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -1,4 +1,5 @@ from datetime import datetime, timedelta +from pytz import utc from django.contrib.sitemaps import Sitemap from django.core.urlresolvers import reverse @@ -62,7 +63,7 @@ class NewsSitemap(Sitemap): priority = "0.8" def __init__(self): - now = datetime.utcnow() + now = datetime.utcnow().replace(tzinfo=utc) self.one_day_ago = now - timedelta(days=1) self.one_week_ago = now - timedelta(days=7) diff --git a/templates/admin/index.html b/templates/admin/index.html index 1755d86f..203206d5 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -1,7 +1,7 @@ {% extends "admin/base_site.html" %} -{% load i18n %} +{% load i18n admin_static %} -{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% load adminmedia %}{% admin_media_prefix %}css/dashboard.css" />{% endblock %} +{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %} {% block coltype %}colMS{% endblock %} @@ -36,19 +36,19 @@ <caption><a href="{{ app.app_url }}" class="section">{% blocktrans with name=app.name %}{{ name }}{% endblocktrans %}</a></caption> {% for model in app.models %} <tr> - {% if model.perms.change %} + {% if model.admin_url %} <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th> {% else %} <th scope="row">{{ model.name }}</th> {% endif %} - {% if model.perms.add %} + {% if model.add_url %} <td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td> {% else %} <td> </td> {% endif %} - {% if model.perms.change %} + {% if model.admin_url %} <td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td> {% else %} <td> </td> diff --git a/templates/base.html b/templates/base.html index f5e8609a..6a874b78 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +{% load url from future %}<!DOCTYPE html> <html lang="en"> <head> <title>{% block title %}Parabola GNU/Linux-libre{% endblock %}</title> @@ -7,7 +7,7 @@ <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}archweb-print.css" media="print" /> <link rel="icon" type="image/x-icon" href="{{ STATIC_URL }}favicon.ico" /> <link rel="shortcut icon" type="image/x-icon" href="{{ STATIC_URL }}favicon.ico" /> - <link rel="search" type="application/opensearchdescription+xml" href="{% url opensearch-packages as osp %}{{ osp }}" title="Parabola Packages" /> + <link rel="search" type="application/opensearchdescription+xml" href="{% url 'opensearch-packages' as osp %}{{ osp }}" title="Parabola Packages" /> {% block head %}{% endblock %} </head> <body class="{% if user.is_authenticated %}devmode {% endif %}{% block bodyclass %}{% endblock %}"> @@ -21,7 +21,7 @@ <li id="anb-wiki"><a href="https://wiki.parabolagnulinux.org" title="Community documentation">Wiki</a></li> <li id="anb-bugs"><a href="https://labs.parabola.nu" title="Issue Tracker">Bugs</a></li> <li id="anb-projects"><a href="https://projects.parabolagnulinux.org" title="Our Code">Projects</a></li> - <li id="anb-download"><a href="https://wiki.parabolagnulinux.org/Download" title="Get Parabola">Download</a></li> + <li id="anb-download"><a href="{% url 'page-download' as pdl %}{{ pdl }}" title="Get Parabola">Download</a></li> </ul> </div> </div><!-- #archnavbar --> @@ -30,16 +30,18 @@ <div id="archdev-navbar"> {% if user.is_authenticated %} <ul> - <li><a href="/devel/" title="Developer Dashboard">Dashboard</a></li> - <li><a href="https://projects.parabolagnulinux.org/" title="Git Projects">Projects</a></li> - <li><a href="{% url news-list as newsl %}{{ newsl }}" title="Manage news articles">News</a></li> + <li><a href="{% url 'devel-index' %}" title="Developer Dashboard">Dashboard</a></li> + <li><a href="https://wiki.parabolagnulinux.org/DeveloperWiki" + title="Developer Wiki">DevWiki</a></li> + <li><a href="{% url 'news-list' as newsl %}{{ newsl }}" title="Manage news articles">News</a></li> <li><a href="/packages/signoffs/" title="Package signoffs">Signoffs</a></li> <li><a href="/todo/" title="Developer todo lists">Todos</a></li> - <li><a href="/packages/differences/" title="Package architecture differences">Architecture Differences</a></li> - <li><a href="https://lists.parabolagnulinux.org/pipermail/dev/" title="dev mailing list archives">Archives</a></li> - <li><a href="/devel/clock/" title="Developer world clocks">Dev Clocks</a></li> + <li><a href="{% url 'devel-clocks' %}" title="Developer world clocks">Dev Clocks</a></li> + <li><a href="https://lists.parabolagnulinux.org/pipermail/dev/" + title="dev mailing list archives">Archives</a></li> + <li><a href="/mirrors/" title="Mirror server statistics">Mirrors</a></li> {% if user.is_staff %} - <li><a href="{% url admin:index %}" title="Django Admin Interface">Django Admin</a></li> + <li><a href="{% url 'admin:index' %}" title="Django Admin Interface">Django Admin</a></li> {% endif %} <li><a href="/devel/profile/" title="Modify your account profile">Profile</a></li> <li><a href="/logout/" title="Logout of the developer interface">Logout</a></li> diff --git a/templates/devel/admin_log.html b/templates/devel/admin_log.html index 0f22ba2b..1629c104 100644 --- a/templates/devel/admin_log.html +++ b/templates/devel/admin_log.html @@ -1,7 +1,7 @@ {% extends "admin/base_site.html" %} -{% load i18n %} +{% load i18n admin_static %} -{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% load adminmedia %}{% admin_media_prefix %}css/dashboard.css" />{% endblock %} +{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="/admin/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %} diff --git a/templates/devel/clock.html b/templates/devel/clock.html index 06324d84..e8a7bf11 100644 --- a/templates/devel/clock.html +++ b/templates/devel/clock.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load tz %} {% block title %}Parabola GNU/Linux-libre - Hackers World Clocks{% endblock %} @@ -10,7 +11,6 @@ depends on hackers keeping the time zone information up to date, so if you see 'UTC' listed, pester them to update their settings.</p> <p> - Parabola Server Time: {{ now|date:"Y-m-d H:i T" }}<br/> UTC Time: {{ utc_now|date:"Y-m-d H:i T" }} </p> @@ -33,7 +33,7 @@ <td>{{ dev.userprofile.alias }}</td> <td>{{ dev.userprofile.location }}</td> <td>{{ dev.userprofile.time_zone }}</td> - <td>{{ dev.current_time|date:"Y-m-d H:i T" }}</td> + <td>{{ utc_now|timezone:dev.userprofile.time_zone|date:"Y-m-d H:i T" }}</td> </tr> {% endfor %} </tbody> diff --git a/templates/packages/search.html b/templates/packages/search.html index e4de5bb6..b344af1f 100644 --- a/templates/packages/search.html +++ b/templates/packages/search.html @@ -1,13 +1,13 @@ {% extends "base.html" %} {% load package_extras %} -{% load adminmedia %} +{% load admin_static %} {% block title %}Parabola - Package Database{% endblock %} {% block navbarclass %}anb-packages{% endblock %} {% block head %} {% if is_paginated and page_obj.number > 1 %}<meta name="robots" content="noindex, nofollow"/>{% endif %} -<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/widgets.css" /> +<link rel="stylesheet" type="text/css" href="{% static "admin/css/widgets.css" %}" /> {% endblock %} {% block content %} @@ -123,8 +123,12 @@ href="https://repo.parabolagnulinux.org/sources/packages" title="Sourceballed packages">sources repo</a>.</p> </div> +{% load cdn %}{% jquery %} <script type="text/javascript" src="/jsi18n/"></script> -<script type="text/javascript">window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";</script> -<script type="text/javascript" src="{% admin_media_prefix %}js/core.js"></script> +<script type="text/javascript"> + window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}"; + var django = {"jQuery": jQuery}; +</script> +<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script> {{search_form.media}} {% endblock %} diff --git a/templates/public/index.html b/templates/public/index.html index fa8bb8fb..73f48012 100644 --- a/templates/public/index.html +++ b/templates/public/index.html @@ -1,5 +1,6 @@ {% extends "base.html" %} {% load markup cache cdn %} +{% load url from future %} {% block head %} <link rel="alternate" type="application/rss+xml" title="Parabola News Updates" href="/feeds/news/" /> @@ -25,13 +26,13 @@ <p>You can find us on IRC at <a href="irc://irc.freenode.net/#parabola">irc.freenode.net/#parabola</a>.</p> - <p class="readmore"><a href="{% url page-about %}" + <p class="readmore"><a href="{% url 'page-about' %}" title="Learn more about Parabola">Learn more...</a></p> </div> <div id="news"> <h3> - <a href="{% url news-list %}" title="Browse the news archives">Latest News</a> + <a href="{% url 'news-list' %}" title="Browse the news archives">Latest News</a> <span class="arrow"></span> </h3> @@ -52,7 +53,7 @@ {% else %} {% if forloop.counter0 == 5 %} <h3> - <a href="{% url news-list %}" + <a href="{% url 'news-list' %}" title="Browse the news archives">Older News</a> <span class="arrow"></span> </h3> @@ -131,15 +132,15 @@ <h4>Support</h4> <ul> - <li><a href="{% url page-donate %}" title="Help support Parabola">Donate</a></li> + <li><a href="{% url 'page-donate' %}" title="Help support Parabola">Donate</a></li> </ul> <h4>Tools</h4> <ul> - <li><a href="{% url mirrorlist %}" + <li><a href="{% url 'mirrorlist' %}" title="Get a custom mirrorlist from our database">Mirrorlist Updater</a></li> - <li><a href="{% url mirror-status %}" + <li><a href="{% url 'mirror-status' %}" title="Check the status of all known mirrors">Mirror Status</a></li> <li><a href="/packages/differences/" title="See differences in packages between available architectures">Differences Reports</a> @@ -152,7 +153,7 @@ <li><a href="https://projects.parabolagnulinux.org" title="Official Parabola projects (git)">Projects in Git</a></li> {% comment %} - <li><a href="{% url page-svn %}" + <li><a href="{% url 'page-svn' %}" title="View SVN entries for packages">SVN Repositories</a></li> <li><a href="https://wiki.archlinux.org/index.php/DeveloperWiki" title="Developer Wiki articles">Developer Wiki</a></li> @@ -161,9 +162,9 @@ title="View the available package groups">Package Groups</a></li> <li><a href="/todolists/" title="Hacker Todo Lists">Todo Lists</a></li> - <li><a href="{% url releng-test-overview %}" + <li><a href="{% url 'releng-test-overview' %}" title="Releng Testbuild Feedback">Releng Testbuild Feedback</a></li> - <li><a href="{% url visualize-index %}" + <li><a href="{% url 'visualize-index' %}" title="View visualizations">Visualizations</a> <img width="16" height="16" src="{% cdnprefix %}/media/new.png" alt="New"/></li> </ul> @@ -171,16 +172,16 @@ <h4>More Resources</h4> <ul> - <li><a href="{% url page-keys %}" + <li><a href="{% url 'page-keys' %}" title="Package/Database signing master keys">Signing Master Keys</a> <img width="16" height="16" src="{% cdnprefix %}/media/new.png" alt="New"/></li> <li><a href="https://wiki.parabolagnulinux.org/Media" - title="Parabola in the media">Media Appearances</a></li> - <li><a href="{% url page-art %}" title="Parabola logos and other artwork for promotional use">Logos & Artwork</a></li> - <li><a href="{% url news-list %}" title="News Archives">News Archives</a></li> + title="Parabola in the media">Press Coverage</a></li> + <li><a href="{% url 'page-art' %}" title="Parabola logos and other artwork for promotional use">Logos & Artwork</a></li> + <li><a href="{% url 'news-list' %}" title="News Archives">News Archives</a></li> <li><a href="/feeds/" title="Various RSS Feeds">RSS Feeds</a></li> - <li><a href="{% url page-devs %}" title="Active hackers">Hackers Profiles</a></li> - <li><a href="{% url page-fellows %}" title="Retired hackers">Fellows Profiles</a></li> + <li><a href="{% url 'page-devs' %}" title="Active hackers">Hackers Profiles</a></li> + <li><a href="{% url 'page-fellows' %}" title="Retired hackers">Fellows Profiles</a></li> </ul> </div> diff --git a/templates/releng/add.html b/templates/releng/add.html index 402ceac6..9ceea66e 100644 --- a/templates/releng/add.html +++ b/templates/releng/add.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% block title %}Parabola - Test Result Entry{% endblock %} @@ -13,7 +14,7 @@ installation properly. Some options require you to check several things (such as config files), this will be mentioned alongside the option.</p> <p>There is also an overview of all feedback on the - <a href="{% url releng-test-overview %}">results page</a>. Once we have + <a href="{% url 'releng-test-overview' %}">results page</a>. Once we have builds that are properly tested (enough successful feedback for all important features of the ISO or a slightly earlier ISO), we can release new official media.</p> diff --git a/templates/releng/iso_overview.html b/templates/releng/iso_overview.html index 5a4445b7..76479c52 100644 --- a/templates/releng/iso_overview.html +++ b/templates/releng/iso_overview.html @@ -1,10 +1,11 @@ {% extends "base.html" %} +{% load url from future %} {% block content %} <div class="box"> <h2>Failures and Successes for Testing ISOs</h2> - <p><a href="{% url releng-test-overview %}">Go back to testing results</a></p> + <p><a href="{% url 'releng-test-overview' %}">Go back to testing results</a></p> <table id="releng-result" class="results"> <thead> diff --git a/templates/releng/result_list.html b/templates/releng/result_list.html index 512e1bf3..62264217 100644 --- a/templates/releng/result_list.html +++ b/templates/releng/result_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% block content %} <div class="box"> @@ -7,7 +8,7 @@ {{ iso_name|default:"" }} </h2> - <p><a href="{% url releng-test-overview %}">Go back to testing results</a></p> + <p><a href="{% url 'releng-test-overview' %}">Go back to testing results</a></p> <table id="releng-result" class="results"> <thead> diff --git a/templates/releng/result_section.html b/templates/releng/result_section.html index e9375cdd..45838b86 100644 --- a/templates/releng/result_section.html +++ b/templates/releng/result_section.html @@ -1,3 +1,4 @@ +{% load url from future %} <tr> <th>{% if option.is_rollback %}Rollback: {% endif %}{{ option.name|title }}</td> <th>Last Success</th> @@ -7,19 +8,20 @@ <tr> <td> <a href="{% url releng-results-for option.field_name item.value.pk %}"> + <a href="{% url 'releng-results-for' option.field_name item.value.pk %}"> {{ item.value.name|lower }} </a> </td> <td> {% if item.success %} - <a href="{% url releng-results-iso item.success.pk %}"> + <a href="{% url 'releng-results-iso' item.success.pk %}"> {{ item.success.name }} </a> {% else %}Never succeeded{% endif %} </td> <td> {% if item.failure %} - <a href="{% url releng-results-iso item.failure.pk %}"> + <a href="{% url 'releng-results-iso' item.failure.pk %}"> {{ item.failure.name }} </a> {% else %}Never failed{% endif %} diff --git a/templates/releng/results.html b/templates/releng/results.html index 6f7d29f0..fa694cc6 100644 --- a/templates/releng/results.html +++ b/templates/releng/results.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% block title %}Parabola - Release Engineering Testbuild Results{% endblock %} @@ -9,10 +10,17 @@ <p>This is an overview screen showing a test results matrix of release engineering produced ISOs. Various options and configurations are shown with last success and last failure results, if known. To help improve ISO - quality, you are encouraged to <a href="{% url releng-test-submit %}">give feedback</a> + quality, you are encouraged to <a href="{% url 'releng-test-submit' %}">give feedback</a> if you have tested and used any ISOs. Both successful and failed results are encouraged and welcome.</p> + <p>For a overview of which ISOs tested best, have a look at + the <a href="{% url 'releng-iso-overview' %}">overview</a>.</p> + + <p>For more information, see the <a + href="https://wiki.parabolagnulinux.org/DeveloperWiki:releng_testimages_feedback">documentation + on the wiki</a>.</p> + <p>All ISOs referenced on this page are available from <a href="{{ iso_url }}">{{ iso_url }}</a>.</p> diff --git a/templates/releng/thanks.html b/templates/releng/thanks.html index fdfc4c4a..8b204eaa 100644 --- a/templates/releng/thanks.html +++ b/templates/releng/thanks.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% block title %}Parabola - Feedback - Thanks!{% endblock %} @@ -7,9 +8,9 @@ <h2>Thanks!</h2> <p>Thank you for taking the time to give us this information! Your results have been succesfully added to our database.</p> - <p>You can now <a href="{% url releng-test-overview %}">go back to the results</a>, - <a href="{% url releng-test-submit %}">give more feedback</a>, or - have a look at the <a href="{% url releng-iso-overview %}">look at + <p>You can now <a href="{% url 'releng-test-overview' %}">go back to the results</a>, + <a href="{% url 'releng-test-submit' %}">give more feedback</a>, or + have a look at the <a href="{% url 'releng-iso-overview' %}">look at the ISO test overview</a>.</p> </div> {% endblock %} diff --git a/templates/visualize/index.html b/templates/visualize/index.html index 75194291..8855a713 100644 --- a/templates/visualize/index.html +++ b/templates/visualize/index.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% block title %}Parabola - Visualizations{% endblock %} @@ -34,11 +35,11 @@ <script type="text/javascript"> $(document).ready(function() { var orderings = { - "repo": { url: "{% url visualize-byrepo %}", color_attr: "repo" }, - "arch": { url: "{% url visualize-byarch %}", color_attr: "arch" }, + "repo": { url: "{% url 'visualize-byrepo' %}", color_attr: "repo" }, + "arch": { url: "{% url 'visualize-byarch' %}", color_attr: "arch" }, }; packages_treemap("#visualize-archrepo", orderings, "repo"); - developer_keys("#visualize-keys", "{% url visualize-pgp_keys %}"); + developer_keys("#visualize-keys", "{% url 'visualize-pgp_keys' %}"); }); </script> {% endblock %} diff --git a/todolists/urls.py b/todolists/urls.py index 0bd8817b..a379468f 100644 --- a/todolists/urls.py +++ b/todolists/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns from django.contrib.auth.decorators import permission_required from .views import DeleteTodolist @@ -1,7 +1,7 @@ import os.path # Stupid Django. Don't remove these "unused" handler imports -from django.conf.urls.defaults import handler500, handler404, include, patterns +from django.conf.urls import handler500, handler404, include, patterns from django.conf import settings from django.contrib import admin diff --git a/visualize/urls.py b/visualize/urls.py index 02d83bec..907f6a22 100644 --- a/visualize/urls.py +++ b/visualize/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns +from django.conf.urls import patterns urlpatterns = patterns('visualize.views', (r'^$', 'index', {}, 'visualize-index'), |