From 7bc3f11a2b98d717a7e460f63b1bb90b008eb1c1 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Thu, 10 Aug 2023 09:20:02 -0300 Subject: [PATCH] [Dep Downloader] Added support for PEP668 compliant Debian pip --- kibot/dep_downloader.py | 41 ++++++++++++++++---------- tests/test_plot/test_dep_downloader.py | 3 +- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/kibot/dep_downloader.py b/kibot/dep_downloader.py index 9efb107d..68ad28f0 100644 --- a/kibot/dep_downloader.py +++ b/kibot/dep_downloader.py @@ -294,7 +294,7 @@ def check_pip(): def pip_install(pip_command, dest=None, name='.'): - cmd = [pip_command, 'install', '-U', '--no-warn-script-location'] + cmd = [pip_command, 'install', '-U', '--user', '--no-warn-script-location'] if name == '.': # Applied only when installing a downloaded tarball # This is what --user means, but Debian's pip installs to /usr/local when used by root @@ -302,20 +302,28 @@ def pip_install(pip_command, dest=None, name='.'): # If we have an older version installed don't remove it '--ignore-installed']) cmd.append(name) - logger.debug('- Running: {}'.format(cmd)) - try: - res_run = subprocess.run(cmd, check=True, capture_output=True, cwd=dest) - logger.debugl(3, '- Output from pip:\n'+res_run.stdout.decode()) - except subprocess.CalledProcessError as e: - logger.debug('- Failed to install `{}` using pip (cmd: {} code: {})'.format(name, e.cmd, e.returncode)) - if e.output: - logger.debug('- Output from command: '+e.output.decode()) - if e.stderr: - logger.debug('- StdErr from command: '+e.stderr.decode()) - return False - except Exception as e: - logger.debug('- Failed to install `{}` using pip ({})'.format(name, e)) - return False + retry = True + while retry: + logger.debug('- Running: {}'.format(cmd)) + retry = False + try: + res_run = subprocess.run(cmd, check=True, capture_output=True, cwd=dest) + logger.debugl(3, '- Output from pip:\n'+res_run.stdout.decode()) + except subprocess.CalledProcessError as e: + logger.debug('- Failed to install `{}` using pip (cmd: {} code: {})'.format(name, e.cmd, e.returncode)) + if e.output: + logger.debug('- Output from command: '+e.output.decode()) + if e.stderr: + logger.debug('- StdErr from command: '+e.stderr.decode()) + if not retry and b'externally-managed-environment' in e.stderr: + # PEP 668 ... and the broken Python packaging concept + retry = True + cmd.insert(-1, '--break-system-packages') + else: + return False + except Exception as e: + logger.debug('- Failed to install `{}` using pip ({})'.format(name, e)) + return False return True @@ -365,6 +373,7 @@ def python_downloader(dep): # Check if we have pip and wheel pip_command = check_pip() if pip_command is None: + logger.error('No pip command available!') return False # Try to pip install it if not pip_install(pip_command, name=dep.pypi_name.lower()): @@ -788,7 +797,7 @@ def check_tool_python(dep, reload=False): res = importlib.reload(reload) return res, ver except ModuleNotFoundError: - pass + logger.error(f'Pip failed for {dep.module_name}') return None, None diff --git a/tests/test_plot/test_dep_downloader.py b/tests/test_plot/test_dep_downloader.py index 11a9fc85..87161038 100644 --- a/tests/test_plot/test_dep_downloader.py +++ b/tests/test_plot/test_dep_downloader.py @@ -60,13 +60,14 @@ def try_dependency(ctx, caplog, monkeypatch, docstring, name_dep, downloader_nam def try_dependency_module(ctx, caplog, monkeypatch, docstring, name_dep, downloader_name): # Note: every attempt to install in a chosen dir failed, even when the module was there and in the sys.path the # importlib call miserably failed. - caplog.set_level(logging.INFO) + caplog.set_level(logging.DEBUG) with monkeypatch.context(): # Refresh the module with actual dependencies mod = importlib.reload(downloader) mod.register_deps('test', yaml.safe_load(docstring)) # Get the dependency dep = mod.used_deps['test:'+name_dep] + logging.info(f"downloader_name: {downloader_name}") # Download it cov.load() cov.start()