Mon, 24 Feb 2025 15:43:49 +0100
Adjusted the code to the modified issue codes.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (c) 2002 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> # # This is the uninstall script for eric. # """ Uninstallation script for the eric IDE and all eric related tools. """ import argparse import contextlib import glob import importlib.util import os import shutil import sys import sysconfig # Define the globals. currDir = os.getcwd() pyModDir = None progLanguages = ["MicroPython", "Python3", "QSS"] defaultMacAppBundleName = "eric7.app" defaultMacAppBundlePath = "/Applications" defaultMacUserAppBundlePath = os.path.expanduser("~/Applications") settingsNameOrganization = "Eric7" settingsNameGlobal = "eric7" def exit(rcode=0): """ Exit the uninstall script. @param rcode result code to report back @type int """ global currDir # restore the local eric7config.py if os.path.exists("eric7config.py.orig"): if os.path.exists("eric7config.py"): os.remove("eric7config.py") os.rename("eric7config.py.orig", "eric7config.py") if sys.platform.startswith(("win", "cygwin")): with contextlib.suppress(EOFError): input("Press enter to continue...") # secok os.chdir(currDir) sys.exit(rcode) # get a local eric7config.py out of the way if os.path.exists("eric7config.py"): os.rename("eric7config.py", "eric7config.py.orig") try: from eric7.Globals import getConfig except ImportError: print("The eric IDE doesn't seem to be installed. Aborting.") exit(1) except SyntaxError: # an incomplete or old config file was found print("The eric IDE seems to be installed incompletely. Aborting.") exit(1) def initGlobals(): """ Set the values of globals that need more than a simple assignment. """ global pyModDir pyModDir = sysconfig.get_path("platlib") if not os.access(pyModDir, os.W_OK): # can't write to the standard path, use the 'user' path instead if sys.platform.startswith(("win", "cygwin")): scheme = "nt_user" elif sys.platform == "darwin": scheme = "osx_framework_user" else: scheme = "posix_user" pyModDir = sysconfig.get_path("platlib", scheme) def wrapperNames(dname, wfile): """ Create the platform specific names for the wrapper script. @param dname name of the directory to place the wrapper into @type str @param wfile basename (without extension) of the wrapper script @type str @return list of names of the wrapper scripts @rtype list of str """ wnames = ( [dname + "\\" + wfile + ".cmd", dname + "\\" + wfile + ".bat"] if sys.platform.startswith(("win", "cygwin")) else [dname + "/" + wfile] ) return wnames def uninstallEric(): """ Uninstall the eric files. """ global pyModDir # Remove the menu entry for Linux systems if sys.platform.startswith(("linux", "freebsd")): uninstallLinuxSpecifics() # Remove the Desktop and Start Menu entries for Windows systems elif sys.platform.startswith(("win", "cygwin")): uninstallWindowsLinks() # Remove the wrapper scripts rem_wnames = [ "eric7_api", "eric7_browser", "eric7_compare", "eric7_configure", "eric7_diff", "eric7_doc", "eric7_editor", "eric7_fido2", "eric7_hexeditor", "eric7_iconeditor", "eric7_ide", "eric7_mpy", "eric7_pdf", "eric7_pip", "eric7_plugininstall", "eric7_pluginrepository", "eric7_pluginuninstall", "eric7_qregularexpression", "eric7_re", "eric7_shell", "eric7_snap", "eric7_sqlbrowser", "eric7_testing", "eric7_tray", "eric7_trpreviewer", "eric7_uipreviewer", "eric7_virtualenv", # obsolete scripts below "eric7_unittest", "eric7", ] try: for rem_wname in rem_wnames: for rwname in wrapperNames(getConfig("bindir"), rem_wname): if os.path.exists(rwname): os.remove(rwname) # Cleanup our config file(s) for name in ["eric7config.py", "eric7config.pyc", "eric7.pth"]: e5cfile = os.path.join(pyModDir, name) if os.path.exists(e5cfile): os.remove(e5cfile) e5cfile = os.path.join(pyModDir, "__pycache__", name) path, ext = os.path.splitext(e5cfile) for f in glob.glob("{0}.*{1}".format(path, ext)): os.remove(f) # Cleanup the install directories for name in [ "ericExamplesDir", "ericDocDir", "ericDTDDir", "ericCSSDir", "ericIconDir", "ericPixDir", "ericTemplatesDir", "ericCodeTemplatesDir", "ericOthersDir", "ericStylesDir", "ericThemesDir", "ericDir", ]: with contextlib.suppress(AttributeError): dirpath = getConfig(name) if os.path.exists(dirpath): shutil.rmtree(dirpath, ignore_errors=True) # Cleanup translations for name in glob.glob( os.path.join(getConfig("ericTranslationsDir"), "eric7_*.qm") ): if os.path.exists(name): os.remove(name) # Cleanup API files with contextlib.suppress(AttributeError): apidir = getConfig("apidir") if apidir: for progLanguage in progLanguages: for name in getConfig("apis"): # step 1: programming language as given apiname = os.path.join(apidir, progLanguage, name) if os.path.exists(apiname): os.remove(apiname) # step 2: programming language as lowercase apiname = os.path.join(apidir, progLanguage.lower(), name) if os.path.exists(apiname): os.remove(apiname) for apiname in glob.glob( os.path.join(apidir, progLanguage, "*.bas") ) + glob.glob(os.path.join(apidir, progLanguage.lower(), "*.bas")): if os.path.exists(apiname): os.remove(apiname) # remove empty directories with contextlib.suppress(FileNotFoundError, OSError): os.rmdir(os.path.join(apidir, progLanguage)) with contextlib.suppress(FileNotFoundError, OSError): os.rmdir(os.path.join(apidir, progLanguage.lower())) if sys.platform == "darwin": # delete the Mac app bundle uninstallMacAppBundle() # remove plug-in directories removePluginDirectories() # remove the eric data directory removeDataDirectory() # remove the eric configuration directory removeConfigurationData() print("\nUninstallation completed") except OSError as msg: sys.stderr.write("Error: {0}\nTry uninstall with admin rights.\n".format(msg)) exit(7) def uninstallWindowsLinks(): """ Clean up the Desktop and Start Menu entries for Windows. """ if importlib.util.find_spec("pywintypes") is None: # links were not created by install.py return regPath = ( "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders" ) # 1. cleanup desktop links regName = "Desktop" desktopEntry = getWinregEntry(regName, regPath) if desktopEntry: desktopFolder = os.path.normpath(os.path.expandvars(desktopEntry)) for linkName in windowsDesktopNames(): linkPath = os.path.join(desktopFolder, linkName) if os.path.exists(linkPath): try: os.remove(linkPath) except OSError: # maybe restrictions prohibited link removal print("Could not remove '{0}'.".format(linkPath)) # 2. cleanup start menu entry regName = "Programs" programsEntry = getWinregEntry(regName, regPath) if programsEntry: programsFolder = os.path.normpath(os.path.expandvars(programsEntry)) eric7EntryPath = os.path.join(programsFolder, windowsProgramsEntry()) if os.path.exists(eric7EntryPath): try: shutil.rmtree(eric7EntryPath) except OSError: # maybe restrictions prohibited link removal print("Could not remove '{0}'.".format(eric7EntryPath)) def uninstallLinuxSpecifics(): """ Uninstall Linux specific files. """ if os.getuid() == 0: for name in [ "/usr/share/appdata/eric7.appdata.xml", "/usr/share/metainfo/eric7.appdata.xml", "/usr/share/applications/eric7_browser.desktop", "/usr/share/applications/eric7_ide.desktop", "/usr/share/applications/eric7_mpy.desktop", "/usr/share/icons/eric.png", "/usr/share/icons/ericMPy.png", "/usr/share/icons/ericWeb.png", "/usr/share/pixmaps/eric.png", "/usr/share/pixmaps/ericMPy.png", "/usr/share/pixmaps/ericWeb.png", # obsolete entries below "/usr/share/applications/eric7.desktop", ]: if os.path.exists(name): os.remove(name) elif os.getuid() >= 1000: # it is assumed that user ids start at 1000 for name in [ "~/.local/share/appdata/eric7.appdata.xml", "~/.local/share/metainfo/eric7.appdata.xml", "~/.local/share/applications/eric7_browser.desktop", "~/.local/share/applications/eric7_ide.desktop", "~/.local/share/applications/eric7_mpy.desktop", "~/.local/share/icons/eric.png", "~/.local/share/icons/ericMPy.png", "~/.local/share/icons/ericWeb.png", "~/.local/share/pixmaps/eric.png", "~/.local/share/pixmaps/ericMPy.png", "~/.local/share/pixmaps/ericWeb.png", # obsolete entries below "~/.local/share/applications/eric7.desktop", ]: path = os.path.expanduser(name) if os.path.exists(path): os.remove(path) def uninstallMacAppBundle(): """ Uninstall the macOS application bundle. """ if os.path.exists("/Developer/Applications/Eric7"): shutil.rmtree("/Developer/Applications/Eric7") try: macAppBundlePath = getConfig("macAppBundlePath") macAppBundleName = getConfig("macAppBundleName") except AttributeError: macAppBundlePath = ( defaultMacAppBundlePath if os.getpid() == 0 else defaultMacUserAppBundlePath ) macAppBundleName = defaultMacAppBundleName for bundlePath in [ os.path.join(defaultMacAppBundlePath, macAppBundleName), os.path.join(defaultMacUserAppBundlePath, macAppBundleName), os.path.join(macAppBundlePath, macAppBundleName), ]: if os.path.exists(bundlePath): shutil.rmtree(bundlePath) def removePluginDirectories(): """ Remove the plug-in directories. """ pathsToRemove = [] globalPluginsDir = os.path.join(getConfig("mdir"), "eric7plugins") if os.path.exists(globalPluginsDir): pathsToRemove.append(globalPluginsDir) localPluginsDir = os.path.join(getConfigDir(), "eric7plugins") if os.path.exists(localPluginsDir): pathsToRemove.append(localPluginsDir) if pathsToRemove: print("Found these plug-in directories") for path in pathsToRemove: print(" - {0}".format(path)) answer = "c" while answer not in ["y", "Y", "n", "N", ""]: answer = input("Shall these directories be removed (y/N)? ") # secok if answer in ["y", "Y"]: for path in pathsToRemove: shutil.rmtree(path) def removeDataDirectory(): """ Remove the eric data directory. """ cfg = getConfigDir() if os.path.exists(cfg): print("Found the eric data directory") print(" - {0}".format(cfg)) answer = "c" while answer not in ["y", "Y", "n", "N", ""]: answer = input("Shall this directory be removed (y/N)? ") # secok if answer in ["y", "Y"]: shutil.rmtree(cfg) def removeConfigurationData(): """ Remove the eric configuration directory. """ try: from PyQt6.QtCore import QSettings # __IGNORE_WARNING_I-10__ except ImportError: print("No PyQt variant installed. The configuration directory") print("cannot be determined. You have to remove it manually.\n") return settings = QSettings( QSettings.Format.IniFormat, QSettings.Scope.UserScope, settingsNameOrganization, settingsNameGlobal, ) settingsDir = os.path.dirname(settings.fileName()) if os.path.exists(settingsDir): print("Found the eric configuration directory") print(" - {0}".format(settingsDir)) answer = "c" while answer not in ["y", "Y", "n", "N", ""]: answer = input("Shall this directory be removed (y/N)? ") # secok if answer in ["y", "Y"]: shutil.rmtree(settingsDir) def getConfigDir(): """ Module function to get the name of the directory storing the config data. @return directory name of the config dir @rtype str """ cdn = ".eric7" return os.path.join(os.path.expanduser("~"), cdn) def getWinregEntry(name, path): """ Function to get an entry from the Windows Registry. @param name variable name @type str @param path registry path of the variable @type str @return value of requested registry variable @rtype Any """ # From http://stackoverflow.com/a/35286642 import winreg # __IGNORE_WARNING_I-103__ try: registryKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, winreg.KEY_READ) value, _ = winreg.QueryValueEx(registryKey, name) winreg.CloseKey(registryKey) return value except WindowsError: return None def windowsDesktopNames(): """ Function to generate the link names for the Windows Desktop. @return list of desktop link names @rtype list of str """ majorVersion, minorVersion = sys.version_info[:2] linkTemplates = [ "eric7 IDE (Python {0}.{1}).lnk", "eric7 Browser (Python {0}.{1}).lnk", "eric7 MicroPython (Python {0}.{1}).lnk", # obsolete entries below "eric7 (Python {0}.{1}).lnk", ] return [ll.format(majorVersion, minorVersion) for ll in linkTemplates] def windowsProgramsEntry(): """ Function to generate the name of the Start Menu top entry. @return name of the Start Menu top entry @rtype str """ majorVersion, minorVersion = sys.version_info[:2] return "eric7 (Python {0}.{1})".format(majorVersion, minorVersion) def createArgumentParser(): """ Function to create an argument parser. @return created argument parser object @rtype argparse.ArgumentParser """ parser = argparse.ArgumentParser(description="Uninstall eric7.") return parser def main(): """ The main function of the script. """ initGlobals() parser = createArgumentParser() parser.parse_args() print("\nUninstalling eric ...") uninstallEric() print("\nUninstallation complete.") print() exit(0) if __name__ == "__main__": try: main() except SystemExit: raise except Exception: print( """An internal error occured. Please report all the output of""" """ the program,\n""" """including the following traceback, to""" """ eric-bugs@eric-ide.python-projects.org.\n""" ) raise # # eflag: noqa = M-801