Extended the Python code scanners to be compatible with Python 3.12. eric7

Thu, 28 Sep 2023 14:02:15 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 28 Sep 2023 14:02:15 +0200
branch
eric7
changeset 10216
c07a1ef5c5d3
parent 10215
d476667171a1
child 10217
7888177e7463
child 10218
8d430aaf4a7a

Extended the Python code scanners to be compatible with Python 3.12.

src/eric7/Utilities/ClassBrowsers/pyclbr.py file | annotate | diff | comparison | revisions
src/eric7/Utilities/ModuleParser.py file | annotate | diff | comparison | revisions
--- a/src/eric7/Utilities/ClassBrowsers/pyclbr.py	Tue Sep 26 18:26:21 2023 +0200
+++ b/src/eric7/Utilities/ClassBrowsers/pyclbr.py	Thu Sep 28 14:02:15 2023 +0200
@@ -10,6 +10,7 @@
 to find out the superclasses of a class as well as its attributes.
 """
 
+import keyword
 import re
 import sys
 
@@ -71,7 +72,7 @@
         (?P<MethodIndent> [ \t]* )
         (?: async [ \t]+ )? (?: cdef | cpdef | def) [ \t]+
         (?P<MethodName> \w+ )
-        (?: [ \t]* \[ (?: plain | html ) \] )?
+        (?: [ \t]* \[ [^\]]+ \] )?
         [ \t]* \(
         (?P<MethodSignature> (?: [^)] | \)[ \t]*,? )*? )
         \) [ \t]*
@@ -85,6 +86,7 @@
         (?: cdef [ \t]+ )?
         class [ \t]+
         (?P<ClassName> \w+ )
+        (?: [ \t]* \[ [^\]]+ \] )?
         [ \t]*
         (?P<ClassSupers> \( [^)]* \) )?
         [ \t]* :
@@ -95,6 +97,7 @@
         (?P<AttributeIndent> [ \t]* )
         self [ \t]* \. [ \t]*
         (?P<AttributeName> \w+ )
+        (?: [ \t]* : [^=\n]+ )?
         [ \t]* =
     )
 
@@ -105,6 +108,13 @@
         [ \t]* =
     )
 
+|   (?P<TypedVariable>
+        ^
+        (?P<TypedVariableIndent> [ \t]* )
+        (?P<TypedVariableName> \w+ )
+        [ \t]* :
+    )
+
 |   (?P<Main>
         ^
         if \s+ __name__ \s* == \s* [^:]+ : $
@@ -654,6 +664,36 @@
                             )
                         break
 
+        elif m.captured("TypedVariable"):
+            thisindent = _indent(m.captured("TypedVariableIndent"))
+            variable_name = m.captured("TypedVariableName")
+            if not keyword.iskeyword(variable_name):
+                # only if the determined name is not a keyword (e.g. else, except)
+                lineno += src.count("\n", last_lineno_pos, start)
+                last_lineno_pos = start
+                if thisindent == 0 or not classstack:
+                    # global variable, reset class stack first
+                    classstack = []
+
+                    if "@@Globals@@" not in dictionary:
+                        dictionary["@@Globals@@"] = ClbrBaseClasses.ClbrBase(
+                            module, "Globals", file, lineno
+                        )
+                    dictionary["@@Globals@@"]._addglobal(
+                        Attribute(module, variable_name, file, lineno)
+                    )
+                else:
+                    index = -1
+                    while index >= -len(classstack):
+                        if classstack[index][1] >= thisindent:
+                            index -= 1
+                        else:
+                            if isinstance(classstack[index][0], Class):
+                                classstack[index][0]._addglobal(
+                                    Attribute(module, variable_name, file, lineno)
+                                )
+                            break
+
         elif m.captured("Publics"):
             idents = m.captured("Identifiers")
             lineno += src.count("\n", last_lineno_pos, start)
--- a/src/eric7/Utilities/ModuleParser.py	Tue Sep 26 18:26:21 2023 +0200
+++ b/src/eric7/Utilities/ModuleParser.py	Thu Sep 28 14:02:15 2023 +0200
@@ -16,6 +16,7 @@
 
 import contextlib
 import importlib.machinery
+import keyword
 import os
 import re
 import sys
@@ -68,7 +69,7 @@
     (?P<Comment>
         \# .*? $   # ignore everything in comments
     )
-    
+
 |   (?P<String>
         \""" (?P<StringContents1>
                [^"\\]* (?:
@@ -145,7 +146,7 @@
         (?P<MethodIndent> [ \t]* )
         (?: async [ \t]+ )? (?: cdef | cpdef | def) [ \t]+
         (?P<MethodName> \w+ )
-        (?: [ \t]* \[ (?: plain | html ) \] )?
+        (?: [ \t]* \[ [^\]]+ \] )?
         [ \t]* \(
         (?P<MethodSignature> (?: [^)] | \)[ \t]*,? )*? )
         \) [ \t]*
@@ -159,6 +160,7 @@
         (?: cdef [ \t]+ )?
         class [ \t]+
         (?P<ClassName> \w+ )
+        (?: [ \t]* \[ [^\]]+ \] )?
         [ \t]*
         (?P<ClassSupers> \( [^)]* \) )?
         [ \t]* :
@@ -169,6 +171,7 @@
         (?P<AttributeIndent> [ \t]* )
         self [ \t]* \. [ \t]*
         (?P<AttributeName> \w+ )
+        (?: [ \t]* : [^=\n]+ )?
         [ \t]* =
     )
 
@@ -179,6 +182,13 @@
         [ \t]* = [ \t]* (?P<VariableSignal> (?:pyqtSignal)? )
     )
 
+|   (?P<TypedVariable>
+        ^
+        (?P<TypedVariableIndent> [ \t]* )
+        (?P<TypedVariableName> \w+ )
+        [ \t]* :
+    )
+
 |   (?P<Main>
         ^
         if \s+ __name__ \s* == \s* [^:]+ : $
@@ -839,6 +849,34 @@
                                 classstack[index][0].addGlobal(variable_name, attr)
                             break
 
+            elif m.start("TypedVariable") >= 0:
+                thisindent = _indent(m.group("TypedVariableIndent"))
+                variable_name = m.group("TypedVariableName")
+                if not keyword.iskeyword(variable_name):
+                    # only if the determined name is not a keyword (e.g. else, except)
+                    lineno += src.count("\n", last_lineno_pos, start)
+                    last_lineno_pos = start
+                    if thisindent == 0:
+                        # global variable
+                        attr = Attribute(self.name, variable_name, self.file, lineno)
+                        self.__py_setVisibility(attr)
+                        self.addGlobal(variable_name, attr)
+                    else:
+                        index = -1
+                        while index >= -len(classstack):
+                            if classstack[index][1] >= thisindent:
+                                index -= 1
+                            else:
+                                if classstack[index][0] is not None and isinstance(
+                                    classstack[index][0], Class
+                                ):
+                                    attr = Attribute(
+                                        self.name, variable_name, self.file, lineno
+                                    )
+                                    self.__py_setVisibility(attr)
+                                    classstack[index][0].addGlobal(variable_name, attr)
+                                break
+
             elif m.start("Import") >= 0:
                 # - import module
                 names = [

eric ide

mercurial