Skip to content

Commit

Permalink
Added support for timezones (new in Django 1.4).
Browse files Browse the repository at this point in the history
From Django 1.4 onwards, settings.USE_TZ = True is the default for new
projects. It makes sense to run the tests with this setting.

Warnings related to time zones support are turned into exceptions to
make debugging easier and prevent regressions in this area.
  • Loading branch information
aaugustin authored and ojii committed Nov 9, 2012
1 parent ac7ae92 commit 9b82acd
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 15 deletions.
4 changes: 2 additions & 2 deletions cms/models/pagemodel.py
Expand Up @@ -6,9 +6,9 @@
from cms.models.pluginmodel import CMSPlugin
from cms.publisher.errors import MpttPublisherCantPublish
from cms.utils import i18n, urlutils, page as page_utils
from cms.utils import timezone
from cms.utils.copy_plugins import copy_plugins_to
from cms.utils.helpers import reversion_register
from datetime import datetime
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist
Expand Down Expand Up @@ -348,7 +348,7 @@ def save(self, no_signals=False, change_state=True, commit=True,

# if the page is published we set the publish date if not set yet.
if self.publication_date is None and self.published:
self.publication_date = datetime.now()
self.publication_date = timezone.now()

if self.reverse_id == "":
self.reverse_id = None
Expand Down
5 changes: 3 additions & 2 deletions cms/models/pluginmodel.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
import warnings
from datetime import datetime, date
from datetime import date

from django.conf import settings
from django.core.exceptions import ValidationError, ObjectDoesNotExist
Expand All @@ -14,6 +14,7 @@
from cms.models.placeholdermodel import Placeholder
from cms.plugin_rendering import PluginContext, render_plugin
from cms.utils.helpers import reversion_register
from cms.utils import timezone

from mptt.models import MPTTModel, MPTTModelBase

Expand Down Expand Up @@ -81,7 +82,7 @@ class CMSPlugin(MPTTModel):
position = models.PositiveSmallIntegerField(_("position"), blank=True, null=True, editable=False)
language = models.CharField(_("language"), max_length=15, blank=False, db_index=True, editable=False)
plugin_type = models.CharField(_("plugin_name"), max_length=50, db_index=True, editable=False)
creation_date = models.DateTimeField(_("creation date"), editable=False, default=datetime.now)
creation_date = models.DateTimeField(_("creation date"), editable=False, default=timezone.now)
changed_date = models.DateTimeField(auto_now=True)
level = models.PositiveIntegerField(db_index=True, editable=False)
lft = models.PositiveIntegerField(db_index=True, editable=False)
Expand Down
7 changes: 4 additions & 3 deletions cms/models/query.py
Expand Up @@ -5,6 +5,7 @@
from cms.publisher.query import PublisherQuerySet
from django.conf import settings
from cms.exceptions import NoHomeFound
from cms.utils import timezone

#from cms.utils.urlutils import levelize_path

Expand Down Expand Up @@ -53,21 +54,21 @@ def published(self, site=None):

if settings.CMS_SHOW_START_DATE:
pub = pub.filter(
Q(publication_date__lt=datetime.now()) |
Q(publication_date__lt=timezone.now()) |
Q(publication_date__isnull=True)
)

if settings.CMS_SHOW_END_DATE:
pub = pub.filter(
Q(publication_end_date__gte=datetime.now()) |
Q(publication_end_date__gte=timezone.now()) |
Q(publication_end_date__isnull=True)
)

return pub

def expired(self):
return self.on_site().filter(
publication_end_date__lte=datetime.now())
publication_end_date__lte=timezone.now())

# - seems this is not used anymore...
# def get_pages_with_application(self, path, language):
Expand Down
4 changes: 2 additions & 2 deletions cms/models/titlemodels.py
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from django.db import models
from django.utils.translation import ugettext_lazy as _
from cms.models.managers import TitleManager
from cms.models.pagemodel import Page
from cms.utils.helpers import reversion_register
from cms.utils import timezone


class Title(models.Model):
Expand All @@ -20,7 +20,7 @@ class Title(models.Model):
meta_keywords = models.CharField(_("keywords"), max_length=255, blank=True, null=True)
page_title = models.CharField(_("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)"))
page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set")
creation_date = models.DateTimeField(_("creation date"), editable=False, default=datetime.now)
creation_date = models.DateTimeField(_("creation date"), editable=False, default=timezone.now)

objects = TitleManager()

Expand Down
7 changes: 4 additions & 3 deletions cms/tests/page.py
Expand Up @@ -20,6 +20,7 @@
from cms.test_utils.util.context_managers import (LanguageOverride,
SettingsOverride)
from cms.utils.page_resolver import get_page_from_request, is_valid_url
from cms.utils import timezone
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.exceptions import ValidationError
Expand Down Expand Up @@ -367,7 +368,7 @@ def test_sitemap_login_required_pages(self):
self.assertEqual(CMSSitemap().items().count(),0)

def test_sitemap_includes_last_modification_date(self):
one_day_ago = datetime.datetime.now() - datetime.timedelta(days=1)
one_day_ago = timezone.now() - datetime.timedelta(days=1)
page = create_page("page", "nav_playground.html", "en", published=True, publication_date=one_day_ago)
page.creation_date = one_day_ago
page.save()
Expand All @@ -377,7 +378,7 @@ def test_sitemap_includes_last_modification_date(self):
self.assertTrue(actual_last_modification_time > one_day_ago)

def test_sitemap_uses_publication_date_when_later_than_modification(self):
now = datetime.datetime.now()
now = timezone.now()
one_day_ago = now - datetime.timedelta(days=1)
page = create_page("page", "nav_playground.html", "en", published=True, publication_date=now)
page.creation_date = one_day_ago
Expand Down Expand Up @@ -573,7 +574,7 @@ def test_page_already_expired(self):
Test that a page which has a end date in the past gives a 404, not a
500.
"""
yesterday = datetime.date.today() - datetime.timedelta(days=1)
yesterday = timezone.now() - datetime.timedelta(days=1)
with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
page = create_page('page', 'nav_playground.html', 'en',
publication_end_date=yesterday, published=True)
Expand Down
3 changes: 2 additions & 1 deletion cms/tests/plugins.py
Expand Up @@ -23,6 +23,7 @@
from cms.sitemaps.cms_sitemap import CMSSitemap
from cms.test_utils.util.context_managers import SettingsOverride
from cms.utils.copy_plugins import copy_plugins_to
from cms.utils import timezone
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
Expand Down Expand Up @@ -596,7 +597,7 @@ def test_empty_plugin_is_ignored(self):
self.assertFalse(len(placeholder._en_plugins_cache))

def test_editing_plugin_changes_page_modification_time_in_sitemap(self):
now = datetime.datetime.now()
now = timezone.now()
one_day_ago = now - datetime.timedelta(days=1)
page = create_page("page", "nav_playground.html", "en", published=True, publication_date=now)
page.creation_date = one_day_ago
Expand Down
3 changes: 2 additions & 1 deletion cms/utils/moderator.py
Expand Up @@ -3,6 +3,7 @@
from django.utils.translation import ugettext as _
from django.conf import settings
from cms.models import Page, PageModeratorState, PageModerator, CMSPlugin, Title
from cms.utils import timezone

I_APPROVE = 100 # current user should approve page
I_APPROVE_DELETE = 200
Expand Down Expand Up @@ -53,7 +54,7 @@ def update_moderation_message(page, message):

from cms.utils.permissions import get_current_user
user = get_current_user()
created = datetime.datetime.now() - datetime.timedelta(seconds=UPDATE_TOLERANCE)
created = timezone.now() - datetime.timedelta(seconds=UPDATE_TOLERANCE)
try:
state = page.pagemoderatorstate_set.filter(user=user, created__gt=created).order_by('-created')[0]
# just state without message!!
Expand Down
47 changes: 47 additions & 0 deletions cms/utils/timezone.py
@@ -0,0 +1,47 @@
# This file is a partial copy of django.utils.timezone as of Django 1.4.
# It must be removed as soon as django-cms drops support for Django 1.3.
# All imports of cms.utils.timezone must be replaced by django.utils.timezone.

from datetime import datetime, timedelta, tzinfo
from threading import local

try:
import pytz
except ImportError:
pytz = None

from django.conf import settings

ZERO = timedelta(0)

class UTC(tzinfo):
"""
UTC implementation taken from Python's docs.
Used only when pytz isn't available.
"""

def __repr__(self):
return "<UTC>"

def utcoffset(self, dt):
return ZERO

def tzname(self, dt):
return "UTC"

def dst(self, dt):
return ZERO

utc = pytz.utc if pytz else UTC()
"""UTC time zone as a tzinfo instance."""

def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
"""
if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower
return datetime.utcnow().replace(tzinfo=utc)
else:
return datetime.now()
9 changes: 8 additions & 1 deletion runtests.py
Expand Up @@ -2,8 +2,10 @@
from __future__ import with_statement
from cms.test_utils.cli import configure
from cms.test_utils.tmpdir import temp_dir
from django import VERSION
import argparse
import sys
import warnings


def main(test_runner='cms.test_utils.runners.NormalTestRunner', junit_output_dir='.',
Expand All @@ -12,9 +14,14 @@ def main(test_runner='cms.test_utils.runners.NormalTestRunner', junit_output_dir
test_labels = ['cms']
with temp_dir() as STATIC_ROOT:
with temp_dir() as MEDIA_ROOT:
# Test with time zone support enabled when it's available
use_tz = VERSION[:2] >= (1, 4)
warnings.filterwarnings(
'error', r"DateTimeField received a naive datetime",
RuntimeWarning, r'django\.db\.models\.fields')
configure(TEST_RUNNER=test_runner, JUNIT_OUTPUT_DIR=junit_output_dir,
TIME_TESTS=time_tests, ROOT_URLCONF='cms.test_utils.project.urls',
STATIC_ROOT=STATIC_ROOT, MEDIA_ROOT=MEDIA_ROOT)
STATIC_ROOT=STATIC_ROOT, MEDIA_ROOT=MEDIA_ROOT, USE_TZ=use_tz)
from django.conf import settings
from django.test.utils import get_runner
TestRunner = get_runner(settings)
Expand Down

0 comments on commit 9b82acd

Please sign in to comment.