summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Castiaux <juc@odoo.com>2019-09-09 16:10:13 +0000
committerXavier Morel <xmo@odoo.com>2019-09-20 05:58:16 +0000
commitd47083e6d219bdd2ca0e36a41aef5274f67a70f1 (patch)
tree14328a15f2a713c7de7e756c28ce1f28e0e7b6f5
parent18299d7e5051cdad29854bc7280db5002a209500 (diff)
[IMP] module.py: deprecate openerp
[PEP-594] is deprecating the `imp` module, that module is used in `module.py` in order to dynamically import addons using any of the `odoo.addons` or `openerp.addons` import anchor. We are deprecating `openerp` module/addons imports in v13 in order to remove the support in v14 and greatly simplify how modules/addons are loaded. If you are still using the old `import openerp` or `import openerp.addons`, `import odoo` and `import odoo.addons` are drop-in replacements. The `odoo.modules.module.ad_paths` addon paths list has been deprecated too. The list is now accessible on `odoo.addons.__path__` where they are now directly loaded [2]. See also: [PEP-594]: https://python.org/dev/peps/pep-0594/ [2]: https://packaging.python.org/guides/packaging-namespace-packages/ closes odoo/odoo#36597 Task: 2003936 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
-rw-r--r--addons/base_import_module/models/ir_module.py5
-rw-r--r--addons/transifex/models/ir_translation.py4
-rw-r--r--addons/web/controllers/main.py3
-rw-r--r--odoo/addons/base/models/ir_attachment.py3
-rw-r--r--odoo/cli/server.py2
-rw-r--r--odoo/http.py5
-rw-r--r--odoo/modules/module.py91
-rw-r--r--odoo/service/server.py4
-rw-r--r--odoo/tools/misc.py4
-rw-r--r--odoo/tools/translate.py2
10 files changed, 55 insertions, 68 deletions
diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py
index ce1499941a9..eda9562fd65 100644
--- a/addons/base_import_module/models/ir_module.py
+++ b/addons/base_import_module/models/ir_module.py
@@ -8,6 +8,7 @@ import sys
import zipfile
from os.path import join as opj
+import odoo
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.modules import load_information_from_description_file
@@ -125,7 +126,7 @@ class IrModule(models.Model):
with tempdir() as module_dir:
import odoo.modules.module as module
try:
- module.ad_paths.append(module_dir)
+ odoo.addons.__path__.append(module_dir)
z.extractall(module_dir)
dirs = [d for d in os.listdir(module_dir) if os.path.isdir(opj(module_dir, d))]
for mod_name in dirs:
@@ -139,7 +140,7 @@ class IrModule(models.Model):
_logger.exception('Error while importing module')
errors[mod_name] = exception_to_unicode(e)
finally:
- module.ad_paths.remove(module_dir)
+ odoo.addons.__path__.remove(module_dir)
r = ["Successfully imported module '%s'" % mod for mod in success]
for mod, error in errors.items():
r.append("Error while importing module '%s'.\n\n %s \n Make sure those modules are installed and try again." % (mod, error))
diff --git a/addons/transifex/models/ir_translation.py b/addons/transifex/models/ir_translation.py
index 6c9e84755d7..ed1150f8d14 100644
--- a/addons/transifex/models/ir_translation.py
+++ b/addons/transifex/models/ir_translation.py
@@ -10,8 +10,8 @@ from os.path import join as opj
import os
import werkzeug
+import odoo
from odoo import models, fields
-from odoo.modules.module import ad_paths
class IrTranslation(models.Model):
@@ -27,7 +27,7 @@ class IrTranslation(models.Model):
tx_config_file = ConfigParser()
tx_sections = []
- for addon_path in ad_paths:
+ for addon_path in odoo.addons.__path__:
tx_path = opj(addon_path, '.tx', 'config')
if os.path.isfile(tx_path):
tx_config_file.read(tx_path)
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index d893271ac6c..40f351e7f78 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1155,7 +1155,8 @@ class View(http.Controller):
class Binary(http.Controller):
def placeholder(self, image='placeholder.png'):
- return tools.file_open(get_resource_path('web', 'static/src/img', image), 'rb').read()
+ with tools.file_open(get_resource_path('web', 'static/src/img', image), 'rb') as fd:
+ return fd.read()
@http.route(['/web/content',
'/web/content/<string:xmlid>',
diff --git a/odoo/addons/base/models/ir_attachment.py b/odoo/addons/base/models/ir_attachment.py
index 7aae9cc5910..27b52033ab5 100644
--- a/odoo/addons/base/models/ir_attachment.py
+++ b/odoo/addons/base/models/ir_attachment.py
@@ -100,7 +100,8 @@ class IrAttachment(models.Model):
if bin_size:
r = human_size(os.path.getsize(full_path))
else:
- r = base64.b64encode(open(full_path,'rb').read())
+ with open(full_path,'rb') as fd:
+ r = base64.b64encode(fd.read())
except (IOError, OSError):
_logger.info("_read_file reading %s", full_path, exc_info=True)
return r
diff --git a/odoo/cli/server.py b/odoo/cli/server.py
index fcb7f2de700..f6214aaa6e7 100644
--- a/odoo/cli/server.py
+++ b/odoo/cli/server.py
@@ -59,7 +59,7 @@ def report_configuration():
_logger.info("Odoo version %s", __version__)
if os.path.isfile(config.rcfile):
_logger.info("Using configuration file at " + config.rcfile)
- _logger.info('addons paths: %s', odoo.modules.module.ad_paths)
+ _logger.info('addons paths: %s', odoo.addons.__path__)
if config.get('upgrades_paths'):
_logger.info('upgrades path: %s', config['upgrades_paths'])
host = config['db_host'] or os.environ.get('PGHOST', 'default')
diff --git a/odoo/http.py b/odoo/http.py
index a4c48f67795..e9e859db592 100644
--- a/odoo/http.py
+++ b/odoo/http.py
@@ -1300,14 +1300,15 @@ class Root(object):
controllers and configure them. """
# TODO should we move this to ir.http so that only configured modules are served ?
statics = {}
- for addons_path in odoo.modules.module.ad_paths:
+ for addons_path in odoo.addons.__path__:
for module in sorted(os.listdir(str(addons_path))):
if module not in addons_manifest:
mod_path = opj(addons_path, module)
manifest_path = module_manifest(mod_path)
path_static = opj(addons_path, module, 'static')
if manifest_path and os.path.isdir(path_static):
- manifest_data = open(manifest_path, 'rb').read()
+ with open(manifest_path, 'rb') as fd:
+ manifest_data = fd.read()
manifest = ast.literal_eval(pycompat.to_text(manifest_data))
if not manifest.get('installable', True):
continue
diff --git a/odoo/modules/module.py b/odoo/modules/module.py
index aef985230c8..b22a76e9630 100644
--- a/odoo/modules/module.py
+++ b/odoo/modules/module.py
@@ -31,60 +31,45 @@ README = ['README.rst', 'README.md', 'README.txt']
_logger = logging.getLogger(__name__)
# addons path as a list
-ad_paths = []
+# ad_paths is a deprecated alias, please use odoo.addons.__path__
+@tools.lazy
+def ad_paths():
+ _logger.warning('"odoo.modules.module.ad_paths" is a deprecated '
+ 'proxy to "odoo.addons.__path__". Please consider '
+ 'using the latter as the former is going to be '
+ 'removed in the next version.',
+ exc_info=DeprecationWarning(), stack_info=True)
+ return odoo.addons.__path__
hooked = False
# Modules already loaded
loaded = []
class AddonsHook(object):
- """ Makes modules accessible through openerp.addons.* and odoo.addons.* """
+ """ Makes modules accessible through openerp.addons.* """
def find_module(self, name, path=None):
- if name.startswith(('odoo.addons.', 'openerp.addons.'))\
- and name.count('.') == 2:
+ if name.startswith('openerp.addons.') and name.count('.') == 2:
+ _logger.warning('"openerp.addons" is a deprecated alias to '
+ '"odoo.addons". Please consider using the '
+ 'latter as the former is going to be removed '
+ 'in the next version.',
+ exc_info=DeprecationWarning(), stack_info=True)
return self
def load_module(self, name):
assert name not in sys.modules
- # get canonical names
odoo_name = re.sub(r'^openerp.addons.(\w+)$', r'odoo.addons.\g<1>', name)
- openerp_name = re.sub(r'^odoo.addons.(\w+)$', r'openerp.addons.\g<1>', odoo_name)
- assert odoo_name not in sys.modules
- assert openerp_name not in sys.modules
+ odoo_module = sys.modules.get(odoo_name)
+ if not odoo_module:
+ odoo_module = importlib.import_module(odoo_name)
- # get module name in addons paths
- _1, _2, addon_name = name.split('.')
- # load module
- f, path, (_suffix, _mode, type_) = imp.find_module(addon_name, ad_paths)
- if f: f.close()
+ sys.modules[name] = odoo_module
- # TODO: fetch existing module from sys.modules if reloads permitted
- # create empty odoo.addons.* module, set name
- new_mod = types.ModuleType(odoo_name)
- new_mod.__loader__ = self
+ return odoo_module
- # module top-level can only be a package
- assert type_ == imp.PKG_DIRECTORY, "Odoo addon top-level must be a package"
- modfile = opj(path, '__init__.py')
- new_mod.__file__ = modfile
- new_mod.__path__ = [path]
- new_mod.__package__ = odoo_name
-
- # both base and alias should be in sys.modules to handle recursive and
- # corecursive situations
- sys.modules[odoo_name] = sys.modules[openerp_name] = new_mod
-
- # execute source in context of module *after* putting everything in
- # sys.modules, so recursive import works
- exec(open(modfile, 'rb').read(), new_mod.__dict__)
-
- # people import openerp.addons and expect openerp.addons.<module> to work
- setattr(odoo.addons, addon_name, new_mod)
-
- return sys.modules[name]
# need to register loader with setuptools as Jinja relies on it when using
# PackageLoader
pkg_resources.register_loader_type(AddonsHook, pkg_resources.DefaultProvider)
@@ -96,6 +81,11 @@ class OdooHook(object):
# openerp.addons.<identifier> should already be matched by AddonsHook,
# only framework and subdirectories of modules should match
if re.match(r'^openerp\b', name):
+ _logger.warning('openerp is a deprecated alias to odoo. '
+ 'Please consider using the latter as the '
+ 'former is going to be removed in the next '
+ 'version.',
+ exc_info=DeprecationWarning(), stack_info=True)
return self
def load_module(self, name):
@@ -125,28 +115,21 @@ def initialize_sys_path():
``import odoo.addons.crm``) works even if the addons are not in the
PYTHONPATH.
"""
- global ad_paths
global hooked
dd = os.path.normcase(tools.config.addons_data_dir)
- if os.access(dd, os.R_OK) and dd not in ad_paths:
- ad_paths.append(dd)
+ if os.access(dd, os.R_OK) and dd not in odoo.addons.__path__:
+ odoo.addons.__path__.append(dd)
for ad in tools.config['addons_path'].split(','):
ad = os.path.normcase(os.path.abspath(tools.ustr(ad.strip())))
- if ad not in ad_paths:
- ad_paths.append(ad)
+ if ad not in odoo.addons.__path__:
+ odoo.addons.__path__.append(ad)
# add base module path
base_path = os.path.normcase(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons')))
- if base_path not in ad_paths and os.path.isdir(base_path):
- ad_paths.append(base_path)
-
- # add odoo.addons.__path__
- for ad in __import__('odoo.addons').addons.__path__:
- ad = os.path.abspath(ad)
- if ad not in ad_paths and os.path.isdir(ad):
- ad_paths.append(ad)
+ if base_path not in odoo.addons.__path__ and os.path.isdir(base_path):
+ odoo.addons.__path__.append(base_path)
if not hooked:
sys.meta_path.insert(0, OdooHook())
@@ -162,7 +145,7 @@ def get_module_path(module, downloaded=False, display_warning=True):
"""
initialize_sys_path()
- for adp in ad_paths:
+ for adp in odoo.addons.__path__:
files = [opj(adp, module, manifest) for manifest in MANIFEST_NAMES] +\
[opj(adp, module + '.zip')]
if any(os.path.exists(f) for f in files):
@@ -241,7 +224,7 @@ def get_resource_from_path(path):
:return: tuple(module_name, relative_path, os_relative_path) if possible, else None
"""
resource = False
- for adpath in ad_paths:
+ for adpath in odoo.addons.__path__:
# force trailing separator
adpath = os.path.join(adpath, "")
if os.path.commonprefix([adpath, path]) == adpath:
@@ -338,8 +321,8 @@ def load_information_from_description_file(module, mod_path=None):
readme_path = [opj(mod_path, x) for x in README
if os.path.isfile(opj(mod_path, x))]
if readme_path:
- readme_text = tools.file_open(readme_path[0]).read()
- info['description'] = readme_text
+ with tools.file_open(readme_path[0]) as fd:
+ info['description'] = fd.read()
# auto_install is set to `False` if disabled, and a set of
# auto_install dependencies otherwise. That way, we can set
@@ -418,7 +401,7 @@ def get_modules():
plist = []
initialize_sys_path()
- for ad in ad_paths:
+ for ad in odoo.addons.__path__:
plist.extend(listdir(ad))
return list(set(plist))
diff --git a/odoo/service/server.py b/odoo/service/server.py
index 574d569fbca..3cc2010c061 100644
--- a/odoo/service/server.py
+++ b/odoo/service/server.py
@@ -210,7 +210,7 @@ class FSWatcherBase(object):
class FSWatcherWatchdog(FSWatcherBase):
def __init__(self):
self.observer = Observer()
- for path in odoo.modules.module.ad_paths:
+ for path in odoo.addons.__path__:
_logger.info('Watching addons folder %s', path)
self.observer.schedule(self, path, recursive=True)
@@ -236,7 +236,7 @@ class FSWatcherInotify(FSWatcherBase):
inotify.adapters._LOGGER.setLevel(logging.ERROR)
# recreate a list as InotifyTrees' __init__ deletes the list's items
paths_to_watch = []
- for path in odoo.modules.module.ad_paths:
+ for path in odoo.addons.__path__:
paths_to_watch.append(path)
_logger.info('Watching addons folder %s', path)
self.watcher = InotifyTrees(paths_to_watch, mask=INOTIFY_LISTEN_EVENTS, block_duration_s=.5)
diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py
index 356e08db371..5715c9b83c6 100644
--- a/odoo/tools/misc.py
+++ b/odoo/tools/misc.py
@@ -157,7 +157,7 @@ def file_open(name, mode="r", subdir='addons', pathinfo=False):
@return fileobject if pathinfo is False else (fileobject, filepath)
"""
import odoo.modules as addons
- adps = addons.module.ad_paths
+ adps = odoo.addons.__path__
rtp = os.path.normcase(os.path.abspath(config['root_path']))
basename = name
@@ -205,7 +205,7 @@ def _fileopen(path, mode, basedir, pathinfo, basename=None):
name = os.path.normpath(os.path.normcase(os.path.join(basedir, path)))
import odoo.modules as addons
- paths = addons.module.ad_paths + [config['root_path']]
+ paths = odoo.addons.__path__ + [config['root_path']]
for addons_path in paths:
addons_path = os.path.normpath(os.path.normcase(addons_path)) + os.sep
if name.startswith(addons_path):
diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py
index 39edaee9423..761da202dc1 100644
--- a/odoo/tools/translate.py
+++ b/odoo/tools/translate.py
@@ -954,7 +954,7 @@ def trans_generate(lang, modules, cr):
for m in env['ir.module.module'].search_read([('state', '=', 'installed')], fields=['name'])
]
- path_list = [(path, True) for path in odoo.modules.module.ad_paths]
+ path_list = [(path, True) for path in odoo.addons.__path__]
# Also scan these non-addon paths
for bin_path in ['osv', 'report', 'modules', 'service', 'tools']:
path_list.append((os.path.join(config['root_path'], bin_path), True))