Browse Source

Use utc datetime object (with explicit tzinfo) on the ISP object

Gu1 11 years ago
parent
commit
052f3f6009

+ 3 - 3
ffdnispdb/crawler.py

@@ -10,7 +10,7 @@ import requests
 
 from ispformat.validator import validate_isp
 from .models import ISP
-from .utils import dict_to_geojson
+from .utils import dict_to_geojson, utcnow
 from . import db
 
 
@@ -357,8 +357,8 @@ class PrettyValidator(Crawler):
         self.session[self.sesskey]['validated']=True
         self.session[self.sesskey]['jdict']=self.jdict
         self.session[self.sesskey]['cache_info']=self.cache_info
-        self.session[self.sesskey]['last_update']=datetime.now()
-        self.session[self.sesskey]['next_update']=datetime.now()+timedelta(seconds=self.jdict_max_age)
+        self.session[self.sesskey]['last_update']=utcnow()
+        self.session[self.sesskey]['next_update']=utcnow()+timedelta(seconds=self.jdict_max_age)
         self.session.save()
 
 

+ 8 - 8
ffdnispdb/cron_task.py

@@ -11,7 +11,7 @@ import itsdangerous
 
 from ffdnispdb.crawler import TextValidator
 from ffdnispdb.models import ISP
-from ffdnispdb import create_app, db, mail
+from ffdnispdb import create_app, db, mail, utils
 
 
 app=create_app({
@@ -95,17 +95,17 @@ app.app_context().push()
 try:
     for isp in ISP.query.filter(ISP.is_disabled == False,
                                 ISP.json_url != None,
-                                ISP.next_update < datetime.now(),
+                                ISP.next_update < utils.utcnow(),
                                 ISP.update_error_strike < 3)\
                         .order_by(ISP.last_update_success):
         try:
             print u'%s: Attempting to update %s'%(datetime.now(), isp)
-            print u'    last successful update=%s'%(isp.last_update_success)
-            print u'    last update attempt=%s'%(isp.last_update_attempt)
-            print u'    next update was scheduled %s ago'%(datetime.now()-isp.next_update)
+            print u'    last successful update=%s'%(utils.tosystemtz(isp.last_update_success))
+            print u'    last update attempt=%s'%(utils.tosystemtz(isp.last_update_attempt))
+            print u'    next update was scheduled %s ago'%(utils.utcnow()-isp.next_update)
             print u'    strike=%d'%(isp.update_error_strike)
 
-            isp.last_update_attempt=datetime.now()
+            isp.last_update_attempt=utils.utcnow()
             db.session.add(isp)
             db.session.commit()
 
@@ -115,7 +115,7 @@ try:
                 isp.update_error_strike += 1
                 # reset cache info (to force refetch next time)
                 isp.cache_info = {}
-                isp.next_update = datetime.now()+timedelta(seconds=validator.jdict_max_age)
+                isp.next_update = utils.utcnow()+timedelta(seconds=validator.jdict_max_age)
                 db.session.add(isp)
                 db.session.commit()
                 print u'%s: Error while updating:'%(datetime.now())
@@ -131,7 +131,7 @@ try:
             isp.cache_info = validator.cache_info
             isp.last_update_success = isp.last_update_attempt
             isp.update_error_strike = 0
-            isp.next_update = datetime.now()+timedelta(seconds=validator.jdict_max_age)
+            isp.next_update = utils.utcnow()+timedelta(seconds=validator.jdict_max_age)
             db.session.add(isp)
             db.session.commit()
 

+ 1 - 0
ffdnispdb/default_settings.py

@@ -4,6 +4,7 @@ SQLALCHEMY_DATABASE_URI = 'sqlite:///../ffdn-db.sqlite'
 CRAWLER_MIN_CACHE_TIME = 60*60 # 1 hour
 CRAWLER_MAX_CACHE_TIME = 60*60*24*14 # 2 week
 CRAWLER_DEFAULT_CACHE_TIME = 60*60*12 # 12 hours
+SYSTEM_TIME_ZONE='Europe/Paris'
 LANGUAGES = {
     'en': 'English',
     'fr': 'Français',

+ 21 - 5
ffdnispdb/models.py

@@ -5,11 +5,12 @@ import json
 import os
 import itertools
 from datetime import datetime
+import pytz
 from . import db
-from .utils import dict_to_geojson
+from .utils import dict_to_geojson, utcnow
 from flask import current_app
 import flask_sqlalchemy
-from sqlalchemy.types import TypeDecorator, VARCHAR
+from sqlalchemy.types import TypeDecorator, VARCHAR, DateTime
 from sqlalchemy.ext.mutable import MutableDict
 from sqlalchemy import event
 import geoalchemy as geo
@@ -46,6 +47,21 @@ class JSONEncodedDict(TypeDecorator):
         return value
 
 
+class UTCDateTime(TypeDecorator):
+
+    impl = DateTime
+
+    def process_bind_param(self, value, engine):
+        if value is not None:
+            return value.astimezone(pytz.utc)
+
+    def process_result_value(self, value, engine):
+        if value is not None:
+            return datetime(value.year, value.month, value.day,
+                            value.hour, value.minute, value.second,
+                            value.microsecond, tzinfo=pytz.utc)
+
+
 class ISP(db.Model):
     __tablename__ = 'isp'
     id = db.Column(db.Integer, primary_key=True)
@@ -54,10 +70,10 @@ class ISP(db.Model):
     is_ffdn_member = db.Column(db.Boolean, default=False)
     is_disabled = db.Column(db.Boolean, default=False) # True = ISP will not appear
     json_url = db.Column(db.String)
-    last_update_success = db.Column(db.DateTime)
-    last_update_attempt = db.Column(db.DateTime)
+    last_update_success = db.Column(UTCDateTime)
+    last_update_attempt = db.Column(UTCDateTime)
     update_error_strike = db.Column(db.Integer, default=0) # if >= 3; then updates are disabled
-    next_update = db.Column(db.DateTime, default=datetime.now())
+    next_update = db.Column(UTCDateTime, default=utcnow)
     tech_email = db.Column(db.String)
     cache_info = db.Column(MutableDict.as_mutable(JSONEncodedDict))
     json = db.Column(MutableDict.as_mutable(JSONEncodedDict))

+ 4 - 4
ffdnispdb/sessions.py

@@ -30,7 +30,7 @@ class SQLSession(CallbackDict, SessionMixin):
         if self.new:
             self.db.execute(self.table.insert({
                 'session_id': self.sid,
-                'expire': datetime.now()+timedelta(hours=1),
+                'expire': datetime.utcnow()+timedelta(hours=1),
                 'value': cPickle.dumps(dict(self), -1)
             }))
             self.new=False
@@ -38,7 +38,7 @@ class SQLSession(CallbackDict, SessionMixin):
             self.db.execute(self.table.update(
                 self.table.c.session_id == self.sid,
                 {
-                    'expire': datetime.now()+timedelta(hours=1),
+                    'expire': datetime.utcnow()+timedelta(hours=1),
                     'value': cPickle.dumps(dict(self), -1)
                 }
             ))
@@ -58,7 +58,7 @@ class MySessionInterface(SessionInterface):
         sid = request.cookies.get(app.session_cookie_name)
         if sid:
             res=self.db.engine.execute(select([self.table.c.value], (self.table.c.session_id == sid) &
-                                                                 (self.table.c.expire > datetime.now()))).first()
+                                                                 (self.table.c.expire > datetime.utcnow()))).first()
             if res:
                 return SQLSession(sid, self.db.engine, self.table, False, cPickle.loads(res[0]))
 
@@ -76,7 +76,7 @@ class MySessionInterface(SessionInterface):
 
         # remove expired sessions.. or maybe not
         if randrange(20) % 20 == 0:
-            self.db.engine.execute(self.table.delete(self.table.c.expire <= datetime.now()))
+            self.db.engine.execute(self.table.delete(self.table.c.expire <= datetime.utcnow()))
 
         response.set_cookie(app.session_cookie_name, session.sid,
                             expires=self.get_expiration_time(app, session),

+ 16 - 0
ffdnispdb/utils.py

@@ -1,6 +1,9 @@
 # -*- coding: utf-8 -*-
 
+from flask import current_app
 from collections import OrderedDict
+from datetime import datetime
+import pytz
 import json
 
 
@@ -26,3 +29,16 @@ def dict_to_geojson(d_in):
 
     return json.dumps(d)
 
+
+def utcnow():
+    """
+    Return the current UTC date and time as a datetime object with proper tzinfo.
+    """
+    return datetime.utcnow().replace(tzinfo=pytz.utc)
+
+
+def tosystemtz(d):
+    """
+    Convert the UTC datetime ``d`` to the system time zone as defined in the config
+    """
+    return d.astimezone(pytz.timezone(current_app.config['SYSTEM_TIME_ZONE']))

+ 1 - 2
ffdnispdb/views.py

@@ -122,7 +122,6 @@ def edit_project(projectid):
     sess_token=session.get('edit_tokens', {}).get(isp.id)
 
     if 'token' in request.args:
-        print session
         s = itsdangerous.URLSafeTimedSerializer(current_app.secret_key, salt='edit')
         try:
             r = s.loads(request.args['token'], max_age=MAX_TOKEN_AGE,
@@ -341,7 +340,7 @@ def reactivate_isp(projectid):
         p=ISP.query.get(session['form_reactivate']['isp_id'])
         p.json=session['form_reactivate']['jdict']
         p.cache_info=session['form_reactivate']['cache_info']
-        p.last_update_attempt=datetime.now()
+        p.last_update_attempt=session['form_form_reactivate']['last_update']
         p.last_update_success=p.last_update_attempt
 
         db.session.add(p)