From 64e0e77605bf248f98a995bbe180ee092b590793 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 23 Sep 2013 12:44:53 +0200 Subject: [PATCH 1/3] [REL] saas-2 bzr revid: chs@openerp.com-20130923104453-051rjk47v54x2a3h --- openerp/release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/release.py b/openerp/release.py index 1ad35340496..af3d40bb090 100644 --- a/openerp/release.py +++ b/openerp/release.py @@ -30,7 +30,7 @@ RELEASE_LEVELS_DISPLAY = {ALPHA: ALPHA, # properly comparable using normal operarors, for example: # (6,1,0,'beta',0) < (6,1,0,'candidate',1) < (6,1,0,'candidate',2) # (6,1,0,'candidate',2) < (6,1,0,'final',0) < (6,1,2,'final',0) -version_info = (8, 0, 0, ALPHA, 1) +version_info = (7, 'saas~2', 0, FINAL, 0) version = '.'.join(map(str, version_info[:2])) + RELEASE_LEVELS_DISPLAY[version_info[3]] + str(version_info[4] or '') serie = major_version = '.'.join(map(str, version_info[:2])) From d4162cc0afee7805555f578beb1ddce0b838ed5d Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 24 Sep 2013 12:41:01 +0200 Subject: [PATCH 2/3] [FIX] @route compatibility with version 7.0: */ add request.debug property */ inject request at first argument at runtime, do not use wrapper method. */ force slashes in routes (do not use os.path.join() for urls) */ routes defined using the legacy decorator httprequest and jsonrequest uses auth="none" */ avoid registring web module routes twice bzr revid: chs@openerp.com-20130924104101-h1dexy6m74b56gvi --- addons/web/http.py | 54 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/addons/web/http.py b/addons/web/http.py index c8fabafd594..73e1843e401 100644 --- a/addons/web/http.py +++ b/addons/web/http.py @@ -177,6 +177,11 @@ class WebRequest(object): self.disable_db = True self.uid = None + @property + def debug(self): + return 'debug' in self.httprequest.args + + def auth_method_user(): request.uid = request.session.uid @@ -382,10 +387,10 @@ def jsonrequest(f): Use the ``route()`` decorator instead. """ f.combine = True - base = f.__name__ + base = f.__name__.lstrip('/') if f.__name__ == "index": base = "" - return route([base, os.path.join(base, "")], type="json", auth="user")(f) + return route([base, base + "/"], type="json", auth="none")(f) class HttpRequest(WebRequest): """ Regular GET/POST request @@ -460,10 +465,10 @@ def httprequest(f): Use the ``route()`` decorator instead. """ f.combine = True - base = f.__name__ + base = f.__name__.lstrip('/') if f.__name__ == "index": base = "" - return route([base, os.path.join(base, "")], type="http", auth="user")(f) + return route([base, base + "/"], type="http", auth="none")(f) #---------------------------------------------------------- # Local storage of requests @@ -496,16 +501,13 @@ class ControllerType(type): def __init__(cls, name, bases, attrs): super(ControllerType, cls).__init__(name, bases, attrs) - # create wrappers for old-style methods with req as first argument - cls._methods_wrapper = {} + # flag old-style methods with req as first argument for k, v in attrs.items(): if inspect.isfunction(v): spec = inspect.getargspec(v) first_arg = spec.args[1] if len(spec.args) >= 2 else None if first_arg in ["req", "request"]: - def build_new(nv): - return lambda self, *args, **kwargs: nv(self, request, *args, **kwargs) - cls._methods_wrapper[k] = build_new(v) + v._first_arg_is_req = True # store the controller in the controllers list name_class = ("%s.%s" % (cls.__module__, cls.__name__), cls) @@ -514,7 +516,6 @@ class ControllerType(type): return # we want to know all modules that have controllers module = class_path[2] - controllers_per_module.setdefault(module, []) # but we only store controllers directly inheriting from Controller if not "Controller" in globals() or not Controller in bases: return @@ -523,12 +524,6 @@ class ControllerType(type): class Controller(object): __metaclass__ = ControllerType - def get_wrapped_method(self, name): - if name in self.__class__._methods_wrapper: - return functools.partial(self.__class__._methods_wrapper[name], self) - else: - return getattr(self, name) - ############################# # OpenERP Sessions # ############################# @@ -991,8 +986,8 @@ class Root(object): cls = v[1] subclasses = cls.__subclasses__() - subclasses = [c for c in subclasses if c.__module__.split(".")[:2] == ["openerp", "addons"] and \ - cls.__module__.split(".")[2] in modules] + subclasses = [c for c in subclasses if c.__module__.startswith('openerp.addons.') and + c.__module__.split(".")[2] in modules] if subclasses: name = "%s (extended by %s)" % (cls.__name__, ', '.join(sub.__name__ for sub in subclasses)) cls = type(name, tuple(reversed(subclasses)), {}) @@ -1001,17 +996,15 @@ class Root(object): members = inspect.getmembers(o) for mk, mv in members: if inspect.ismethod(mv) and getattr(mv, 'exposed', False) and \ - nodb_only == (getattr(mv, "auth", None) == "none"): - function = (o.get_wrapped_method(mk), mv) + nodb_only == (getattr(mv, "auth", "none") == "none"): for url in mv.routes: if getattr(mv, "combine", False): - url = os.path.join(o._cp_path, url) + url = o._cp_path.rstrip('/') + '/' + url.lstrip('/') if url.endswith("/") and len(url) > 1: url = url[: -1] - routing_map.add(routing.Rule(url, endpoint=function)) + routing_map.add(routing.Rule(url, endpoint=mv)) - modules_set = set(controllers_per_module.keys()) - modules_set -= set("web") + modules_set = set(controllers_per_module.keys()) - set(['web']) # building all none methods gen(["web"] + sorted(modules_set), True) if not db: @@ -1020,12 +1013,12 @@ class Root(object): registry = openerp.modules.registry.RegistryManager.get(db) with registry.cursor() as cr: m = registry.get('ir.module.module') - ids = m.search(cr, openerp.SUPERUSER_ID, [('state','=','installed')]) + ids = m.search(cr, openerp.SUPERUSER_ID, [('state', '=', 'installed'), ('name', '!=', 'web')]) installed = set([x['name'] for x in m.read(cr, 1, ids, ['name'])]) modules_set = modules_set.intersection(set(installed)) modules = ["web"] + sorted(modules_set) # building all other methods - gen(["web"] + sorted(modules_set), False) + gen(modules, False) return routing_map @@ -1044,17 +1037,18 @@ class Root(object): """ path = request.httprequest.path urls = self.get_db_router(request.db).bind("") - matched, arguments = urls.match(path) + func, arguments = urls.match(path) arguments = dict([(k, v) for k, v in arguments.items() if not k.startswith("_ignored_")]) - func, original = matched def nfunc(*args, **kwargs): kwargs.update(arguments) + if getattr(func, '_first_arg_is_req', False): + args = (request,) + args return func(*args, **kwargs) request.func = nfunc - request.auth_method = getattr(original, "auth", "user") - request.func_request_type = original.exposed + request.auth_method = getattr(func, "auth", "user") + request.func_request_type = func.exposed root = None From 03ef8485d79e556cad2be91f79ccad316f967e48 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 30 Sep 2013 14:59:46 +0200 Subject: [PATCH 3/3] [FIX] orm: correct read_group when searching by month bzr revid: chs@openerp.com-20130930125946-exr791f83seaa9br --- openerp/osv/orm.py | 6 +++-- openerp/tests/test_orm.py | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 608b8043706..b5440c2be44 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -39,7 +39,6 @@ """ -import babel.dates import calendar import collections import copy @@ -54,6 +53,8 @@ import time import traceback import types +import babel.dates +import dateutil.parser import psycopg2 from lxml import etree @@ -2736,7 +2737,8 @@ class BaseModel(object): d['__context'] = {'group_by': groupby_list[1:]} if groupby and groupby in fget: if d[groupby] and fget[groupby]['type'] in ('date', 'datetime'): - groupby_datetime = datetime.datetime.strptime(alldata[d['id']][groupby], '%Y-%m-%d') + _default = datetime.datetime(1970, 1, 1) # force starts of month + groupby_datetime = dateutil.parser.parse(alldata[d['id']][groupby], default=_default) d[groupby] = babel.dates.format_date( groupby_datetime, format=group_by_params.get('display_format', 'MMMM yyyy'), locale=context.get('lang', 'en_US')) if group_by_params.get('interval') == 'month': diff --git a/openerp/tests/test_orm.py b/openerp/tests/test_orm.py index 91b2cb0f278..9e2a9c4a65f 100644 --- a/openerp/tests/test_orm.py +++ b/openerp/tests/test_orm.py @@ -1,3 +1,4 @@ +from collections import defaultdict from openerp.tools import mute_logger import common @@ -100,6 +101,57 @@ class TestORM(common.TransactionCase): found = self.partner.search_read(self.cr, UID, [['name', '=', 'Does not exists']], ['name']) self.assertEqual(len(found), 0) + def test_groupby_date(self): + partners = dict( + A='2012-11-19', + B='2012-12-17', + C='2012-12-31', + D='2013-01-07', + E='2013-01-14', + F='2013-01-28', + G='2013-02-11', + ) + + all_partners = [] + partners_by_day = defaultdict(set) + partners_by_month = defaultdict(set) + partners_by_year = defaultdict(set) + + for name, date in partners.items(): + p = self.partner.create(self.cr, UID, dict(name=name, date=date)) + all_partners.append(p) + partners_by_day[date].add(p) + partners_by_month[date.rsplit('-', 1)[0]].add(p) + partners_by_year[date.split('-', 1)[0]].add(p) + + def read_group(interval, domain=None): + main_domain = [('id', 'in', all_partners)] + if domain: + domain = ['&'] + main_domain + domain + else: + domain = main_domain + + display_format, groupby_format = { + 'year': ('YYYY', 'yyyy'), + 'month': ('YYYY-MM', 'yyyy-mm'), + 'day': ('yyyy-MM-dd', 'yyyy-mm-dd'), + }[interval] + + datetime_format = { + 'date': dict(interval=interval, display_format=display_format, groupby_format=groupby_format) + } + context = dict(datetime_format=datetime_format) + + rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date', context=context) + result = {} + for r in rg: + result[r['date']] = set(self.partner.search(self.cr, self.uid, r['__domain'])) + return result + + self.assertDictEqual(read_group('day'), partners_by_day) + self.assertDictEqual(read_group('month'), partners_by_month) + self.assertDictEqual(read_group('year'), partners_by_year) + class TestInherits(common.TransactionCase): """ test the behavior of the orm for models that use _inherits;