Skip to content

Instantly share code, notes, and snippets.

@mtwebster
Last active January 14, 2022 16:08
Show Gist options
  • Save mtwebster/eec06bb6fa1385ff05cf9624c4c6c414 to your computer and use it in GitHub Desktop.
Save mtwebster/eec06bb6fa1385ff05cf9624c4c6c414 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
import json
import sys
import subprocess
import re
import sysconfig
import shutil
if len(sys.argv) < 2:
print("Single argument must be the system package manager name (apt, rpm)")
exit(1)
PM = sys.argv[1]
if shutil.which("pip3") == None:
print("Program pip3 missing")
if PM == "apt":
print("Install it with 'apt install python3-pip' and run this script again")
elif PM == "rpm":
print("Install it with 'dnf install python3-pip' and run this script again")
exit(1)
# user_prefix = sysconfig.get_config_var("userbase")
# print("User python module location: %s" % user_prefix)
path_finder = re.compile(r"(?:Location:[\s]+?)([\S]+lib\/python3[\.]*[\d]*[\/]*[\S]*)")
# user_path_finder = re.compile(f"({{}})".format(re.escape(user_prefix)))
print("What this does...\n")
print("1 - Gather a list of all python3 modules on the system.")
print("2 - Filter out all non-system-managed modules.")
print("3 - Look for installed, system-managed python modules whose names are included in that filtered list.")
input("\nEnter to proceed\n")
def match_apt(name):
ret = subprocess.run(["dpkg-query", "--status", name],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
return ret.returncode == 0
def match_rpm(name):
ret = subprocess.run(["rpm", "-q", name],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
return ret.returncode == 0
print("Gathering all python3 module names...")
try:
pip3_list_out = subprocess.check_output(["pip3", "list", "--format", "json"],
stderr=subprocess.DEVNULL
).decode("utf-8")
pip3_json = json.loads(pip3_list_out)
except Exception as e:
print(e)
exit(0)
mod_candidates = []
for item in pip3_json:
name = item["name"]
info = subprocess.check_output(["pip3", "show", "-f", name],
stderr=subprocess.DEVNULL
).decode("utf-8")
match = path_finder.search(info)
if match:
if "Cannot locate RECORD" in info:
continue
if match == "pip":
print("Skipping pip")
continue
print("Found %s" % name)
mod_candidates.append(name.lower())
print("\nNow comparing those against system packages...\n")
overlapping_modules = []
# "pip name" : "pm name"
APT_RENAMES = {
"pillow": "pil"
}
RPM_RENAMES = {
}
def adjusted(dict, pip_name):
if pip_name in dict.keys():
print("Using %s in place of %s" % (dict[pip_name], pip_name))
return dict[pip_name]
else:
return pip_name
for module in mod_candidates:
if PM == "apt":
sysmod = "python3-%s" % adjusted(APT_RENAMES, module)
if match_apt(sysmod):
print("Possible module conflict: %s -> %s" % (module, sysmod))
overlapping_modules.append(sysmod)
elif PM == "rpm":
sysmod = "python3-%s" % adjusted (RPM_RENAMES, module)
if match_rpm(sysmod):
print("Possible module conflict: %s -> %s" % (module, sysmod))
overlapping_modules.append(sysmod)
if PM == "apt":
cmd = ["apt", "reinstall"] + overlapping_modules
elif PM == "rpm":
cmd = ["dnf", "reinstall"] + overlapping_modules
pass
print("\nWill now use %s to re-install the system versions of these packages:\n" % PM)
print(" ".join(cmd))
input("\nEnter to proceed (or hit ctrl-c now to abort)\n")
ret = subprocess.run(cmd)
if ret.returncode == 0:
print("Success!\n")
else:
print("Something went wrong...")
exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment