diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 1c03a7ec5b6..d3e14d68ae1 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -7,7 +7,6 @@ import operator import os import time import datetime -import dateutil import pytz import openerp @@ -19,7 +18,7 @@ from openerp.osv import fields, osv from openerp.osv.orm import browse_record import openerp.report.interface from openerp.report.report_sxw import report_sxw, report_rml -from openerp.tools import ormcache +from openerp.tools import ormcache, wrap_module from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.translate import _ import openerp.workflow @@ -28,6 +27,16 @@ from openerp.exceptions import MissingError, UserError _logger = logging.getLogger(__name__) +# build dateutil helper, starting with the relevant *lazy* imports +import dateutil +import dateutil.parser +import dateutil.relativedelta +import dateutil.rrule +import dateutil.tz +mods = {'parser', 'relativedelta', 'rrule', 'tz'} +attribs = {atr for m in mods for atr in getattr(dateutil, m).__all__} +dateutil = wrap_module(dateutil, mods | attribs) + class actions(osv.osv): _name = 'ir.actions.actions' _table = 'ir_actions' diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index 74b89f1c2c1..c7cf97eba86 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -19,6 +19,7 @@ import socket import sys import threading import time +import types import werkzeug.utils import zipfile from cStringIO import StringIO @@ -1234,3 +1235,23 @@ class Pickle(object): dump = cPickle.dump pickle = Pickle + +def wrap_module(module, attr_list): + """Helper for wrapping a package/module to expose selected attributes + + :param Module module: the actual package/module to wrap, as returned by ``import `` + :param iterable attr_list: a global list of attributes to expose, usually the top-level + attributes and their own main attributes. No support for hiding attributes in case + of name collision at different levels. + """ + attr_list = set(attr_list) + class WrappedModule(object): + def __getattr__(self, attrib): + if attrib in attr_list: + target = getattr(module, attrib) + if isinstance(target, types.ModuleType): + return wrap_module(target, attr_list) + return target + raise AttributeError(attrib) + # module and attr_list are in the closure + return WrappedModule()