src/eric7/Utilities/ClassBrowsers/pyclbr.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
130 (?P<ImportFromList> 130 (?P<ImportFromList>
131 (?: \( \s* .*? \s* \) ) 131 (?: \( \s* .*? \s* \) )
132 | 132 |
133 (?: [^#;\\\n]* (?: \\\n )* )* ) 133 (?: [^#;\\\n]* (?: \\\n )* )* )
134 )""", 134 )""",
135 re.VERBOSE | re.DOTALL | re.MULTILINE).search 135 re.VERBOSE | re.DOTALL | re.MULTILINE,
136 ).search
136 137
137 _commentsub = re.compile(r"""#[^\n]*\n|#[^\n]*$""").sub 138 _commentsub = re.compile(r"""#[^\n]*\n|#[^\n]*$""").sub
138 139
139 _modules = {} # cache of modules we've seen 140 _modules = {} # cache of modules we've seen
140 141
141 142
142 class VisibilityMixin(ClbrBaseClasses.ClbrVisibilityMixinBase): 143 class VisibilityMixin(ClbrBaseClasses.ClbrVisibilityMixinBase):
143 """ 144 """
144 Mixin class implementing the notion of visibility. 145 Mixin class implementing the notion of visibility.
145 """ 146 """
147
146 def __init__(self): 148 def __init__(self):
147 """ 149 """
148 Constructor 150 Constructor
149 """ 151 """
150 if self.name.startswith('__'): 152 if self.name.startswith("__"):
151 self.setPrivate() 153 self.setPrivate()
152 elif self.name.startswith('_'): 154 elif self.name.startswith("_"):
153 self.setProtected() 155 self.setProtected()
154 else: 156 else:
155 self.setPublic() 157 self.setPublic()
156 158
157 159
158 class Class(ClbrBaseClasses.Class, VisibilityMixin): 160 class Class(ClbrBaseClasses.Class, VisibilityMixin):
159 """ 161 """
160 Class to represent a Python class. 162 Class to represent a Python class.
161 """ 163 """
164
162 def __init__(self, module, name, superClasses, file, lineno): 165 def __init__(self, module, name, superClasses, file, lineno):
163 """ 166 """
164 Constructor 167 Constructor
165 168
166 @param module name of the module containing this class 169 @param module name of the module containing this class
167 @param name name of this class 170 @param name name of this class
168 @param superClasses list of class names this class is inherited from 171 @param superClasses list of class names this class is inherited from
169 @param file filename containing this class 172 @param file filename containing this class
170 @param lineno linenumber of the class definition 173 @param lineno linenumber of the class definition
171 """ 174 """
172 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, 175 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, lineno)
173 lineno)
174 VisibilityMixin.__init__(self) 176 VisibilityMixin.__init__(self)
175 177
176 178
177 class Function(ClbrBaseClasses.Function, VisibilityMixin): 179 class Function(ClbrBaseClasses.Function, VisibilityMixin):
178 """ 180 """
179 Class to represent a Python function. 181 Class to represent a Python function.
180 """ 182 """
181 def __init__(self, module, name, file, lineno, signature='', separator=',', 183
182 modifierType=ClbrBaseClasses.Function.General, annotation=""): 184 def __init__(
185 self,
186 module,
187 name,
188 file,
189 lineno,
190 signature="",
191 separator=",",
192 modifierType=ClbrBaseClasses.Function.General,
193 annotation="",
194 ):
183 """ 195 """
184 Constructor 196 Constructor
185 197
186 @param module name of the module containing this function 198 @param module name of the module containing this function
187 @param name name of this function 199 @param name name of this function
188 @param file filename containing this class 200 @param file filename containing this class
189 @param lineno linenumber of the class definition 201 @param lineno linenumber of the class definition
190 @param signature parameterlist of the method 202 @param signature parameterlist of the method
191 @param separator string separating the parameters 203 @param separator string separating the parameters
192 @param modifierType type of the function 204 @param modifierType type of the function
193 @param annotation return annotation 205 @param annotation return annotation
194 """ 206 """
195 ClbrBaseClasses.Function.__init__(self, module, name, file, lineno, 207 ClbrBaseClasses.Function.__init__(
196 signature, separator, modifierType, 208 self,
197 annotation) 209 module,
210 name,
211 file,
212 lineno,
213 signature,
214 separator,
215 modifierType,
216 annotation,
217 )
198 VisibilityMixin.__init__(self) 218 VisibilityMixin.__init__(self)
199 219
200 220
201 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin): 221 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin):
202 """ 222 """
203 Class to represent a class attribute. 223 Class to represent a class attribute.
204 """ 224 """
225
205 def __init__(self, module, name, file, lineno): 226 def __init__(self, module, name, file, lineno):
206 """ 227 """
207 Constructor 228 Constructor
208 229
209 @param module name of the module containing this class 230 @param module name of the module containing this class
210 @param name name of this class 231 @param name name of this class
211 @param file filename containing this attribute 232 @param file filename containing this attribute
212 @param lineno linenumber of the class definition 233 @param lineno linenumber of the class definition
213 """ 234 """
217 238
218 class Publics: 239 class Publics:
219 """ 240 """
220 Class to represent the list of public identifiers. 241 Class to represent the list of public identifiers.
221 """ 242 """
243
222 def __init__(self, module, file, lineno, idents): 244 def __init__(self, module, file, lineno, idents):
223 """ 245 """
224 Constructor 246 Constructor
225 247
226 @param module name of the module containing this function 248 @param module name of the module containing this function
227 @param file filename containing this class 249 @param file filename containing this class
228 @param lineno linenumber of the class definition 250 @param lineno linenumber of the class definition
229 @param idents list of public identifiers 251 @param idents list of public identifiers
230 """ 252 """
231 self.module = module 253 self.module = module
232 self.name = '__all__' 254 self.name = "__all__"
233 self.file = file 255 self.file = file
234 self.lineno = lineno 256 self.lineno = lineno
235 self.identifiers = [e.replace('"', '').replace("'", "").strip() 257 self.identifiers = [
236 for e in idents.split(',')] 258 e.replace('"', "").replace("'", "").strip() for e in idents.split(",")
259 ]
237 260
238 261
239 class Imports: 262 class Imports:
240 """ 263 """
241 Class to represent the list of imported modules. 264 Class to represent the list of imported modules.
242 """ 265 """
266
243 def __init__(self, module, file): 267 def __init__(self, module, file):
244 """ 268 """
245 Constructor 269 Constructor
246 270
247 @param module name of the module containing the import (string) 271 @param module name of the module containing the import (string)
248 @param file file name containing the import (string) 272 @param file file name containing the import (string)
249 """ 273 """
250 self.module = module 274 self.module = module
251 self.name = 'import' 275 self.name = "import"
252 self.file = file 276 self.file = file
253 self.imports = {} 277 self.imports = {}
254 278
255 def addImport(self, moduleName, names, lineno): 279 def addImport(self, moduleName, names, lineno):
256 """ 280 """
257 Public method to add a list of imported names. 281 Public method to add a list of imported names.
258 282
259 @param moduleName name of the imported module (string) 283 @param moduleName name of the imported module (string)
260 @param names list of names (list of strings) 284 @param names list of names (list of strings)
261 @param lineno line number of the import 285 @param lineno line number of the import
262 """ 286 """
263 if moduleName not in self.imports: 287 if moduleName not in self.imports:
264 module = ImportedModule(self.module, self.file, moduleName) 288 module = ImportedModule(self.module, self.file, moduleName)
265 self.imports[moduleName] = module 289 self.imports[moduleName] = module
266 else: 290 else:
267 module = self.imports[moduleName] 291 module = self.imports[moduleName]
268 module.addImport(lineno, names) 292 module.addImport(lineno, names)
269 293
270 def getImport(self, moduleName): 294 def getImport(self, moduleName):
271 """ 295 """
272 Public method to get an imported module item. 296 Public method to get an imported module item.
273 297
274 @param moduleName name of the imported module (string) 298 @param moduleName name of the imported module (string)
275 @return imported module item (ImportedModule) or None 299 @return imported module item (ImportedModule) or None
276 """ 300 """
277 if moduleName in self.imports: 301 if moduleName in self.imports:
278 return self.imports[moduleName] 302 return self.imports[moduleName]
279 else: 303 else:
280 return None 304 return None
281 305
282 def getImports(self): 306 def getImports(self):
283 """ 307 """
284 Public method to get all imported module names. 308 Public method to get all imported module names.
285 309
286 @return dictionary of imported module names with name as key and list 310 @return dictionary of imported module names with name as key and list
287 of line numbers of imports as value 311 of line numbers of imports as value
288 """ 312 """
289 return self.imports 313 return self.imports
290 314
291 315
292 class ImportedModule: 316 class ImportedModule:
293 """ 317 """
294 Class to represent an imported module. 318 Class to represent an imported module.
295 """ 319 """
320
296 def __init__(self, module, file, importedModule): 321 def __init__(self, module, file, importedModule):
297 """ 322 """
298 Constructor 323 Constructor
299 324
300 @param module name of the module containing the import (string) 325 @param module name of the module containing the import (string)
301 @param file file name containing the import (string) 326 @param file file name containing the import (string)
302 @param importedModule name of the imported module (string) 327 @param importedModule name of the imported module (string)
303 """ 328 """
304 self.module = module 329 self.module = module
305 self.name = 'import' 330 self.name = "import"
306 self.file = file 331 self.file = file
307 self.importedModuleName = importedModule 332 self.importedModuleName = importedModule
308 self.linenos = [] 333 self.linenos = []
309 self.importedNames = {} 334 self.importedNames = {}
310 # dictionary of imported names with name as key and list of line 335 # dictionary of imported names with name as key and list of line
311 # numbers as value 336 # numbers as value
312 337
313 def addImport(self, lineno, importedNames): 338 def addImport(self, lineno, importedNames):
314 """ 339 """
315 Public method to add a list of imported names. 340 Public method to add a list of imported names.
316 341
317 @param lineno line number of the import 342 @param lineno line number of the import
318 @param importedNames list of imported names (list of strings) 343 @param importedNames list of imported names (list of strings)
319 """ 344 """
320 if lineno not in self.linenos: 345 if lineno not in self.linenos:
321 self.linenos.append(lineno) 346 self.linenos.append(lineno)
322 347
323 for name in importedNames: 348 for name in importedNames:
324 if name not in self.importedNames: 349 if name not in self.importedNames:
325 self.importedNames[name] = [lineno] 350 self.importedNames[name] = [lineno]
326 else: 351 else:
327 self.importedNames[name].append(lineno) 352 self.importedNames[name].append(lineno)
328 353
329 354
330 def readmodule_ex(module, path=None, inpackage=False, isPyFile=False): 355 def readmodule_ex(module, path=None, inpackage=False, isPyFile=False):
331 """ 356 """
332 Read a module file and return a dictionary of classes. 357 Read a module file and return a dictionary of classes.
333 358
334 Search for MODULE in PATH and sys.path, read and parse the 359 Search for MODULE in PATH and sys.path, read and parse the
335 module and return a dictionary with one entry for each class 360 module and return a dictionary with one entry for each class
336 found in the module. 361 found in the module.
337 362
338 @param module name of the module file 363 @param module name of the module file
339 @type str 364 @type str
340 @param path path the module should be searched in 365 @param path path the module should be searched in
341 @type list of str 366 @type list of str
342 @param inpackage flag indicating a module inside a package is scanned 367 @param inpackage flag indicating a module inside a package is scanned
345 @type bool 370 @type bool
346 @return the resulting dictionary 371 @return the resulting dictionary
347 @rtype dict 372 @rtype dict
348 """ 373 """
349 global _modules 374 global _modules
350 375
351 if module in _modules: 376 if module in _modules:
352 # we've seen this module before... 377 # we've seen this module before...
353 return _modules[module] 378 return _modules[module]
354 if module in sys.builtin_module_names: 379 if module in sys.builtin_module_names:
355 # this is a built-in module 380 # this is a built-in module
359 # search the path for the module 384 # search the path for the module
360 path = [] if path is None else path[:] 385 path = [] if path is None else path[:]
361 f = None 386 f = None
362 if inpackage: 387 if inpackage:
363 try: 388 try:
364 f, file, (suff, mode, type) = ClassBrowsers.find_module( 389 f, file, (suff, mode, type) = ClassBrowsers.find_module(module, path)
365 module, path)
366 except ImportError: 390 except ImportError:
367 f = None 391 f = None
368 if f is None: 392 if f is None:
369 fullpath = path[:] + sys.path[:] 393 fullpath = path[:] + sys.path[:]
370 f, file, (suff, mode, type) = ClassBrowsers.find_module( 394 f, file, (suff, mode, type) = ClassBrowsers.find_module(
371 module, fullpath, isPyFile) 395 module, fullpath, isPyFile
396 )
372 if f: 397 if f:
373 f.close() 398 f.close()
374 if type not in SUPPORTED_TYPES: 399 if type not in SUPPORTED_TYPES:
375 # not Python source, can't do anything with this module 400 # not Python source, can't do anything with this module
376 _modules[module] = {} 401 _modules[module] = {}
380 src = Utilities.readEncodedFile(file)[0] 405 src = Utilities.readEncodedFile(file)[0]
381 except (UnicodeError, OSError): 406 except (UnicodeError, OSError):
382 # can't do anything with this module 407 # can't do anything with this module
383 _modules[module] = {} 408 _modules[module] = {}
384 return {} 409 return {}
385 410
386 _modules[module] = scan(src, file, module) 411 _modules[module] = scan(src, file, module)
387 return _modules[module] 412 return _modules[module]
388 413
389 414
390 def scan(src, file, module): 415 def scan(src, file, module):
391 """ 416 """
392 Public method to scan the given source text. 417 Public method to scan the given source text.
393 418
394 @param src source text to be scanned 419 @param src source text to be scanned
395 @type str 420 @type str
396 @param file file name associated with the source text 421 @param file file name associated with the source text
397 @type str 422 @type str
398 @param module module name associated with the source text 423 @param module module name associated with the source text
399 @type str 424 @type str
400 @return dictionary containing the extracted data 425 @return dictionary containing the extracted data
401 @rtype dict 426 @rtype dict
402 """ 427 """
428
403 def calculateEndline(lineno, lines, indent): 429 def calculateEndline(lineno, lines, indent):
404 """ 430 """
405 Function to calculate the end line of a class or method/function. 431 Function to calculate the end line of a class or method/function.
406 432
407 @param lineno line number to start at (one based) 433 @param lineno line number to start at (one based)
408 @type int 434 @type int
409 @param lines list of source lines 435 @param lines list of source lines
410 @type list of str 436 @type list of str
411 @param indent indent length the class/method/function definition 437 @param indent indent length the class/method/function definition
421 # a comment sign 447 # a comment sign
422 lineIndent = _indent(line.replace(line.lstrip(), "")) 448 lineIndent = _indent(line.replace(line.lstrip(), ""))
423 if lineIndent <= indent: 449 if lineIndent <= indent:
424 return lineno 450 return lineno
425 lineno += 1 451 lineno += 1
426 452
427 # nothing found 453 # nothing found
428 return -1 454 return -1
429 455
430 # convert eol markers the Python style 456 # convert eol markers the Python style
431 src = src.replace("\r\n", "\n").replace("\r", "\n") 457 src = src.replace("\r\n", "\n").replace("\r", "\n")
432 srcLines = src.splitlines() 458 srcLines = src.splitlines()
433 459
434 dictionary = {} 460 dictionary = {}
435 dict_counts = {} 461 dict_counts = {}
436 462
437 classstack = [] # stack of (class, indent) pairs 463 classstack = [] # stack of (class, indent) pairs
438 conditionalsstack = [] # stack of indents of conditional defines 464 conditionalsstack = [] # stack of indents of conditional defines
439 deltastack = [] 465 deltastack = []
440 deltaindent = 0 466 deltaindent = 0
441 deltaindentcalculated = False 467 deltaindentcalculated = False
442 468
443 lineno, last_lineno_pos = 1, 0 469 lineno, last_lineno_pos = 1, 0
444 i = 0 470 i = 0
445 modifierType = ClbrBaseClasses.Function.General 471 modifierType = ClbrBaseClasses.Function.General
446 modifierIndent = -1 472 modifierIndent = -1
447 while True: 473 while True:
451 start, i = m.span() 477 start, i = m.span()
452 478
453 if m.start("MethodModifier") >= 0: 479 if m.start("MethodModifier") >= 0:
454 modifierIndent = _indent(m.group("MethodModifierIndent")) 480 modifierIndent = _indent(m.group("MethodModifierIndent"))
455 modifierType = m.group("MethodModifierType") 481 modifierType = m.group("MethodModifierType")
456 482
457 elif m.start("Method") >= 0: 483 elif m.start("Method") >= 0:
458 # found a method definition or function 484 # found a method definition or function
459 thisindent = _indent(m.group("MethodIndent")) 485 thisindent = _indent(m.group("MethodIndent"))
460 meth_name = m.group("MethodName") 486 meth_name = m.group("MethodName")
461 meth_sig = m.group("MethodSignature") 487 meth_sig = m.group("MethodSignature")
462 meth_sig = meth_sig.replace('\\\n', '') 488 meth_sig = meth_sig.replace("\\\n", "")
463 meth_sig = _commentsub('', meth_sig) 489 meth_sig = _commentsub("", meth_sig)
464 meth_ret = m.group("MethodReturnAnnotation") 490 meth_ret = m.group("MethodReturnAnnotation")
465 meth_ret = meth_ret.replace('\\\n', '') 491 meth_ret = meth_ret.replace("\\\n", "")
466 meth_ret = _commentsub('', meth_ret) 492 meth_ret = _commentsub("", meth_ret)
467 lineno += src.count('\n', last_lineno_pos, start) 493 lineno += src.count("\n", last_lineno_pos, start)
468 last_lineno_pos = start 494 last_lineno_pos = start
469 if modifierType and modifierIndent == thisindent: 495 if modifierType and modifierIndent == thisindent:
470 if modifierType == "@staticmethod": 496 if modifierType == "@staticmethod":
471 modifier = ClbrBaseClasses.Function.Static 497 modifier = ClbrBaseClasses.Function.Static
472 elif modifierType == "@classmethod": 498 elif modifierType == "@classmethod":
482 deltastack.append(thisindent - conditionalsstack[-1]) 508 deltastack.append(thisindent - conditionalsstack[-1])
483 deltaindent = reduce(lambda x, y: x + y, deltastack) 509 deltaindent = reduce(lambda x, y: x + y, deltastack)
484 deltaindentcalculated = True 510 deltaindentcalculated = True
485 thisindent -= deltaindent 511 thisindent -= deltaindent
486 else: 512 else:
487 while ( 513 while conditionalsstack and conditionalsstack[-1] >= thisindent:
488 conditionalsstack and
489 conditionalsstack[-1] >= thisindent
490 ):
491 del conditionalsstack[-1] 514 del conditionalsstack[-1]
492 if deltastack: 515 if deltastack:
493 del deltastack[-1] 516 del deltastack[-1]
494 deltaindentcalculated = False 517 deltaindentcalculated = False
495 # close all classes indented at least as much 518 # close all classes indented at least as much
498 if classstack: 521 if classstack:
499 # it's a class method 522 # it's a class method
500 cur_class = classstack[-1][0] 523 cur_class = classstack[-1][0]
501 if cur_class: 524 if cur_class:
502 # it's a method/nested def 525 # it's a method/nested def
503 f = Function(None, meth_name, 526 f = Function(
504 file, lineno, meth_sig, annotation=meth_ret, 527 None,
505 modifierType=modifier) 528 meth_name,
529 file,
530 lineno,
531 meth_sig,
532 annotation=meth_ret,
533 modifierType=modifier,
534 )
506 cur_class._addmethod(meth_name, f) 535 cur_class._addmethod(meth_name, f)
507 else: 536 else:
508 f = None 537 f = None
509 else: 538 else:
510 # it's a function 539 # it's a function
511 f = Function(module, meth_name, 540 f = Function(
512 file, lineno, meth_sig, annotation=meth_ret, 541 module,
513 modifierType=modifier) 542 meth_name,
543 file,
544 lineno,
545 meth_sig,
546 annotation=meth_ret,
547 modifierType=modifier,
548 )
514 if meth_name in dict_counts: 549 if meth_name in dict_counts:
515 dict_counts[meth_name] += 1 550 dict_counts[meth_name] += 1
516 meth_name = "{0}_{1:d}".format( 551 meth_name = "{0}_{1:d}".format(meth_name, dict_counts[meth_name])
517 meth_name, dict_counts[meth_name])
518 else: 552 else:
519 dict_counts[meth_name] = 0 553 dict_counts[meth_name] = 0
520 dictionary[meth_name] = f 554 dictionary[meth_name] = f
521 if f: 555 if f:
522 endlineno = calculateEndline(lineno, srcLines, thisindent) 556 endlineno = calculateEndline(lineno, srcLines, thisindent)
523 f.setEndLine(endlineno) 557 f.setEndLine(endlineno)
524 classstack.append((f, thisindent)) # Marker for nested fns 558 classstack.append((f, thisindent)) # Marker for nested fns
525 559
526 # reset the modifier settings 560 # reset the modifier settings
527 modifierType = ClbrBaseClasses.Function.General 561 modifierType = ClbrBaseClasses.Function.General
528 modifierIndent = -1 562 modifierIndent = -1
529 563
530 elif m.start("String") >= 0: 564 elif m.start("String") >= 0:
534 # we found a class definition 568 # we found a class definition
535 thisindent = _indent(m.group("ClassIndent")) 569 thisindent = _indent(m.group("ClassIndent"))
536 # close all classes indented at least as much 570 # close all classes indented at least as much
537 while classstack and classstack[-1][1] >= thisindent: 571 while classstack and classstack[-1][1] >= thisindent:
538 del classstack[-1] 572 del classstack[-1]
539 lineno += src.count('\n', last_lineno_pos, start) 573 lineno += src.count("\n", last_lineno_pos, start)
540 last_lineno_pos = start 574 last_lineno_pos = start
541 class_name = m.group("ClassName") 575 class_name = m.group("ClassName")
542 inherit = m.group("ClassSupers") 576 inherit = m.group("ClassSupers")
543 if inherit: 577 if inherit:
544 # the class inherits from other classes 578 # the class inherits from other classes
545 inherit = inherit[1:-1].strip() 579 inherit = inherit[1:-1].strip()
546 inherit = _commentsub('', inherit) 580 inherit = _commentsub("", inherit)
547 names = [] 581 names = []
548 for n in inherit.split(','): 582 for n in inherit.split(","):
549 n = n.strip() 583 n = n.strip()
550 if n in dictionary: 584 if n in dictionary:
551 # we know this super class 585 # we know this super class
552 n = dictionary[n] 586 n = dictionary[n]
553 else: 587 else:
554 c = n.split('.') 588 c = n.split(".")
555 if len(c) > 1: 589 if len(c) > 1:
556 # super class 590 # super class
557 # is of the 591 # is of the
558 # form module.class: 592 # form module.class:
559 # look in 593 # look in
572 deltastack.append(thisindent - conditionalsstack[-1]) 606 deltastack.append(thisindent - conditionalsstack[-1])
573 deltaindent = reduce(lambda x, y: x + y, deltastack) 607 deltaindent = reduce(lambda x, y: x + y, deltastack)
574 deltaindentcalculated = True 608 deltaindentcalculated = True
575 thisindent -= deltaindent 609 thisindent -= deltaindent
576 else: 610 else:
577 while ( 611 while conditionalsstack and conditionalsstack[-1] >= thisindent:
578 conditionalsstack and
579 conditionalsstack[-1] >= thisindent
580 ):
581 del conditionalsstack[-1] 612 del conditionalsstack[-1]
582 if deltastack: 613 if deltastack:
583 del deltastack[-1] 614 del deltastack[-1]
584 deltaindentcalculated = False 615 deltaindentcalculated = False
585 # remember this class 616 # remember this class
586 cur_class = Class(module, class_name, inherit, 617 cur_class = Class(module, class_name, inherit, file, lineno)
587 file, lineno)
588 endlineno = calculateEndline(lineno, srcLines, thisindent) 618 endlineno = calculateEndline(lineno, srcLines, thisindent)
589 cur_class.setEndLine(endlineno) 619 cur_class.setEndLine(endlineno)
590 if not classstack: 620 if not classstack:
591 if class_name in dict_counts: 621 if class_name in dict_counts:
592 dict_counts[class_name] += 1 622 dict_counts[class_name] += 1
593 class_name = "{0}_{1:d}".format( 623 class_name = "{0}_{1:d}".format(class_name, dict_counts[class_name])
594 class_name, dict_counts[class_name])
595 else: 624 else:
596 dict_counts[class_name] = 0 625 dict_counts[class_name] = 0
597 dictionary[class_name] = cur_class 626 dictionary[class_name] = cur_class
598 else: 627 else:
599 classstack[-1][0]._addclass(class_name, cur_class) 628 classstack[-1][0]._addclass(class_name, cur_class)
600 classstack.append((cur_class, thisindent)) 629 classstack.append((cur_class, thisindent))
601 630
602 elif m.start("Attribute") >= 0: 631 elif m.start("Attribute") >= 0:
603 lineno += src.count('\n', last_lineno_pos, start) 632 lineno += src.count("\n", last_lineno_pos, start)
604 last_lineno_pos = start 633 last_lineno_pos = start
605 index = -1 634 index = -1
606 while index >= -len(classstack): 635 while index >= -len(classstack):
607 if ( 636 if classstack[index][0] is not None and not isinstance(
608 classstack[index][0] is not None and 637 classstack[index][0], Function
609 not isinstance(classstack[index][0], Function)
610 ): 638 ):
611 attr = Attribute( 639 attr = Attribute(module, m.group("AttributeName"), file, lineno)
612 module, m.group("AttributeName"), file, lineno)
613 classstack[index][0]._addattribute(attr) 640 classstack[index][0]._addattribute(attr)
614 break 641 break
615 else: 642 else:
616 index -= 1 643 index -= 1
617 644
618 elif m.start("Main") >= 0: 645 elif m.start("Main") >= 0:
619 # 'main' part of the script, reset class stack 646 # 'main' part of the script, reset class stack
620 lineno += src.count('\n', last_lineno_pos, start) 647 lineno += src.count("\n", last_lineno_pos, start)
621 last_lineno_pos = start 648 last_lineno_pos = start
622 classstack = [] 649 classstack = []
623 650
624 elif m.start("Variable") >= 0: 651 elif m.start("Variable") >= 0:
625 thisindent = _indent(m.group("VariableIndent")) 652 thisindent = _indent(m.group("VariableIndent"))
626 variable_name = m.group("VariableName") 653 variable_name = m.group("VariableName")
627 lineno += src.count('\n', last_lineno_pos, start) 654 lineno += src.count("\n", last_lineno_pos, start)
628 last_lineno_pos = start 655 last_lineno_pos = start
629 if thisindent == 0 or not classstack: 656 if thisindent == 0 or not classstack:
630 # global variable, reset class stack first 657 # global variable, reset class stack first
631 classstack = [] 658 classstack = []
632 659
633 if "@@Globals@@" not in dictionary: 660 if "@@Globals@@" not in dictionary:
634 dictionary["@@Globals@@"] = ClbrBaseClasses.ClbrBase( 661 dictionary["@@Globals@@"] = ClbrBaseClasses.ClbrBase(
635 module, "Globals", file, lineno) 662 module, "Globals", file, lineno
663 )
636 dictionary["@@Globals@@"]._addglobal( 664 dictionary["@@Globals@@"]._addglobal(
637 Attribute(module, variable_name, file, lineno)) 665 Attribute(module, variable_name, file, lineno)
666 )
638 else: 667 else:
639 index = -1 668 index = -1
640 while index >= -len(classstack): 669 while index >= -len(classstack):
641 if classstack[index][1] >= thisindent: 670 if classstack[index][1] >= thisindent:
642 index -= 1 671 index -= 1
643 else: 672 else:
644 if isinstance(classstack[index][0], Class): 673 if isinstance(classstack[index][0], Class):
645 classstack[index][0]._addglobal( 674 classstack[index][0]._addglobal(
646 Attribute(module, variable_name, file, lineno)) 675 Attribute(module, variable_name, file, lineno)
676 )
647 break 677 break
648 678
649 elif m.start("Publics") >= 0: 679 elif m.start("Publics") >= 0:
650 idents = m.group("Identifiers") 680 idents = m.group("Identifiers")
651 lineno += src.count('\n', last_lineno_pos, start) 681 lineno += src.count("\n", last_lineno_pos, start)
652 last_lineno_pos = start 682 last_lineno_pos = start
653 pubs = Publics(module, file, lineno, idents) 683 pubs = Publics(module, file, lineno, idents)
654 dictionary['__all__'] = pubs 684 dictionary["__all__"] = pubs
655 685
656 elif m.start("Import") >= 0: 686 elif m.start("Import") >= 0:
657 #- import module 687 # - import module
658 names = [n.strip() for n in 688 names = [
659 "".join(m.group("ImportList").splitlines()) 689 n.strip()
660 .replace("\\", "").split(',')] 690 for n in "".join(m.group("ImportList").splitlines())
661 lineno += src.count('\n', last_lineno_pos, start) 691 .replace("\\", "")
692 .split(",")
693 ]
694 lineno += src.count("\n", last_lineno_pos, start)
662 last_lineno_pos = start 695 last_lineno_pos = start
663 if "@@Import@@" not in dictionary: 696 if "@@Import@@" not in dictionary:
664 dictionary["@@Import@@"] = Imports(module, file) 697 dictionary["@@Import@@"] = Imports(module, file)
665 for name in names: 698 for name in names:
666 dictionary["@@Import@@"].addImport(name, [], lineno) 699 dictionary["@@Import@@"].addImport(name, [], lineno)
667 700
668 elif m.start("ImportFrom") >= 0: 701 elif m.start("ImportFrom") >= 0:
669 #- from module import stuff 702 # - from module import stuff
670 mod = m.group("ImportFromPath") 703 mod = m.group("ImportFromPath")
671 namesLines = (m.group("ImportFromList") 704 namesLines = (
672 .replace("(", "").replace(")", "") 705 m.group("ImportFromList")
673 .replace("\\", "") 706 .replace("(", "")
674 .strip().splitlines()) 707 .replace(")", "")
675 namesLines = [line.split("#")[0].strip() 708 .replace("\\", "")
676 for line in namesLines] 709 .strip()
677 names = [n.strip() for n in 710 .splitlines()
678 "".join(namesLines) 711 )
679 .split(',')] 712 namesLines = [line.split("#")[0].strip() for line in namesLines]
680 lineno += src.count('\n', last_lineno_pos, start) 713 names = [n.strip() for n in "".join(namesLines).split(",")]
714 lineno += src.count("\n", last_lineno_pos, start)
681 last_lineno_pos = start 715 last_lineno_pos = start
682 if "@@Import@@" not in dictionary: 716 if "@@Import@@" not in dictionary:
683 dictionary["@@Import@@"] = Imports(module, file) 717 dictionary["@@Import@@"] = Imports(module, file)
684 dictionary["@@Import@@"].addImport(mod, names, lineno) 718 dictionary["@@Import@@"].addImport(mod, names, lineno)
685 719
686 elif m.start("ConditionalDefine") >= 0: 720 elif m.start("ConditionalDefine") >= 0:
687 # a conditional function/method definition 721 # a conditional function/method definition
688 thisindent = _indent(m.group("ConditionalDefineIndent")) 722 thisindent = _indent(m.group("ConditionalDefineIndent"))
689 while conditionalsstack and conditionalsstack[-1] >= thisindent: 723 while conditionalsstack and conditionalsstack[-1] >= thisindent:
690 del conditionalsstack[-1] 724 del conditionalsstack[-1]
691 if deltastack: 725 if deltastack:
692 del deltastack[-1] 726 del deltastack[-1]
693 conditionalsstack.append(thisindent) 727 conditionalsstack.append(thisindent)
694 deltaindentcalculated = False 728 deltaindentcalculated = False
695 729
696 elif m.start("CodingLine") >= 0: 730 elif m.start("CodingLine") >= 0:
697 # a coding statement 731 # a coding statement
698 coding = m.group("Coding") 732 coding = m.group("Coding")
699 lineno += src.count('\n', last_lineno_pos, start) 733 lineno += src.count("\n", last_lineno_pos, start)
700 last_lineno_pos = start 734 last_lineno_pos = start
701 if "@@Coding@@" not in dictionary: 735 if "@@Coding@@" not in dictionary:
702 dictionary["@@Coding@@"] = ClbrBaseClasses.Coding( 736 dictionary["@@Coding@@"] = ClbrBaseClasses.Coding(
703 module, file, lineno, coding) 737 module, file, lineno, coding
704 738 )
705 if '__all__' in dictionary: 739
740 if "__all__" in dictionary:
706 # set visibility of all top level elements 741 # set visibility of all top level elements
707 pubs = dictionary['__all__'] 742 pubs = dictionary["__all__"]
708 for key in dictionary: 743 for key in dictionary:
709 if key == '__all__' or key.startswith("@@"): 744 if key == "__all__" or key.startswith("@@"):
710 continue 745 continue
711 if key in pubs.identifiers: 746 if key in pubs.identifiers:
712 dictionary[key].setPublic() 747 dictionary[key].setPublic()
713 else: 748 else:
714 dictionary[key].setPrivate() 749 dictionary[key].setPrivate()
715 del dictionary['__all__'] 750 del dictionary["__all__"]
716 751
717 return dictionary 752 return dictionary
718 753
719 754
720 def _indent(ws): 755 def _indent(ws):
721 """ 756 """
722 Module function to return the indentation depth. 757 Module function to return the indentation depth.
723 758
724 @param ws the whitespace to be checked (string) 759 @param ws the whitespace to be checked (string)
725 @return length of the whitespace string (integer) 760 @return length of the whitespace string (integer)
726 """ 761 """
727 return len(ws.expandtabs(TABWIDTH)) 762 return len(ws.expandtabs(TABWIDTH))

eric ide

mercurial