[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 <chs@odoo.com>
This commit is contained in:
Stéphane Bidoul (ACSONE)
2019-08-05 17:25:59 +00:00
parent 4f44ad4fe4
commit 795c7b0a94
4 changed files with 25 additions and 7 deletions
+1 -1
View File
@@ -11,6 +11,6 @@
'views/res_config_settings_views.xml',
],
'external_dependencies' : {
'python' : ['ldap'],
'python' : ['pyldap'],
}
}
+1 -1
View File
@@ -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,
}
+1 -1
View File
@@ -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,
}
+22 -4
View File
@@ -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: