launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #04100
[Merge] lp:~jml/launchpad/utc-now into lp:launchpad
Jonathan Lange has proposed merging lp:~jml/launchpad/utc-now into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~jml/launchpad/utc-now/+merge/66437
Add a utc_now() helper and change many callsites to use it.
--
https://code.launchpad.net/~jml/launchpad/utc-now/+merge/66437
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jml/launchpad/utc-now into lp:launchpad.
=== modified file 'lib/canonical/launchpad/database/temporaryblobstorage.py'
--- lib/canonical/launchpad/database/temporaryblobstorage.py 2011-03-09 04:49:00 +0000
+++ lib/canonical/launchpad/database/temporaryblobstorage.py 2011-06-30 11:34:26 +0000
@@ -12,13 +12,9 @@
from cStringIO import StringIO
-from datetime import (
- datetime,
- timedelta,
- )
+from datetime import timedelta
import uuid
-from pytz import utc
from sqlobject import (
ForeignKey,
SQLObjectNotFound,
@@ -31,15 +27,14 @@
from canonical.database.constants import DEFAULT
from canonical.database.datetimecol import UtcDateTimeCol
from canonical.database.sqlbase import SQLBase
-from canonical.launchpad.database.librarian import LibraryFileAlias
from canonical.launchpad.interfaces.temporaryblobstorage import (
BlobTooLarge,
ITemporaryBlobStorage,
ITemporaryStorageManager,
)
from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
-from canonical.launchpad.interfaces.lpstorm import IStore
from lp.services.job.interfaces.job import JobStatus
+from lp.services.utils import utc_now
class TemporaryBlobStorage(SQLBase):
@@ -104,8 +99,7 @@
# A week might be quite a long time, but it shouldn't hurt,
# and it gives people enough time to create an account
# before accessing the uploaded blob.
- expires = (
- datetime.utcnow().replace(tzinfo=utc) + timedelta(weeks=1))
+ expires = utc_now() + timedelta(weeks=1)
# At this stage we could do some sort of throttling if we were
# concerned about abuse of the temporary storage facility. For
=== modified file 'lib/canonical/launchpad/scripts/ftests/librarianformatter.txt'
--- lib/canonical/launchpad/scripts/ftests/librarianformatter.txt 2010-12-22 14:50:08 +0000
+++ lib/canonical/launchpad/scripts/ftests/librarianformatter.txt 2011-06-30 11:34:26 +0000
@@ -36,6 +36,8 @@
>>> from canonical.testing.layers import LibrarianLayer
>>> LibrarianLayer.hide()
+>>> from lp.services.utils import utc_now
+
>>> normal_log, normal_out= make_logger(logging.Formatter)
>>> librarian_log, librarian_out = make_logger(LibrarianFormatter)
>>> import time
@@ -95,8 +97,7 @@
>>> from canonical.launchpad.database.librarian import LibraryFileAlias
>>> transaction.abort() # To see db changes made by the librarian
>>> alias = LibraryFileAlias.get(alias_id)
->>> now = datetime.now().replace(tzinfo=utc)
->>> alias.expires > now + timedelta(days=89)
+>>> alias.expires > utc_now() + timedelta(days=89)
True
Note that we also need to remain informative with dud exceptions, such as
=== modified file 'lib/canonical/launchpad/scripts/logger.py'
--- lib/canonical/launchpad/scripts/logger.py 2011-02-23 13:49:47 +0000
+++ lib/canonical/launchpad/scripts/logger.py 2011-06-30 11:34:26 +0000
@@ -34,7 +34,6 @@
from contextlib import contextmanager
from cStringIO import StringIO
from datetime import (
- datetime,
timedelta,
)
import hashlib
@@ -47,7 +46,6 @@
import time
from traceback import format_exception_only
-from pytz import utc
from zope.component import getUtility
from zope.exceptions.log import Formatter
@@ -61,7 +59,10 @@
UploadFailed,
)
from lp.services.log import loglevels
-from lp.services.utils import compress_hash
+from lp.services.utils import (
+ compress_hash,
+ utc_now,
+ )
# Reexport our custom loglevels for old callsites. These callsites
# should be importing the symbols from lp.services.log.loglevels
@@ -148,7 +149,7 @@
if not exception_string:
exception_string = ei[0].__name__
- expiry = datetime.now().replace(tzinfo=utc) + timedelta(days=90)
+ expiry = utc_now() + timedelta(days=90)
try:
filename = compress_hash(hashlib.sha1(traceback)) + '.txt'
url = librarian.remoteAddFile(
=== modified file 'lib/canonical/lazr/feed/feed.py'
--- lib/canonical/lazr/feed/feed.py 2010-11-08 12:52:43 +0000
+++ lib/canonical/lazr/feed/feed.py 2011-06-30 11:34:26 +0000
@@ -17,7 +17,6 @@
'MINUTES',
]
-from datetime import datetime
import operator
import os
import time
@@ -25,7 +24,6 @@
from xml.sax.saxutils import escape as xml_escape
from BeautifulSoup import BeautifulSoup
-import pytz
from z3c.ptcompat import ViewPageTemplateFile
from zope.component import getUtility
from zope.datetime import rfc1123_date
@@ -51,6 +49,7 @@
UnsupportedFeedFormat,
)
from lp.services.propertycache import cachedproperty
+from lp.services.utils import utc_now
SUPPORTED_FEEDS = ('.atom', '.html')
@@ -181,7 +180,7 @@
# datetime.isoformat() doesn't place the necessary "+00:00"
# for the feedvalidator's check of the iso8601 date format
# unless a timezone is specified with tzinfo.
- return datetime.utcnow().replace(tzinfo=pytz.utc)
+ return utc_now()
last_modified = sorted_items[0].last_modified
if last_modified is None:
raise AssertionError, 'All feed entries require a date updated.'
@@ -257,8 +256,6 @@
if authors is None:
authors = []
self.authors = authors
- if contributors is None:
- contribuors = []
self.contributors = contributors
if id_ is None:
self.id = self.construct_id()
=== modified file 'lib/canonical/librarian/ftests/test_gc.py'
--- lib/canonical/librarian/ftests/test_gc.py 2010-12-23 00:38:29 +0000
+++ lib/canonical/librarian/ftests/test_gc.py 2011-06-30 11:34:26 +0000
@@ -6,7 +6,7 @@
__metaclass__ = type
from cStringIO import StringIO
-from datetime import datetime, timedelta
+from datetime import timedelta
import os
import shutil
from subprocess import Popen, PIPE, STDOUT
@@ -14,7 +14,6 @@
import tempfile
from unittest import TestLoader
-from pytz import utc
from sqlobject import SQLObjectNotFound
import transaction
@@ -32,6 +31,7 @@
from canonical.librarian.client import LibrarianClient
from canonical.testing.layers import LaunchpadZopelessLayer
from lp.services.log.logger import BufferLogger
+from lp.services.utils import utc_now
from lp.testing import TestCase
@@ -52,12 +52,9 @@
# far enough so that how long it takes the test to run
# is not an issue. 'stay_of_excution - 1 hour' fits these
# criteria.
- self.recent_past = (
- datetime.utcnow().replace(tzinfo=utc)
- - timedelta(days=6, hours=23))
+ self.recent_past = utc_now() - timedelta(days=6, hours=23)
# A time beyond the stay of execution.
- self.ancient_past = (
- datetime.utcnow().replace(tzinfo=utc) - timedelta(days=30))
+ self.ancient_past = utc_now - timedelta(days=30)
self.f1_id, self.f2_id = self._makeDupes()
=== modified file 'lib/lp/app/browser/launchpad.py'
--- lib/lp/app/browser/launchpad.py 2011-06-27 15:36:25 +0000
+++ lib/lp/app/browser/launchpad.py 2011-06-30 11:34:26 +0000
@@ -24,7 +24,6 @@
import cgi
from datetime import (
- datetime,
timedelta,
)
import operator
@@ -43,7 +42,6 @@
from zope.datetime import (
DateTimeError,
parseDatetimetz,
- tzinfo,
)
from zope.i18nmessageid import Message
from zope.interface import implements
@@ -143,6 +141,7 @@
from lp.registry.interfaces.projectgroup import IProjectGroupSet
from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
from lp.services.propertycache import cachedproperty
+from lp.services.utils import utc_now
from lp.services.worlddata.interfaces.country import ICountrySet
from lp.services.worlddata.interfaces.language import ILanguageSet
from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
@@ -374,8 +373,7 @@
except DateTimeError:
# XXX SteveAlexander 2005-09-22: log a warning here.
return ''
- nowtz = datetime.utcnow().replace(tzinfo=tzinfo(0))
- timeleft = maintenancetime - nowtz
+ timeleft = maintenancetime - utc_now()
if timeleft > self.toomuchtime:
return ''
elif timeleft < self.notmuchtime:
=== modified file 'lib/lp/bugs/doc/bug-heat.txt'
--- lib/lp/bugs/doc/bug-heat.txt 2010-12-23 13:36:01 +0000
+++ lib/lp/bugs/doc/bug-heat.txt 2011-06-30 11:34:26 +0000
@@ -176,10 +176,11 @@
>>> from datetime import datetime, timedelta
>>> from pytz import timezone
+ >>> from lp.services.utils import utc_now
>>> from lp.bugs.adapters.bugchange import BugDescriptionChange
>>> change = BugDescriptionChange(
- ... when=datetime.now().replace(tzinfo=timezone('UTC')),
+ ... when=utc_now(),
... person=bug.owner, what_changed='description',
... old_value=bug.description, new_value='Some text')
>>> bug.addChange(change)
=== modified file 'lib/lp/registry/browser/tests/poll-views.txt'
--- lib/lp/registry/browser/tests/poll-views.txt 2011-01-05 19:18:57 +0000
+++ lib/lp/registry/browser/tests/poll-views.txt 2011-06-30 11:34:26 +0000
@@ -52,11 +52,10 @@
The portlet shows a link to polls to all users when there is a poll, but it
has not opened.
- >>> import pytz
- >>> from datetime import datetime, timedelta
>>> from lp.registry.interfaces.poll import IPollSubset, PollSecrecy
+ >>> from lp.services.utils import utc_now
- >>> open_date = datetime.now().replace(tzinfo=pytz.timezone('UTC'))
+ >>> open_date = utc_now()
>>> close_date = open_date + timedelta(weeks=1)
>>> poll_subset = IPollSubset(team)
>>> poll = poll_subset.new(
=== modified file 'lib/lp/registry/doc/announcement.txt'
--- lib/lp/registry/doc/announcement.txt 2011-05-27 19:53:20 +0000
+++ lib/lp/registry/doc/announcement.txt 2011-06-30 11:34:26 +0000
@@ -11,7 +11,8 @@
>>> from zope.component import getUtility
>>> from datetime import datetime, timedelta
>>> import pytz
- >>> NOW = datetime.utcnow().replace(tzinfo=pytz.utc)
+ >>> from lp.services.utils import utc_now
+ >>> NOW = utc_now()
>>> FUTURE = NOW + timedelta(days=10)
>>> from lp.registry.interfaces.announcement import IAnnouncementSet
>>> from lp.registry.interfaces.distribution import IDistributionSet
@@ -49,8 +50,6 @@
In this first example, we will specify a date and time the announcement was
published:
- >>> from datetime import datetime
- >>> import pytz
>>> apache_asia = apache.announce(
... mark,
... "OS Summit Asia 2007 - New Event by Apache and Eclipse",
=== modified file 'lib/lp/registry/model/announcement.py'
--- lib/lp/registry/model/announcement.py 2010-08-20 20:31:18 +0000
+++ lib/lp/registry/model/announcement.py 2011-06-30 11:34:26 +0000
@@ -11,9 +11,6 @@
'MakesAnnouncements',
]
-import datetime
-
-import pytz
from sqlobject import (
BoolCol,
ForeignKey,
@@ -36,6 +33,7 @@
from lp.registry.interfaces.person import validate_public_person
from lp.registry.interfaces.product import IProduct
from lp.registry.interfaces.projectgroup import IProjectGroup
+from lp.services.utils import utc_now
class Announcement(SQLBase):
@@ -125,8 +123,7 @@
"""See `IAnnouncement`."""
if self.date_announced is None:
return True
- return self.date_announced > \
- datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
+ return self.date_announced > utc_now()
@property
def published(self):
=== modified file 'lib/lp/services/tests/test_utils.py'
--- lib/lp/services/tests/test_utils.py 2011-03-31 05:12:09 +0000
+++ lib/lp/services/tests/test_utils.py 2011-06-30 11:34:26 +0000
@@ -6,11 +6,18 @@
__metaclass__ = type
from contextlib import contextmanager
+from datetime import datetime
import hashlib
import itertools
import os
import sys
+from pytz import UTC
+from testtools.matchers import (
+ GreaterThan,
+ LessThan,
+ )
+
from lp.services.utils import (
AutoDecorate,
base,
@@ -22,6 +29,7 @@
iter_split,
run_capturing_output,
traceback_info,
+ utc_now,
)
from lp.testing import TestCase
@@ -299,3 +307,21 @@
def test_is_not_upset_by_missing_directory(self):
self.assertFalse(
file_exists("a-nonexistent-directory/a-nonexistent-file.txt"))
+
+
+class TestUTCNow(TestCase):
+ """Tests for `utc_now`."""
+
+ def test_tzinfo(self):
+ # utc_now() returns a timezone-aware timestamp with the timezone of
+ # UTC.
+ now = utc_now()
+ self.assertEqual(now.tzinfo, UTC)
+
+ def test_time_is_now(self):
+ # utc_now() returns a timestamp which is now.
+ old_now = datetime.now().replace(tzinfo=UTC)
+ now = utc_now()
+ new_now = datetime.now().replace(tzinfo=UTC)
+ self.assertThat(now, GreaterThan(old_now))
+ self.assertThat(now, LessThan(new_now))
=== modified file 'lib/lp/services/utils.py'
--- lib/lp/services/utils.py 2011-06-28 23:43:37 +0000
+++ lib/lp/services/utils.py 2011-06-30 11:34:26 +0000
@@ -22,9 +22,11 @@
'synchronize',
'text_delta',
'traceback_info',
+ 'utc_now',
'value_string',
]
+from datetime import datetime
from itertools import tee
import os
from StringIO import StringIO
@@ -38,6 +40,7 @@
MonkeyPatch,
)
from lazr.enum import BaseItem
+import pytz
from twisted.python.util import mergeFunctionMetadata
from zope.security.proxy import isinstance as zope_isinstance
@@ -285,3 +288,8 @@
variables, and helps to avoid typos.
"""
sys._getframe(1).f_locals["__traceback_info__"] = info
+
+
+def utc_now():
+ """Return a timezone-aware timestamp for the current time."""
+ return datetime.now().replace(tzinfo=pytz.UTC)
=== modified file 'versions.cfg'
--- versions.cfg 2011-06-27 23:06:19 +0000
+++ versions.cfg 2011-06-30 11:34:26 +0000
@@ -75,7 +75,7 @@
soupmatchers = 0.1r53
sourcecodegen = 0.6.9
storm = 0.18.0.99-lpwithnodatetime-r393
-testtools = 0.9.11
+testtools = 0.9.12-r194
transaction = 1.0.0
Twisted = 11.0.0
uuid = 1.30