eric7/Plugins/WizardPlugins/SetupWizard/SetupWizardDialog.py

branch
eric7
changeset 9175
21e2be5f0b41
parent 8881
54e42bc2437a
child 9188
d137adc02a0f
--- a/eric7/Plugins/WizardPlugins/SetupWizard/SetupWizardDialog.py	Fri Jun 24 10:19:17 2022 +0200
+++ b/eric7/Plugins/WizardPlugins/SetupWizard/SetupWizardDialog.py	Sun Jun 26 15:01:48 2022 +0200
@@ -10,14 +10,15 @@
 import os
 import datetime
 
-from PyQt6.QtCore import pyqtSlot, Qt, QUrl
+import trove_classifiers
+
+from PyQt6.QtCore import pyqtSlot, Qt
 from PyQt6.QtWidgets import (
     QDialog, QDialogButtonBox, QTreeWidgetItem, QListWidgetItem
 )
-from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply
 
 from EricWidgets.EricApplication import ericApp
-from EricWidgets import EricMessageBox, EricFileDialog
+from EricWidgets import EricFileDialog
 from EricWidgets.EricPathPicker import EricPathPickerModes
 
 from .Ui_SetupWizardDialog import Ui_SetupWizardDialog
@@ -33,13 +34,12 @@
     It displays a dialog for entering the parameters for the setup.py code
     generator.
     """
-    ClassifiersUrl = "https://pypi.org/pypi?%3Aaction=list_classifiers"
-    
     def __init__(self, parent=None):
         """
         Constructor
         
-        @param parent reference to the parent widget (QWidget)
+        @param parent reference to the parent widget
+        @type QWidget
         """
         super().__init__(parent)
         self.setupUi(self)
@@ -62,7 +62,7 @@
                          self.maintainerEmailEdit]:
             lineEdit.setStyleSheet(self.__mandatoryStyleSheet)
         
-        self.__loadClassifiersFromPyPI()
+        self.__populateClassifiers()
         
         self.__okButton = self.buttonBox.button(
             QDialogButtonBox.StandardButton.Ok)
@@ -96,73 +96,9 @@
         
         self.__okButton.setEnabled(enable)
     
-    def __loadClassifiersFromPyPI(self):
-        """
-        Private method to populate the classifiers list with data retrieved
-        from PyPI.
-        """
-        request = QNetworkRequest(QUrl(SetupWizardDialog.ClassifiersUrl))
-        request.setAttribute(
-            QNetworkRequest.Attribute.CacheLoadControlAttribute,
-            QNetworkRequest.CacheLoadControl.AlwaysNetwork)
-        reply = (
-            ericApp().getObject("UserInterface").networkAccessManager()
-            .get(request)
-        )
-        reply.finished.connect(lambda: self.__classifiersDownloadDone(reply))
-        self.__replies.append(reply)
-
-    @pyqtSlot()
-    def __classifiersDownloadDone(self, reply):
-        """
-        Private slot called, after the classifiers file has been downloaded
-        from the internet.
-        
-        @param reply reference to the network reply
-        @type QNetworkReply
-        """
-        reply.deleteLater()
-        if reply in self.__replies:
-            self.__replies.remove(reply)
-        if reply.error() == QNetworkReply.NetworkError.NoError:
-            ioEncoding = Preferences.getSystem("IOEncoding")
-            lines = str(reply.readAll(), ioEncoding, 'replace').splitlines()
-            
-            self.__populateClassifiers(lines)
-        
-        reply.close()
-    
-    @pyqtSlot()
-    def on_localClassifiersButton_clicked(self):
-        """
-        Private method to populate lists from the Trove list file.
-        
-        Note: The trove list file was created from querying
-        "https://pypi.org/pypi?%3Aaction=list_classifiers".
-        """
-        filename = os.path.join(os.path.dirname(__file__),
-                                "data", "trove_classifiers.txt")
-        try:
-            with open(filename, "r") as f:
-                lines = f.readlines()
-        except OSError as err:
-            EricMessageBox.warning(
-                self,
-                self.tr("Reading Trove Classifiers"),
-                self.tr("""<p>The Trove Classifiers file <b>{0}</b>"""
-                        """ could not be read.</p><p>Reason: {1}</p>""")
-                .format(filename, str(err)))
-            return
-        
-        self.__populateClassifiers(lines)
-    
-    def __populateClassifiers(self, classifiers):
+    def __populateClassifiers(self):
         """
         Private method to populate the classifiers.
-        
-        @param classifiers list of classifiers read from a local file or
-            retrieved from PyPI
-        @type list of str
         """
         self.licenseClassifierComboBox.clear()
         self.classifiersList.clear()
@@ -171,18 +107,17 @@
         self.developmentStatusComboBox.addItem("", "")
         
         self.__classifiersDict = {}
-        for line in classifiers:
-            line = line.strip()
-            if line.startswith("License "):
+        for classifier in trove_classifiers.sorted_classifiers:
+            if classifier.startswith("License ::"):
                 self.licenseClassifierComboBox.addItem(
-                    "/".join(line.split(" :: ")[1:]),
-                    line
+                    "/".join(classifier.split(" :: ")[1:]),
+                    classifier
                 )
-            elif line.startswith("Development Status "):
+            elif classifier.startswith("Development Status ::"):
                 self.developmentStatusComboBox.addItem(
-                    line.split(" :: ")[1], line)
+                    classifier.split(" :: ")[1], classifier)
             else:
-                self.__addClassifierEntry(line)
+                self.__addClassifierEntry(classifier)
         self.__classifiersDict = {}
         
         self.licenseClassifierComboBox.setCurrentIndex(
@@ -192,15 +127,16 @@
             )
         )
     
-    def __addClassifierEntry(self, line):
+    def __addClassifierEntry(self, classifier):
         """
         Private method to add a new entry to the list of trove classifiers.
         
-        @param line line containing the data for the entry (string)
+        @param classifier classifier containing the data for the entry
+        @type str
         """
         itm = None
         pitm = None
-        dataList = line.split(" :: ")
+        dataList = classifier.split(" :: ")
         for index in range(len(dataList)):
             key = " :: ".join(dataList[:index + 1])
             if key not in self.__classifiersDict:
@@ -215,13 +151,14 @@
             else:
                 pitm = self.__classifiersDict[key]
         itm.setCheckState(0, Qt.CheckState.Unchecked)
-        itm.setData(0, Qt.ItemDataRole.UserRole, line)
+        itm.setData(0, Qt.ItemDataRole.UserRole, classifier)
     
     def __getLicenseText(self):
         """
         Private method to get the license text.
         
-        @return license text (string)
+        @return license text
+        @rtype str
         """
         if not self.licenseClassifierCheckBox.isChecked():
             return self.licenseEdit.text()
@@ -235,9 +172,12 @@
         """
         Public method to get the source code.
         
-        @param indLevel indentation level (int)
-        @param indString string used for indentation (space or tab) (string)
-        @return generated code (string)
+        @param indLevel indentation level
+        @type int
+        @param indString string used for indentation (space or tab)
+        @type str
+        @return generated code
+        @rtype str
         """
         # Note: all paths are created with '/'; setup will do the right thing
         
@@ -250,95 +190,95 @@
         
         # now generate the code
         if self.introCheckBox.isChecked():
-            code = "#!/usr/bin/env python3{0}".format(os.linesep)
-            code += "# -*- coding: utf-8 -*-{0}{0}".format(os.linesep)
+            sourceCode = "#!/usr/bin/env python3{0}".format(os.linesep)
+            sourceCode += "# -*- coding: utf-8 -*-{0}{0}".format(os.linesep)
         else:
-            code = ""
+            sourceCode = ""
         
         if self.metaDataCheckBox.isChecked():
-            code += '# metadata{0}'.format(os.linesep)
-            code += '"{0}"{1}'.format(
+            sourceCode += '# metadata{0}'.format(os.linesep)
+            sourceCode += '"{0}"{1}'.format(
                 self.summaryEdit.text() or "Setup routine",
                 os.linesep
             )
-            code += '__version__ = "{0}"{1}'.format(
+            sourceCode += '__version__ = "{0}"{1}'.format(
                 self.versionEdit.text(), os.linesep)
-            code += '__license__ = "{0}"{1}'.format(
+            sourceCode += '__license__ = "{0}"{1}'.format(
                 self.__getLicenseText(), os.linesep)
-            code += '__author__ = "{0}"{1}'.format(
+            sourceCode += '__author__ = "{0}"{1}'.format(
                 self.authorEdit.text() or self.maintainerEdit.text(),
                 os.linesep)
-            code += '__email__ = "{0}"{1}'.format(
+            sourceCode += '__email__ = "{0}"{1}'.format(
                 self.authorEmailEdit.text() or self.maintainerEmailEdit.text(),
                 os.linesep)
-            code += '__url__ = "{0}"{1}'.format(
+            sourceCode += '__url__ = "{0}"{1}'.format(
                 self.homePageUrlEdit.text(), os.linesep)
-            code += '__date__ = "{0}"{1}'.format(
+            sourceCode += '__date__ = "{0}"{1}'.format(
                 datetime.datetime.now().isoformat().split('.')[0], os.linesep)
-            code += '__prj__ = "{0}"{1}'.format(
+            sourceCode += '__prj__ = "{0}"{1}'.format(
                 self.nameEdit.text(), os.linesep)
-            code += os.linesep
+            sourceCode += os.linesep
         
         if self.importCheckBox.isChecked():
             additionalImport = ", find_packages"
-            code += "from setuptools import setup{0}{1}".format(
+            sourceCode += "from setuptools import setup{0}{1}".format(
                 additionalImport, os.linesep)
-        if code:
-            code += "{0}{0}".format(os.linesep)
+        if sourceCode:
+            sourceCode += "{0}{0}".format(os.linesep)
         
         if self.descriptionFromFilesCheckBox.isChecked():
-            code += 'def get_long_description():{0}'.format(os.linesep)
-            code += '{0}descr = []{1}'.format(istring, os.linesep)
-            code += '{0}for fname in "{1}":{2}'.format(
+            sourceCode += 'def get_long_description():{0}'.format(os.linesep)
+            sourceCode += '{0}descr = []{1}'.format(istring, os.linesep)
+            sourceCode += '{0}for fname in "{1}":{2}'.format(
                 istring,
                 '", "'.join(self.descriptionEdit.toPlainText().splitlines()),
                 os.linesep)
-            code += '{0}{0}with open(fname) as f:{1}'.format(
+            sourceCode += '{0}{0}with open(fname) as f:{1}'.format(
                 istring, os.linesep)
-            code += '{0}{0}{0}descr.append(f.read()){1}'.format(
+            sourceCode += '{0}{0}{0}descr.append(f.read()){1}'.format(
                 istring, os.linesep)
-            code += '{0}return "\\n\\n".join(descr){1}'.format(
+            sourceCode += '{0}return "\\n\\n".join(descr){1}'.format(
                 istring, os.linesep)
-            code += "{0}{0}".format(os.linesep)
+            sourceCode += "{0}{0}".format(os.linesep)
         
-        code += 'setup({0}'.format(os.linesep)
-        code += '{0}name="{1}",{2}'.format(
+        sourceCode += 'setup({0}'.format(os.linesep)
+        sourceCode += '{0}name="{1}",{2}'.format(
             istring, self.nameEdit.text(), os.linesep)
-        code += '{0}version="{1}",{2}'.format(
+        sourceCode += '{0}version="{1}",{2}'.format(
             istring, self.versionEdit.text(), os.linesep)
         
         if self.summaryEdit.text():
-            code += '{0}description="{1}",{2}'.format(
+            sourceCode += '{0}description="{1}",{2}'.format(
                 istring, self.summaryEdit.text(), os.linesep)
         
         if self.descriptionFromFilesCheckBox.isChecked():
-            code += '{0}long_description=get_long_description(),{1}'.format(
+            sourceCode += '{0}long_description=get_long_description(),{1}'.format(
                 istring, os.linesep)
         elif self.descriptionEdit.toPlainText():
-            code += '{0}long_description="""{1}""",{2}'.format(
+            sourceCode += '{0}long_description="""{1}""",{2}'.format(
                 istring, self.descriptionEdit.toPlainText(), os.linesep)
         
         if self.authorEdit.text():
-            code += '{0}author="{1}",{2}'.format(
+            sourceCode += '{0}author="{1}",{2}'.format(
                 istring, self.authorEdit.text(), os.linesep)
-            code += '{0}author_email="{1}",{2}'.format(
+            sourceCode += '{0}author_email="{1}",{2}'.format(
                 istring, self.authorEmailEdit.text(), os.linesep)
         
         if self.maintainerEdit.text():
-            code += '{0}maintainer="{1}",{2}'.format(
+            sourceCode += '{0}maintainer="{1}",{2}'.format(
                 istring, self.maintainerEdit.text(), os.linesep)
-            code += '{0}maintainer_email="{1}",{2}'.format(
+            sourceCode += '{0}maintainer_email="{1}",{2}'.format(
                 istring, self.maintainerEmailEdit.text(), os.linesep)
         
-        code += '{0}url="{1}",{2}'.format(
+        sourceCode += '{0}url="{1}",{2}'.format(
             istring, self.homePageUrlEdit.text(), os.linesep)
         if self.downloadUrlEdit.text():
-            code += '{0}download_url="{1}",{2}'.format(
+            sourceCode += '{0}download_url="{1}",{2}'.format(
                 istring, self.downloadUrlEdit.text(), os.linesep)
         
         classifiers = []
         if not self.licenseClassifierCheckBox.isChecked():
-            code += '{0}license="{1}",{2}'.format(
+            sourceCode += '{0}license="{1}",{2}'.format(
                 istring, self.licenseEdit.text(), os.linesep)
         else:
             classifiers.append(
@@ -347,12 +287,12 @@
         
         platforms = self.platformsEdit.toPlainText().splitlines()
         if platforms:
-            code += '{0}platforms=[{1}'.format(istring, os.linesep)
-            code += '{0}"{1}"{2}'.format(
+            sourceCode += '{0}platforms=[{1}'.format(istring, os.linesep)
+            sourceCode += '{0}"{1}"{2}'.format(
                 i1string,
                 '",{0}{1}"'.format(os.linesep, i1string).join(platforms),
                 os.linesep)
-            code += '{0}],{1}'.format(istring, os.linesep)
+            sourceCode += '{0}],{1}'.format(istring, os.linesep)
         
         if self.developmentStatusComboBox.currentIndex() != 0:
             classifiers.append(
@@ -369,19 +309,19 @@
         # cleanup classifiers list - remove all invalid entries
         classifiers = [c for c in classifiers if bool(c)]
         if classifiers:
-            code += '{0}classifiers=[{1}'.format(istring, os.linesep)
-            code += '{0}"{1}"{2}'.format(
+            sourceCode += '{0}classifiers=[{1}'.format(istring, os.linesep)
+            sourceCode += '{0}"{1}"{2}'.format(
                 i1string,
                 '",{0}{1}"'.format(os.linesep, i1string).join(classifiers),
                 os.linesep)
-            code += '{0}],{1}'.format(istring, os.linesep)
+            sourceCode += '{0}],{1}'.format(istring, os.linesep)
         del classifiers
         
         if self.keywordsEdit.text():
-            code += '{0}keywords="{1}",{2}'.format(
+            sourceCode += '{0}keywords="{1}",{2}'.format(
                 istring, self.keywordsEdit.text(), os.linesep)
         
-        code += '{0}packages=find_packages('.format(istring)
+        sourceCode += '{0}packages=find_packages('.format(istring)
         src = Utilities.fromNativeSeparators(
             self.sourceDirectoryPicker.text())
         excludePatterns = []
@@ -389,51 +329,51 @@
             excludePatterns.append(
                 self.excludePatternList.item(row).text())
         if src:
-            code += '{0}{1}"{2}"'.format(os.linesep, i1string, src)
+            sourceCode += '{0}{1}"{2}"'.format(os.linesep, i1string, src)
             if excludePatterns:
-                code += ','
+                sourceCode += ','
             else:
-                code += '{0}{1}'.format(os.linesep, istring)
+                sourceCode += '{0}{1}'.format(os.linesep, istring)
         if excludePatterns:
-            code += '{0}{1}exclude=[{0}'.format(os.linesep, i1string)
-            code += '{0}"{1}"{2}'.format(
+            sourceCode += '{0}{1}exclude=[{0}'.format(os.linesep, i1string)
+            sourceCode += '{0}"{1}"{2}'.format(
                 i2string,
                 '",{0}{1}"'.format(os.linesep, i2string)
                 .join(excludePatterns),
                 os.linesep)
-            code += '{0}]{1}{2}'.format(i1string, os.linesep, istring)
-        code += '),{0}'.format(os.linesep)
+            sourceCode += '{0}]{1}{2}'.format(i1string, os.linesep, istring)
+        sourceCode += '),{0}'.format(os.linesep)
         
         if self.includePackageDataCheckBox.isChecked():
-            code += '{0}include_package_data = True,{1}'.format(
+            sourceCode += '{0}include_package_data = True,{1}'.format(
                 istring, os.linesep)
         
         modules = []
         for row in range(self.modulesList.count()):
             modules.append(self.modulesList.item(row).text())
         if modules:
-            code += '{0}py_modules=[{1}'.format(istring, os.linesep)
-            code += '{0}"{1}"{2}'.format(
+            sourceCode += '{0}py_modules=[{1}'.format(istring, os.linesep)
+            sourceCode += '{0}"{1}"{2}'.format(
                 i1string,
                 '",{0}{1}"'.format(os.linesep, i1string).join(modules),
                 os.linesep)
-            code += '{0}],{1}'.format(istring, os.linesep)
+            sourceCode += '{0}],{1}'.format(istring, os.linesep)
         del modules
         
         scripts = []
         for row in range(self.scriptsList.count()):
             scripts.append(self.scriptsList.item(row).text())
         if scripts:
-            code += '{0}scripts=[{1}'.format(istring, os.linesep)
-            code += '{0}"{1}"{2}'.format(
+            sourceCode += '{0}scripts=[{1}'.format(istring, os.linesep)
+            sourceCode += '{0}"{1}"{2}'.format(
                 i1string,
                 '",{0}{1}"'.format(os.linesep, i1string).join(scripts),
                 os.linesep)
-            code += '{0}],{1}'.format(istring, os.linesep)
+            sourceCode += '{0}],{1}'.format(istring, os.linesep)
         del scripts
         
-        code += "){0}".format(estring)
-        return code
+        sourceCode += "){0}".format(estring)
+        return sourceCode
     
     @pyqtSlot()
     def on_projectButton_clicked(self):
@@ -471,7 +411,8 @@
         """
         Private method to get the start directory for selection dialogs.
         
-        @return start directory (string)
+        @return start directory
+        @rtype str
         """
         return (Preferences.getMultiProject("Workspace") or
                 Utilities.getHomeDir())
@@ -593,7 +534,8 @@
         """
         Private slot to handle a change of the exclude pattern text.
         
-        @param txt text of the line edit (string)
+        @param txt text of the line edit
+        @type str
         """
         self.addExludePatternButton.setEnabled(bool(txt))
     

eric ide

mercurial