diff -r e3381757d40d -r 4aa36fcd4a30 src/eric7/Project/Project.py --- a/src/eric7/Project/Project.py Sat Feb 10 11:02:45 2024 +0100 +++ b/src/eric7/Project/Project.py Sun Mar 03 10:39:29 2024 +0100 @@ -23,8 +23,6 @@ from PyQt6.QtCore import ( QByteArray, QCryptographicHash, - QFile, - QIODevice, QObject, QProcess, pyqtSignal, @@ -45,11 +43,6 @@ from eric7.EricWidgets.EricApplication import ericApp from eric7.EricWidgets.EricListSelectionDialog import EricListSelectionDialog from eric7.EricWidgets.EricProgressDialog import EricProgressDialog -from eric7.EricXML.DebuggerPropertiesReader import DebuggerPropertiesReader -from eric7.EricXML.ProjectReader import ProjectReader -from eric7.EricXML.SessionReader import SessionReader -from eric7.EricXML.TasksReader import TasksReader -from eric7.EricXML.UserProjectReader import UserProjectReader from eric7.Globals import recentNameProject from eric7.Sessions.SessionFile import SessionFile from eric7.SystemUtilities import ( @@ -551,7 +544,7 @@ "HASH": "", "PROGLANGUAGE": "Python3", "MIXEDLANGUAGE": False, - "PROJECTTYPE": "PyQt5", + "PROJECTTYPE": "PyQt6", "SPELLLANGUAGE": Preferences.getEditor("SpellCheckingDefaultLanguage"), "SPELLWORDS": "", "SPELLEXCLUDES": "", @@ -875,7 +868,6 @@ "*.rst": "OTHERS", "README": "OTHERS", "README.*": "OTHERS", - "*.e4p": "OTHERS", "*.epj": "OTHERS", "GNUmakefile": "OTHERS", "makefile": "OTHERS", @@ -1118,46 +1110,15 @@ def __readProject(self, fn): """ - Private method to read in a project (.epj or .e4p) file. + Private method to read in a project (.epj) file. @param fn filename of the project file to be read @type str @return flag indicating success @rtype bool """ - if os.path.splitext(fn)[1] == ".epj": - # new JSON based format - with EricOverrideCursor(): - res = self.__projectFile.readFile(fn) - else: - # old XML based format - f = QFile(fn) - if f.open(QIODevice.OpenModeFlag.ReadOnly): - reader = ProjectReader(f, self) - reader.readXML() - res = not reader.hasError() - f.close() - - # create hash value, if it doesn't have one - if reader.version.startswith("5.") and not self.__pdata["HASH"]: - hashStr = str( - QCryptographicHash.hash( - QByteArray(self.ppath.encode("utf-8")), - QCryptographicHash.Algorithm.Sha1, - ).toHex(), - encoding="utf-8", - ) - self.__pdata["HASH"] = hashStr - self.setDirty(True) - else: - EricMessageBox.critical( - self.ui, - self.tr("Read Project File"), - self.tr( - "<p>The project file <b>{0}</b> could not be read.</p>" - ).format(fn), - ) - res = False + with EricOverrideCursor(): + res = self.__projectFile.readFile(fn) if res: self.pfile = os.path.abspath(fn) @@ -1247,8 +1208,7 @@ def __readUserProperties(self): """ - Private method to read in the user specific project file (.eqj or - .e4q). + Private method to read in the user specific project file (.eqj). """ if self.pfile is None: return @@ -1256,26 +1216,7 @@ fn1, ext = os.path.splitext(os.path.basename(self.pfile)) fn = os.path.join(self.getProjectManagementDir(), "{0}.eqj".format(fn1)) if os.path.exists(fn): - # try the new JSON based format first self.__userProjectFile.readFile(fn) - else: - # try the old XML based format second - fn = os.path.join(self.getProjectManagementDir(), "{0}.e4q".format(fn1)) - if os.path.exists(fn): - f = QFile(fn) - if f.open(QIODevice.OpenModeFlag.ReadOnly): - reader = UserProjectReader(f, self) - reader.readXML() - f.close() - else: - EricMessageBox.critical( - self.ui, - self.tr("Read User Project Properties"), - self.tr( - "<p>The user specific project properties file" - " <b>{0}</b> could not be read.</p>" - ).format(fn), - ) def __writeUserProperties(self): """ @@ -1299,16 +1240,15 @@ enable = False else: fn, ext = os.path.splitext(os.path.basename(self.pfile)) - fn_new = os.path.join(self.getProjectManagementDir(), "{0}.esj".format(fn)) - fn_old = os.path.join(self.getProjectManagementDir(), "{0}.e5s".format(fn)) - enable = os.path.exists(fn_new) or os.path.exists(fn_old) + fn_sess = os.path.join(self.getProjectManagementDir(), "{0}.esj".format(fn)) + enable = os.path.exists(fn_sess) self.sessActGrp.findChild(QAction, "project_load_session").setEnabled(enable) self.sessActGrp.findChild(QAction, "project_delete_session").setEnabled(enable) @pyqtSlot() def __readSession(self, quiet=False, indicator=""): """ - Private method to read in the project session file (.esj or .e5s). + Private method to read in the project session file (.esj). @param quiet flag indicating quiet operations. If this flag is true, no errors are reported. @@ -1330,29 +1270,7 @@ self.getProjectManagementDir(), "{0}{1}.esj".format(fn1, indicator) ) if os.path.exists(fn): - # try the new JSON based format first self.__sessionFile.readFile(fn) - else: - # try the old XML based format second - fn = os.path.join( - self.getProjectManagementDir(), "{0}{1}.e5s".format(fn1, indicator) - ) - if os.path.exists(fn): - f = QFile(fn) - if f.open(QIODevice.OpenModeFlag.ReadOnly): - reader = SessionReader(f, False) - reader.readXML(quiet=quiet) - f.close() - else: - if not quiet: - EricMessageBox.critical( - self.ui, - self.tr("Read project session"), - self.tr( - "<p>The project session file <b>{0}</b> could" - " not be read.</p>" - ).format(fn), - ) @pyqtSlot() def __writeSession(self, quiet=False, indicator=""): @@ -1395,26 +1313,23 @@ fname, ext = os.path.splitext(os.path.basename(self.pfile)) - for ext in (".esj", ".e5s", ".e4s"): - fn = os.path.join( - self.getProjectManagementDir(), "{0}{1}".format(fname, ext) - ) - if os.path.exists(fn): - try: - os.remove(fn) - except OSError: - EricMessageBox.critical( - self.ui, - self.tr("Delete Project Session"), - self.tr( - "<p>The project session file <b>{0}</b> could" - " not be deleted.</p>" - ).format(fn), - ) + fn = os.path.join(self.getProjectManagementDir(), f"{fname}.esj") + if os.path.exists(fn): + try: + os.remove(fn) + except OSError: + EricMessageBox.critical( + self.ui, + self.tr("Delete Project Session"), + self.tr( + "<p>The project session file <b>{0}</b> could" + " not be deleted.</p>" + ).format(fn), + ) def __readTasks(self): """ - Private method to read in the project tasks file (.etj or .e6t). + Private method to read in the project tasks file (.etj). """ if self.pfile is None: EricMessageBox.critical( @@ -1427,25 +1342,7 @@ base, ext = os.path.splitext(os.path.basename(self.pfile)) fn = os.path.join(self.getProjectManagementDir(), "{0}.etj".format(base)) if os.path.exists(fn): - # try new style JSON file first self.__tasksFile.readFile(fn) - else: - # try old style XML file second - fn = os.path.join(self.getProjectManagementDir(), "{0}.e6t".format(base)) - if os.path.exists(fn): - f = QFile(fn) - if f.open(QIODevice.OpenModeFlag.ReadOnly): - reader = TasksReader(f, True) - reader.readXML() - f.close() - else: - EricMessageBox.critical( - self.ui, - self.tr("Read Tasks"), - self.tr( - "<p>The tasks file <b>{0}</b> could not be read.</p>" - ).format(fn), - ) def writeTasks(self): """ @@ -1468,11 +1365,7 @@ enable = False else: fn, ext = os.path.splitext(os.path.basename(self.pfile)) - # try new style file first fn = os.path.join(self.getProjectManagementDir(), "{0}.edj".format(fn)) - if not os.path.exists(fn): - # try old style file second - fn = os.path.join(self.getProjectManagementDir(), "{0}.e4d".format(fn)) enable = os.path.exists(fn) self.dbgActGrp.findChild( QAction, "project_debugger_properties_load" @@ -1484,8 +1377,7 @@ @pyqtSlot() def __readDebugProperties(self, quiet=False): """ - Private method to read in the project debugger properties file - (.edj or .e4d). + Private method to read in the project debugger properties file (.edj). @param quiet flag indicating quiet operations. If this flag is true, no errors are reported. @@ -1502,32 +1394,12 @@ fn1, ext = os.path.splitext(os.path.basename(self.pfile)) fn = os.path.join(self.getProjectManagementDir(), "{0}.edj".format(fn1)) - if os.path.exists(fn): - # try the new JSON based format first - if self.__debuggerPropertiesFile.readFile(fn): - self.debugPropertiesLoaded = True - self.debugPropertiesChanged = False - else: - # try the old XML based format second - fn = os.path.join(self.getProjectManagementDir(), "{0}.e4d".format(fn1)) - - f = QFile(fn) - if f.open(QIODevice.OpenModeFlag.ReadOnly): - reader = DebuggerPropertiesReader(f, self) - reader.readXML(quiet=quiet) - f.close() - self.debugPropertiesLoaded = True - self.debugPropertiesChanged = False - else: - if not quiet: - EricMessageBox.critical( - self.ui, - self.tr("Read Debugger Properties"), - self.tr( - "<p>The project debugger properties file" - " <b>{0}</b> could not be read.</p>" - ).format(fn), - ) + if ( + os.path.exists(fn) + and self.__debuggerPropertiesFile.readFile(fn) + ): + self.debugPropertiesLoaded = True + self.debugPropertiesChanged = False @pyqtSlot() def __writeDebugProperties(self, quiet=False): @@ -1555,8 +1427,7 @@ def __deleteDebugProperties(self): """ - Private method to delete the project debugger properties file - (.edj or .e4d). + Private method to delete the project debugger properties file (.edj). """ if self.pfile is None: EricMessageBox.critical( @@ -1568,22 +1439,19 @@ fname, ext = os.path.splitext(os.path.basename(self.pfile)) - for ext in (".edj", ".e4d"): - fn = os.path.join( - self.getProjectManagementDir(), "{0}{1}".format(fname, ext) - ) - if os.path.exists(fn): - try: - os.remove(fn) - except OSError: - EricMessageBox.critical( - self.ui, - self.tr("Delete Debugger Properties"), - self.tr( - "<p>The project debugger properties file" - " <b>{0}</b> could not be deleted.</p>" - ).format(fn), - ) + fn = os.path.join(self.getProjectManagementDir(), f"{fname}.edj") + if os.path.exists(fn): + try: + os.remove(fn) + except OSError: + EricMessageBox.critical( + self.ui, + self.tr("Delete Debugger Properties"), + self.tr( + "<p>The project debugger properties file" + " <b>{0}</b> could not be deleted.</p>" + ).format(fn), + ) def __initDebugProperties(self): """ @@ -2253,7 +2121,7 @@ self.tr("Rename file"), oldfn, "", - EricFileDialog.DontConfirmOverwrite, + options=EricFileDialog.DontConfirmOverwrite, ) if not newfn: return False @@ -2719,7 +2587,7 @@ ms = self.__pdata["MAINSCRIPT"] if not os.path.exists(ms): try: - os.makedirs(os.path.dirname(ms)) + os.makedirs(os.path.dirname(ms), exist_ok=True) with open(ms, "w"): pass except OSError as err: @@ -2744,7 +2612,7 @@ mf = os.path.join(self.ppath, Project.DefaultMakefile) if not os.path.exists(mf): try: - os.makedirs(os.path.dirname(mf)) + os.makedirs(os.path.dirname(mf), exist_ok=True) with open(mf, "w"): pass except OSError as err: @@ -3247,7 +3115,7 @@ self.parent(), self.tr("Open project"), Preferences.getMultiProject("Workspace") or OSUtilities.getHomeDir(), - self.tr("Project Files (*.epj);;XML Project Files (*.e4p)"), + self.tr("Project Files (*.epj)"), ) if fn and self.closeProject(): @@ -3423,9 +3291,6 @@ """ if self.isDirty(): if len(self.pfile) > 0: - if self.pfile.endswith(".e4p"): - self.pfile = self.pfile.replace(".e4p", ".epj") - self.__syncRecent() ok = self.__writeProject() else: ok = self.saveProjectAs() @@ -5686,7 +5551,7 @@ if filetype == "__IGNORE__" ] - dirs = self.subdirs[:] + dirs = [""] if recursiveSearch else self.subdirs[:] + [""] for directory in dirs: skip = False for ignore_pattern in ignore_patterns: @@ -5709,14 +5574,7 @@ binpattern = self.__binaryTranslationFile(pattern) for ns in newSources: # ignore hidden files and directories - if ns.startswith("."): - continue - if ( - OSUtilities.isWindowsPlatform() - and os.path.isdir(os.path.join(curpath, ns)) - and ns.startswith("_") - ): - # dot net hack + if ns.startswith(".") or ns == "__pycache__": continue # set fn to project relative name @@ -7107,19 +6965,21 @@ @return path of the embedded virtual environment (empty if not found) @rtype str """ - with os.scandir(self.getProjectPath()) as ppathDirEntriesIterator: - for dirEntry in ppathDirEntriesIterator: - # potential venv directory; check for 'pyvenv.cfg' - if dirEntry.is_dir() and os.path.exists( - os.path.join(dirEntry.path, "pyvenv.cfg") - ): - return dirEntry.path - - # check for some common names in case 'pyvenv.cfg' is missing - for venvPathName in (".venv", "venv", ".env", "env"): - venvPath = os.path.join(self.getProjectPath(), venvPathName) - if os.path.isdir(venvPath): - return venvPath + ppath = self.getProjectPath() + if ppath and os.path.exists(ppath): + with os.scandir(self.getProjectPath()) as ppathDirEntriesIterator: + for dirEntry in ppathDirEntriesIterator: + # potential venv directory; check for 'pyvenv.cfg' + if dirEntry.is_dir() and os.path.exists( + os.path.join(dirEntry.path, "pyvenv.cfg") + ): + return dirEntry.path + + # check for some common names in case 'pyvenv.cfg' is missing + for venvPathName in (".venv", "venv", ".env", "env"): + venvPath = os.path.join(self.getProjectPath(), venvPathName) + if os.path.isdir(venvPath): + return venvPath return ""