[MERGE] Use of the new fields.date.context_today method for bug 925361
authorOlivier Dony <odo@openerp.com>
Mon, 13 Feb 2012 18:48:53 +0000 (19:48 +0100)
committerOlivier Dony <odo@openerp.com>
Mon, 13 Feb 2012 18:48:53 +0000 (19:48 +0100)
lp bug: https://launchpad.net/bugs/925361 fixed

bzr revid: odo@openerp.com-20120213184853-uoyo7utrnvlh1zoa

openerp/addons/base/res/res_users.py
openerp/osv/fields.py

index dbdd186..f148813 100644 (file)
@@ -474,23 +474,40 @@ class users(osv.osv):
             return False
         cr = pooler.get_db(db).cursor()
         try:
-            # We autocommit: our single request will be performed atomically.
+            # autocommit: our single request will be performed atomically.
             # (In this way, there is no opportunity to have two transactions
-            # interleaving ther cr.execute()..cr.commit() calls and have one
-            # of them rollbacked due to a concurrent access.)
+            # interleaving their cr.execute()..cr.commit() calls and have one
+            # of them rolled back due to a concurrent access.)
             # We effectively unconditionally write the res_users line.
             cr.autocommit(True)
+            # Even w/ autocommit there's a chance the user row will be locked,
+            # in which case we can't delay the login just for the purpose of
+            # update the last login date - hence we use FOR UPDATE NOWAIT to
+            # try to get the lock - fail-fast
+            cr.execute("""SELECT id from res_users
+                          WHERE login=%s AND password=%s
+                                AND active FOR UPDATE NOWAIT""",
+                       (tools.ustr(login), tools.ustr(password)))
             cr.execute("""UPDATE res_users
                             SET date = now() AT TIME ZONE 'UTC'
-                            WHERE login=%s AND password=%s AND active RETURNING id""",
+                            WHERE login=%s AND password=%s AND active
+                            RETURNING id""",
+                       (tools.ustr(login), tools.ustr(password)))
+        except Exception:
+            # Failing to acquire the lock on the res_users row probably means
+            # another request is holding it. No big deal, we don't want to
+            # prevent/delay login in that case. It will also have been logged
+            # as a SQL error, if anyone cares.
+            cr.execute("""SELECT id from res_users
+                          WHERE login=%s AND password=%s
+                                AND active""",
                        (tools.ustr(login), tools.ustr(password)))
+        finally:
             res = cr.fetchone()
+            cr.close()
             if res:
                 return res[0]
-            else:
-                return False
-        finally:
-            cr.close()
+        return False
 
     def check_super(self, passwd):
         if passwd == tools.config['admin_passwd']:
index 3e6f07c..94b638e 100644 (file)
 import base64
 import datetime as DT
 import logging
+import pytz
 import re
-import string
-import sys
 import xmlrpclib
 from psycopg2 import Binary
 
 import openerp
-import openerp.netsvc as netsvc
 import openerp.tools as tools
 from openerp.tools.translate import _
 from openerp.tools import float_round, float_repr
@@ -262,6 +260,7 @@ class float(_column):
 
 class date(_column):
     _type = 'date'
+
     @staticmethod
     def today(*args):
         """ Returns the current date in a format fit for being a
@@ -273,6 +272,28 @@ class date(_column):
         return DT.date.today().strftime(
             tools.DEFAULT_SERVER_DATE_FORMAT)
 
+    @staticmethod
+    def context_today(cr, uid, today=None, context=None):
+        """Returns the current date as seen in the client's timezone
+           in a format fit for date fields.
+           This method may be passed as value to initialize _defaults.
+
+           :param datetime today: optional date value to use instead of
+                                  the current date"""
+        today = DT.datetime.now()
+        context_today = None
+        if context and context.get('tz'):
+            try:
+                utc = pytz.timezone('UTC')
+                context_tz = pytz.timezone(context['tz'])
+                utc_today = utc.localize(today, is_dst=False)
+                context_today = utc_today.astimezone(context_tz)
+            except Exception:
+                _logger.debug("failed to compute context/client-specific today date, "
+                              "using the UTC value for `today`",
+                              exc_info=True)
+        return (context_today or today).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
+
 class datetime(_column):
     _type = 'datetime'
     @staticmethod