src/eric7/Graphics/ImportsDiagramBuilder.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9278
36448ca469c2
--- a/src/eric7/Graphics/ImportsDiagramBuilder.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/Graphics/ImportsDiagramBuilder.py	Wed Jul 13 14:55:47 2022 +0200
@@ -24,15 +24,15 @@
 class ImportsDiagramBuilder(UMLDiagramBuilder):
     """
     Class implementing a builder for imports diagrams of a package.
-    
+
     Note: Only package internal imports are shown in order to maintain
     some readability.
     """
-    def __init__(self, dialog, view, project, package,
-                 showExternalImports=False):
+
+    def __init__(self, dialog, view, project, package, showExternalImports=False):
         """
         Constructor
-        
+
         @param dialog reference to the UML dialog
         @type UMLDialog
         @param view reference to the view object
@@ -48,68 +48,70 @@
         """
         super().__init__(dialog, view, project)
         self.setObjectName("ImportsDiagram")
-        
+
         self.showExternalImports = showExternalImports
         self.packagePath = os.path.abspath(package)
-        
+
         self.__relPackagePath = (
             self.project.getRelativePath(self.packagePath)
-            if self.project.isProjectSource(self.packagePath) else
-            ""
+            if self.project.isProjectSource(self.packagePath)
+            else ""
         )
-    
+
     def initialize(self):
         """
         Public method to initialize the object.
         """
-        self.package = os.path.splitdrive(self.packagePath)[1].replace(
-            os.sep, '.')[1:]
+        self.package = os.path.splitdrive(self.packagePath)[1].replace(os.sep, ".")[1:]
         hasInit = True
         ppath = self.packagePath
         while hasInit:
             ppath = os.path.dirname(ppath)
-            hasInit = len(glob.glob(os.path.join(ppath, '__init__.*'))) > 0
-        self.shortPackage = self.packagePath.replace(ppath, '').replace(
-            os.sep, '.')[1:]
-        
+            hasInit = len(glob.glob(os.path.join(ppath, "__init__.*"))) > 0
+        self.shortPackage = self.packagePath.replace(ppath, "").replace(os.sep, ".")[1:]
+
         pname = self.project.getProjectName()
         name = (
             self.tr("Imports Diagramm {0}: {1}").format(
-                pname, self.project.getRelativePath(self.packagePath))
-            if pname else
-            self.tr("Imports Diagramm: {0}").format(self.packagePath)
+                pname, self.project.getRelativePath(self.packagePath)
+            )
+            if pname
+            else self.tr("Imports Diagramm: {0}").format(self.packagePath)
         )
         self.umlView.setDiagramName(name)
-    
+
     def __buildModulesDict(self):
         """
         Private method to build a dictionary of modules contained in the
         package.
-        
+
         @return dictionary of modules contained in the package
         @rtype dict
         """
         import Utilities.ModuleParser
-        extensions = (
-            Preferences.getPython("Python3Extensions")
-        )
+
+        extensions = Preferences.getPython("Python3Extensions")
         moduleDict = {}
         modules = []
-        for ext in (
-            Preferences.getPython("Python3Extensions")
-        ):
-            modules.extend(glob.glob(Utilities.normjoinpath(
-                self.packagePath, '*{0}'.format(ext))))
-        
+        for ext in Preferences.getPython("Python3Extensions"):
+            modules.extend(
+                glob.glob(Utilities.normjoinpath(self.packagePath, "*{0}".format(ext)))
+            )
+
         tot = len(modules)
         progress = EricProgressDialog(
             self.tr("Parsing modules..."),
-            None, 0, tot, self.tr("%v/%m Modules"), self.parent())
+            None,
+            0,
+            tot,
+            self.tr("%v/%m Modules"),
+            self.parent(),
+        )
         progress.setWindowTitle(self.tr("Imports Diagramm"))
         try:
             progress.show()
             QApplication.processEvents()
-            
+
             now = time.monotonic()
             for prog, module in enumerate(modules):
                 progress.setValue(prog)
@@ -118,46 +120,50 @@
                     now = time.monotonic()
                 try:
                     mod = Utilities.ModuleParser.readModule(
-                        module, extensions=extensions, caching=False)
+                        module, extensions=extensions, caching=False
+                    )
                 except ImportError:
                     continue
                 else:
                     name = mod.name
                     if name.startswith(self.package):
-                        name = name[len(self.package) + 1:]
+                        name = name[len(self.package) + 1 :]
                     moduleDict[name] = mod
         finally:
             progress.setValue(tot)
             progress.deleteLater()
         return moduleDict
-    
+
     def buildDiagram(self):
         """
         Public method to build the modules shapes of the diagram.
         """
-        initlist = glob.glob(os.path.join(self.packagePath, '__init__.*'))
+        initlist = glob.glob(os.path.join(self.packagePath, "__init__.*"))
         if len(initlist) == 0:
             ct = QGraphicsTextItem(None)
-            ct.setHtml(self.buildErrorMessage(
-                self.tr("The directory <b>'{0}'</b> is not a Python"
-                        " package.").format(self.package)
-            ))
+            ct.setHtml(
+                self.buildErrorMessage(
+                    self.tr(
+                        "The directory <b>'{0}'</b> is not a Python" " package."
+                    ).format(self.package)
+                )
+            )
             self.scene.addItem(ct)
             return
-        
+
         self.__shapes = {}
-        
+
         modules = self.__buildModulesDict()
         externalMods = []
-        packageList = self.shortPackage.split('.')
+        packageList = self.shortPackage.split(".")
         packageListLen = len(packageList)
         for module in sorted(modules.keys()):
             impLst = []
             for importName in modules[module].imports:
                 n = (
-                    importName[len(self.package) + 1:]
-                    if importName.startswith(self.package) else
-                    importName
+                    importName[len(self.package) + 1 :]
+                    if importName.startswith(self.package)
+                    else importName
                 )
                 if importName in modules:
                     impLst.append(n)
@@ -166,20 +172,21 @@
                     if n not in externalMods:
                         externalMods.append(n)
             for importName in list(modules[module].from_imports.keys()):
-                if importName.startswith('.'):
-                    dots = len(importName) - len(importName.lstrip('.'))
+                if importName.startswith("."):
+                    dots = len(importName) - len(importName.lstrip("."))
                     if dots == 1:
                         n = importName[1:]
                         importName = n
                     else:
                         if self.showExternalImports:
-                            n = '.'.join(
-                                packageList[:packageListLen - dots + 1] +
-                                [importName[dots:]])
+                            n = ".".join(
+                                packageList[: packageListLen - dots + 1]
+                                + [importName[dots:]]
+                            )
                         else:
                             n = importName
                 elif importName.startswith(self.package):
-                    n = importName[len(self.package) + 1:]
+                    n = importName[len(self.package) + 1 :]
                 else:
                     n = importName
                 if importName in modules:
@@ -188,7 +195,7 @@
                     impLst.append(n)
                     if n not in externalMods:
                         externalMods.append(n)
-            
+
             classNames = []
             for class_ in list(modules[module].classes.keys()):
                 className = modules[module].classes[class_].name
@@ -196,11 +203,11 @@
                     classNames.append(className)
             shape = self.__addModule(module, classNames, 0.0, 0.0)
             self.__shapes[module] = (shape, impLst)
-        
+
         for module in externalMods:
             shape = self.__addModule(module, [], 0.0, 0.0)
             self.__shapes[module] = (shape, [])
-        
+
         # build a list of routes
         nodes = []
         routes = []
@@ -210,15 +217,15 @@
                 route = (module, rel)
                 if route not in routes:
                     routes.append(route)
-        
+
         self.__arrangeNodes(nodes, routes[:])
         self.__createAssociations(routes)
         self.umlView.autoAdjustSceneSize(limit=True)
-    
+
     def __addModule(self, name, classes, x, y):
         """
         Private method to add a module to the diagram.
-        
+
         @param name module name to be shown
         @type str
         @param classes list of class names contained in the module
@@ -231,19 +238,21 @@
         @rtype ModuleItem
         """
         from .ModuleItem import ModuleItem, ModuleModel
+
         classes.sort()
         impM = ModuleModel(name, classes)
-        impW = ModuleItem(impM, x, y, scene=self.scene,
-                          colors=self.umlView.getDrawingColors())
+        impW = ModuleItem(
+            impM, x, y, scene=self.scene, colors=self.umlView.getDrawingColors()
+        )
         impW.setId(self.umlView.getItemId())
         return impW
-    
+
     def __arrangeNodes(self, nodes, routes, whiteSpaceFactor=1.2):
         """
         Private method to arrange the shapes on the canvas.
-        
+
         The algorithm is borrowed from Boa Constructor.
-        
+
         @param nodes list of nodes to arrange
         @type list of str
         @param routes list of routes
@@ -253,16 +262,16 @@
         @type float
         """
         from . import GraphicsUtilities
+
         generations = GraphicsUtilities.sort(nodes, routes)
-        
+
         # calculate width and height of all elements
         sizes = []
         for generation in generations:
             sizes.append([])
             for child in generation:
-                sizes[-1].append(
-                    self.__shapes[child][0].sceneBoundingRect())
-                
+                sizes[-1].append(self.__shapes[child][0].sceneBoundingRect())
+
         # calculate total width and total height
         width = 0
         height = 0
@@ -271,72 +280,71 @@
         for generation in sizes:
             currentWidth = 0
             currentHeight = 0
-            
+
             for rect in generation:
                 if rect.height() > currentHeight:
                     currentHeight = rect.height()
                 currentWidth += rect.width()
-                
+
             # update totals
             if currentWidth > width:
                 width = currentWidth
             height += currentHeight
-            
+
             # store generation info
             widths.append(currentWidth)
             heights.append(currentHeight)
-        
+
         # add in some whitespace
         width *= whiteSpaceFactor
         height = height * whiteSpaceFactor - 20
         verticalWhiteSpace = 40.0
-        
+
         sceneRect = self.umlView.sceneRect()
         width += 50.0
         height += 50.0
         swidth = sceneRect.width() if width < sceneRect.width() else width
         sheight = sceneRect.height() if height < sceneRect.height() else height
         self.umlView.setSceneSize(swidth, sheight)
-        
+
         # distribute each generation across the width and the
         # generations across height
         y = 10.0
-        for currentWidth, currentHeight, generation in (
-            zip(reversed(widths), reversed(heights), reversed(generations))
+        for currentWidth, currentHeight, generation in zip(
+            reversed(widths), reversed(heights), reversed(generations)
         ):
             x = 10.0
             # whiteSpace is the space between any two elements
-            whiteSpace = (
-                (width - currentWidth - 20) /
-                (len(generation) - 1.0 or 2.0)
-            )
+            whiteSpace = (width - currentWidth - 20) / (len(generation) - 1.0 or 2.0)
             for name in generation:
                 shape = self.__shapes[name][0]
                 shape.setPos(x, y)
                 rect = shape.sceneBoundingRect()
                 x = x + rect.width() + whiteSpace
             y = y + currentHeight + verticalWhiteSpace
-    
+
     def __createAssociations(self, routes):
         """
         Private method to generate the associations between the module shapes.
-        
+
         @param routes list of associations
         @type list of tuple of (str, str)
         """
         from .AssociationItem import AssociationItem, AssociationType
+
         for route in routes:
             assoc = AssociationItem(
                 self.__shapes[route[0]][0],
                 self.__shapes[route[1]][0],
                 AssociationType.IMPORTS,
-                colors=self.umlView.getDrawingColors())
+                colors=self.umlView.getDrawingColors(),
+            )
             self.scene.addItem(assoc)
-    
+
     def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
-        
+
         @param version version of the data
         @type str
         @param data persisted data to be parsed
@@ -346,24 +354,23 @@
         """
         parts = data.split(", ")
         if (
-            len(parts) != 2 or
-            not parts[0].startswith("package=") or
-            not parts[1].startswith("show_external=")
+            len(parts) != 2
+            or not parts[0].startswith("package=")
+            or not parts[1].startswith("show_external=")
         ):
             return False
-        
+
         self.packagePath = parts[0].split("=", 1)[1].strip()
-        self.showExternalImports = Utilities.toBool(
-            parts[1].split("=", 1)[1].strip())
-        
+        self.showExternalImports = Utilities.toBool(parts[1].split("=", 1)[1].strip())
+
         self.initialize()
-        
+
         return True
-    
+
     def toDict(self):
         """
         Public method to collect data to be persisted.
-        
+
         @return dictionary containing data to be persisted
         @rtype dict
         """
@@ -371,19 +378,19 @@
             "project_name": self.project.getProjectName(),
             "show_external": self.showExternalImports,
         }
-        
+
         data["package"] = (
             Utilities.fromNativeSeparators(self.__relPackagePath)
-            if self.__relPackagePath else
-            Utilities.fromNativeSeparators(self.packagePath)
+            if self.__relPackagePath
+            else Utilities.fromNativeSeparators(self.packagePath)
         )
-        
+
         return data
-    
+
     def fromDict(self, version, data):
         """
         Public method to populate the class with data persisted by 'toDict()'.
-        
+
         @param version version of the data
         @type str
         @param data dictionary containing the persisted data
@@ -394,7 +401,7 @@
         """
         try:
             self.showExternalImports = data["show_external"]
-            
+
             packagePath = Utilities.toNativeSeparators(data["package"])
             if os.path.isabs(packagePath):
                 self.packagePath = packagePath
@@ -407,12 +414,12 @@
                         " Please open it and try again.</p>"
                     ).format(data["project_name"])
                     return False, msg
-                
+
                 self.__relPackagePath = packagePath
                 self.package = self.project.getAbsolutePath(packagePath)
         except KeyError:
             return False, ""
-        
+
         self.initialize()
-        
+
         return True, ""

eric ide

mercurial