From d634fbd9ab432bf7bb35320fd044c0373ecfda2e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 1 Jun 2017 11:38:22 +0200 Subject: [PATCH] [FIX] P3: reorder finders in meta_path So that was a fun one: mock.patch calls would regularly fail refusing to find the addon in odoo.addon (e.g. essentially getattr(odoo.addon, 'account_budget' deep within the bowels of mock). Turns out the answer is that our import hooks would not be used for many imports: while in Python 2, sys.meta_path is empty and the default finders are run after all meta_path finders fail as noted by the documentation[0]. However when the import system was rewritten in Python 3.3[1] meta_path was "despecialised" and the default finders were moved to meta_path rather than be a hidden part of the import machinery[2]: > sys.meta_path and sys.path_hooks now store all of the meta path > finders and path entry hooks used by import. Previously the finders > were implicit and hidden within the C code of import instead of > being directly exposed. The result of this change is that ``sys.meta_path.append`` means the default finders should take priority and the custom ones should be fallback. This is the exact opposite of what we want. Fix issue by ``sys.meta_path.insert``-ing our finders at the start of the path rather than appending them at the end. This should change nothing in Python 2 but seems to fix the issue in P3. [0] https://docs.python.org/2/library/sys.html?highlight=meta_path#sys.meta_path [1] https://docs.python.org/3/whatsnew/3.3.html#importlib [2] https://docs.python.org/3/whatsnew/3.3.html#visible-changes --- odoo/modules/module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odoo/modules/module.py b/odoo/modules/module.py index e6194a5fb10..f0836cbe041 100644 --- a/odoo/modules/module.py +++ b/odoo/modules/module.py @@ -149,8 +149,8 @@ def initialize_sys_path(): ad_paths.append(ad) if not hooked: - sys.meta_path.append(AddonsHook()) - sys.meta_path.append(OdooHook()) + sys.meta_path.insert(0, OdooHook()) + sys.meta_path.insert(0, AddonsHook()) hooked = True def get_module_path(module, downloaded=False, display_warning=True):