File: uninstall_module.py

package info (click to toggle)
criu 4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,500 kB
  • sloc: ansic: 139,280; python: 7,484; sh: 3,824; java: 2,799; makefile: 2,659; asm: 1,137; perl: 206; xml: 117; exp: 45
file content (76 lines) | stat: -rwxr-xr-x 2,654 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/python3
"""
`pip uninstall` doesn't support `--prefix`.
https://github.com/pypa/pip/issues/11213
"""
import argparse
import os
import shutil
import site
import subprocess
import sys

# With Python 3.13 the subprocess module now uses the `posix_spawn()`
# function which requires loading the `signal` module:
#     https://docs.python.org/3/whatsnew/3.13.html#subprocess
#
# We need to load this module here, before PYTHONPATH and sys.path
# have been modified to use the path specified with `--prefix`.
#
# flake8: noqa: F401
import signal

import importlib_metadata


def add_site_dir(prefix: str):
    """
    Add site directory with prefix to sys.path and update PYTHONPATH.
    """
    # If prefix is used, we need to make sure that we
    # do not uninstall other packages from the system paths.
    sys.path = []
    site.PREFIXES = [prefix]
    pkgs = site.getsitepackages()
    for path in pkgs:
        site.addsitedir(path)
        if 'dist-packages' in path:
            # Ubuntu / Debian might use both dist- and site- packages.
            site.addsitedir(path.replace('dist-packages', 'site-packages'))
    os.environ['PYTHONPATH'] = os.pathsep.join(sys.path)


def uninstall_module(package_name: str, prefix=None):
    """
    Enable support for '--prefix' with 'pip uninstall'.
    """
    dist_info_path = None
    if prefix:
        add_site_dir(prefix)
        try:
            distribution = next(importlib_metadata.Distribution.discover(name=package_name))
            dist_info_path = str(distribution._path)
        except StopIteration:
            print(f"Skipping {package_name} as it is not installed.")
            sys.exit(0)

    command = [sys.executable, '-m', 'pip', 'uninstall', '-y', package_name]
    try:
        subprocess.check_call(command, env=os.environ)
        if dist_info_path and os.path.isdir(dist_info_path):
            # .dist-info files are not cleaned up when the package
            # has been installed with --prefix.
            # https://github.com/pypa/pip/issues/5573
            shutil.rmtree(dist_info_path)
            if 'dist-packages' in dist_info_path:
                shutil.rmtree(dist_info_path.replace('dist-packages', 'site-packages'))
    except subprocess.CalledProcessError as err:
        print(f'Error uninstalling package {package_name}: {err}')


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('module_name', help='The name of the module to uninstall')
    parser.add_argument('--prefix', help='The prefix where the module was installed')
    args = parser.parse_args()
    uninstall_module(args.module_name, args.prefix)