■ ■ ■ ■ ■ ■
scripts/uninstall_module.py
| 1 | + | #!/usr/bin/python3 |
| 2 | + | """ |
| 3 | + | `pip uninstall` doesn't support `--prefix`. |
| 4 | + | https://github.com/pypa/pip/issues/11213 |
| 5 | + | """ |
| 6 | + | import argparse |
| 7 | + | import os |
| 8 | + | import shutil |
| 9 | + | import site |
| 10 | + | import subprocess |
| 11 | + | import sys |
| 12 | + | |
| 13 | + | import importlib_metadata |
| 14 | + | |
| 15 | + | |
| 16 | + | def add_site_dir(prefix: str): |
| 17 | + | """ |
| 18 | + | Add site directory with prefix to sys.path and update PYTHONPATH. |
| 19 | + | """ |
| 20 | + | # If prefix is used, we need to make sure that we |
| 21 | + | # do not uninstall other packages from the system paths. |
| 22 | + | sys.path = [] |
| 23 | + | site.PREFIXES = [prefix] |
| 24 | + | pkgs = site.getsitepackages() |
| 25 | + | for path in pkgs: |
| 26 | + | site.addsitedir(path) |
| 27 | + | if 'dist-packages' in path: |
| 28 | + | # Ubuntu / Debian might use both dist- and site- packages. |
| 29 | + | site.addsitedir(path.replace('dist-packages', 'site-packages')) |
| 30 | + | os.environ['PYTHONPATH'] = os.pathsep.join(sys.path) |
| 31 | + | |
| 32 | + | |
| 33 | + | def uninstall_module(package_name: str, prefix=None): |
| 34 | + | """ |
| 35 | + | Enable support for '--prefix' with 'pip uninstall'. |
| 36 | + | """ |
| 37 | + | dist_info_path = None |
| 38 | + | if prefix: |
| 39 | + | add_site_dir(prefix) |
| 40 | + | try: |
| 41 | + | dist_info_path = str(importlib_metadata.distribution(package_name)._path) |
| 42 | + | except importlib_metadata.PackageNotFoundError: |
| 43 | + | print(f"Skipping {package_name} as it is not installed.") |
| 44 | + | sys.exit(0) |
| 45 | + | |
| 46 | + | command = [sys.executable, '-m', 'pip', 'uninstall', '-y', package_name] |
| 47 | + | try: |
| 48 | + | subprocess.check_call(command, env=os.environ) |
| 49 | + | if dist_info_path and os.path.isdir(dist_info_path): |
| 50 | + | # .dist-info files are not cleaned up when the package |
| 51 | + | # has been installed with --prefix. |
| 52 | + | # https://github.com/pypa/pip/issues/5573 |
| 53 | + | shutil.rmtree(dist_info_path) |
| 54 | + | if 'dist-packages' in dist_info_path: |
| 55 | + | shutil.rmtree(dist_info_path.replace('dist-packages', 'site-packages')) |
| 56 | + | except subprocess.CalledProcessError as err: |
| 57 | + | print(f'Error uninstalling package {package_name}: {err}') |
| 58 | + | |
| 59 | + | |
| 60 | + | if __name__ == '__main__': |
| 61 | + | parser = argparse.ArgumentParser() |
| 62 | + | parser.add_argument('module_name', help='The name of the module to uninstall') |
| 63 | + | parser.add_argument('--prefix', help='The prefix where the module was installed') |
| 64 | + | args = parser.parse_args() |
| 65 | + | uninstall_module(args.module_name, args.prefix) |
| 66 | + | |