From 795c7b0a9415d04a777e1a5d48921adbd72f38cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Sat, 30 Jun 2018 09:41:31 +0000 Subject: [PATCH] [IMP] core: improve python external dependencies check Use pkg_resources.get_distribution() to check if python external dependencies are installed, instead of trying an import. The import test is preserved as a backwards compatibility measure. This better expresses which python distribution needs to be installed from PyPI and allows declaring a minimum supported version using PEP 440 version specifiers. Closes #25541 closes odoo/odoo#25549 Signed-off-by: Christophe Simonis --- addons/auth_ldap/__manifest__.py | 2 +- addons/hw_blackbox_be/__manifest__.py | 2 +- addons/hw_escpos/__manifest__.py | 2 +- odoo/addons/base/models/ir_module.py | 26 ++++++++++++++++++++++---- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/addons/auth_ldap/__manifest__.py b/addons/auth_ldap/__manifest__.py index 62fa393e24d..97bad615a50 100644 --- a/addons/auth_ldap/__manifest__.py +++ b/addons/auth_ldap/__manifest__.py @@ -11,6 +11,6 @@ 'views/res_config_settings_views.xml', ], 'external_dependencies' : { - 'python' : ['ldap'], + 'python' : ['pyldap'], } } diff --git a/addons/hw_blackbox_be/__manifest__.py b/addons/hw_blackbox_be/__manifest__.py index 56803a3af06..a88789d5299 100644 --- a/addons/hw_blackbox_be/__manifest__.py +++ b/addons/hw_blackbox_be/__manifest__.py @@ -19,6 +19,6 @@ Belgian cash register. It allows the communication on with a certified Fiscal Data Module but will not modify the behaviour of the Point of Sale. """, 'depends': ['hw_proxy'], - 'external_dependencies': {'python': ['serial']}, + 'external_dependencies': {'python': ['pyserial']}, 'installable': False, } diff --git a/addons/hw_escpos/__manifest__.py b/addons/hw_escpos/__manifest__.py index e51d811e745..b458ff33031 100644 --- a/addons/hw_escpos/__manifest__.py +++ b/addons/hw_escpos/__manifest__.py @@ -18,7 +18,7 @@ that would need such functionality. """, 'depends': ['hw_proxy'], 'external_dependencies': { - 'python' : ['usb.core','serial','qrcode'], + 'python' : ['pyusb','pyserial','qrcode'], }, 'installable': False, } diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index 883c8a43784..4d06d27d564 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -8,6 +8,7 @@ import importlib import io import logging import os +import pkg_resources import shutil import tempfile import zipfile @@ -307,16 +308,33 @@ class Module(models.Model): self.clear_caches() return super(Module, self).unlink() + @staticmethod + def _check_python_external_dependency(pydep): + try: + pkg_resources.get_distribution(pydep) + except pkg_resources.DistributionNotFound as e: + try: + importlib.import_module(pydep) + _logger.warning("python external dependency %s should be replaced by it's PyPI package name", pydep) + except ImportError: + # backward compatibility attempt failed + _logger.warning("DistributionNotFound: %s", e) + raise Exception('Python library not installed: %s' % (pydep,)) + except pkg_resources.VersionConflict as e: + _logger.warning("VersionConflict: %s", e) + raise Exception('Python library version conflict: %s' % (pydep,)) + except Exception as e: + _logger.warning("get_distribution(%s) failed: %s", pydep, e) + raise Exception('Error finding python library %s' % (pydep,)) + + @staticmethod def _check_external_dependencies(terp): depends = terp.get('external_dependencies') if not depends: return for pydep in depends.get('python', []): - try: - importlib.import_module(pydep) - except ImportError: - raise ImportError('No module named %s' % (pydep,)) + Module._check_python_external_dependency(pydep) for binary in depends.get('bin', []): try: