419 self.functions_counts = {} |
430 self.functions_counts = {} |
420 self.description = "" |
431 self.description = "" |
421 self.globals = {} |
432 self.globals = {} |
422 self.imports = [] |
433 self.imports = [] |
423 self.from_imports = {} |
434 self.from_imports = {} |
424 self.package = '.'.join(name.split('.')[:-1]) |
435 self.package = ".".join(name.split(".")[:-1]) |
425 self.type = moduleType |
436 self.type = moduleType |
426 if moduleType in [PY_SOURCE, PTL_SOURCE]: |
437 if moduleType in [PY_SOURCE, PTL_SOURCE]: |
427 self._getnext = _py_getnext |
438 self._getnext = _py_getnext |
428 elif moduleType == RB_SOURCE: |
439 elif moduleType == RB_SOURCE: |
429 self._getnext = _rb_getnext |
440 self._getnext = _rb_getnext |
430 else: |
441 else: |
431 self._getnext = None |
442 self._getnext = None |
432 |
443 |
433 def addClass(self, name, _class): |
444 def addClass(self, name, _class): |
434 """ |
445 """ |
435 Public method to add information about a class. |
446 Public method to add information about a class. |
436 |
447 |
437 @param name name of class to be added (string) |
448 @param name name of class to be added (string) |
438 @param _class Class object to be added |
449 @param _class Class object to be added |
439 """ |
450 """ |
440 if name in self.classes: |
451 if name in self.classes: |
441 self.classes_counts[name] += 1 |
452 self.classes_counts[name] += 1 |
442 name = "{0}_{1:d}".format(name, self.classes_counts[name]) |
453 name = "{0}_{1:d}".format(name, self.classes_counts[name]) |
443 else: |
454 else: |
444 self.classes_counts[name] = 0 |
455 self.classes_counts[name] = 0 |
445 self.classes[name] = _class |
456 self.classes[name] = _class |
446 |
457 |
447 def addModule(self, name, module): |
458 def addModule(self, name, module): |
448 """ |
459 """ |
449 Public method to add information about a Ruby module. |
460 Public method to add information about a Ruby module. |
450 |
461 |
451 @param name name of module to be added (string) |
462 @param name name of module to be added (string) |
452 @param module Module object to be added |
463 @param module Module object to be added |
453 """ |
464 """ |
454 if name in self.modules: |
465 if name in self.modules: |
455 self.modules_counts[name] += 1 |
466 self.modules_counts[name] += 1 |
456 name = "{0}_{1:d}".format(name, self.modules_counts[name]) |
467 name = "{0}_{1:d}".format(name, self.modules_counts[name]) |
457 else: |
468 else: |
458 self.modules_counts[name] = 0 |
469 self.modules_counts[name] = 0 |
459 self.modules[name] = module |
470 self.modules[name] = module |
460 |
471 |
461 def addFunction(self, name, function): |
472 def addFunction(self, name, function): |
462 """ |
473 """ |
463 Public method to add information about a function. |
474 Public method to add information about a function. |
464 |
475 |
465 @param name name of function to be added (string) |
476 @param name name of function to be added (string) |
466 @param function Function object to be added |
477 @param function Function object to be added |
467 """ |
478 """ |
468 if name in self.functions: |
479 if name in self.functions: |
469 self.functions_counts[name] += 1 |
480 self.functions_counts[name] += 1 |
470 name = "{0}_{1:d}".format(name, self.functions_counts[name]) |
481 name = "{0}_{1:d}".format(name, self.functions_counts[name]) |
471 else: |
482 else: |
472 self.functions_counts[name] = 0 |
483 self.functions_counts[name] = 0 |
473 self.functions[name] = function |
484 self.functions[name] = function |
474 |
485 |
475 def addGlobal(self, name, attr): |
486 def addGlobal(self, name, attr): |
476 """ |
487 """ |
477 Public method to add information about global variables. |
488 Public method to add information about global variables. |
478 |
489 |
479 @param name name of the global to add (string) |
490 @param name name of the global to add (string) |
480 @param attr Attribute object to be added |
491 @param attr Attribute object to be added |
481 """ |
492 """ |
482 if name not in self.globals: |
493 if name not in self.globals: |
483 self.globals[name] = attr |
494 self.globals[name] = attr |
484 else: |
495 else: |
485 self.globals[name].addAssignment(attr.lineno) |
496 self.globals[name].addAssignment(attr.lineno) |
486 |
497 |
487 def addDescription(self, description): |
498 def addDescription(self, description): |
488 """ |
499 """ |
489 Public method to store the modules docstring. |
500 Public method to store the modules docstring. |
490 |
501 |
491 @param description the docstring to be stored (string) |
502 @param description the docstring to be stored (string) |
492 """ |
503 """ |
493 self.description = description |
504 self.description = description |
494 |
505 |
495 def scan(self, src): |
506 def scan(self, src): |
496 """ |
507 """ |
497 Public method to scan the source text and retrieve the relevant |
508 Public method to scan the source text and retrieve the relevant |
498 information. |
509 information. |
499 |
510 |
500 @param src the source text to be scanned (string) |
511 @param src the source text to be scanned (string) |
501 """ |
512 """ |
502 # convert eol markers the Python style |
513 # convert eol markers the Python style |
503 src = src.replace("\r\n", "\n").replace("\r", "\n") |
514 src = src.replace("\r\n", "\n").replace("\r", "\n") |
504 if self.type in [PY_SOURCE, PTL_SOURCE]: |
515 if self.type in [PY_SOURCE, PTL_SOURCE]: |
505 self.__py_scan(src) |
516 self.__py_scan(src) |
506 elif self.type == RB_SOURCE: |
517 elif self.type == RB_SOURCE: |
507 self.__rb_scan(src) |
518 self.__rb_scan(src) |
508 |
519 |
509 def __py_setVisibility(self, objectRef): |
520 def __py_setVisibility(self, objectRef): |
510 """ |
521 """ |
511 Private method to set the visibility of an object. |
522 Private method to set the visibility of an object. |
512 |
523 |
513 @param objectRef reference to the object (Attribute, Class or Function) |
524 @param objectRef reference to the object (Attribute, Class or Function) |
514 """ |
525 """ |
515 if objectRef.name.startswith('__'): |
526 if objectRef.name.startswith("__"): |
516 objectRef.setPrivate() |
527 objectRef.setPrivate() |
517 elif objectRef.name.startswith('_'): |
528 elif objectRef.name.startswith("_"): |
518 objectRef.setProtected() |
529 objectRef.setProtected() |
519 else: |
530 else: |
520 objectRef.setPublic() |
531 objectRef.setPublic() |
521 |
532 |
522 def __py_scan(self, src): |
533 def __py_scan(self, src): |
523 """ |
534 """ |
524 Private method to scan the source text of a Python module and retrieve |
535 Private method to scan the source text of a Python module and retrieve |
525 the relevant information. |
536 the relevant information. |
526 |
537 |
527 @param src the source text to be scanned (string) |
538 @param src the source text to be scanned (string) |
528 """ |
539 """ |
529 # __IGNORE_WARNING_D234__ |
540 # __IGNORE_WARNING_D234__ |
530 def calculateEndline(lineno, lines, indent): |
541 def calculateEndline(lineno, lines, indent): |
531 """ |
542 """ |
532 Function to calculate the end line of a class or method/function. |
543 Function to calculate the end line of a class or method/function. |
533 |
544 |
534 @param lineno line number to start at (one based) |
545 @param lineno line number to start at (one based) |
535 @type int |
546 @type int |
536 @param lines list of source lines |
547 @param lines list of source lines |
537 @type list of str |
548 @type list of str |
538 @param indent indent length the class/method/function definition |
549 @param indent indent length the class/method/function definition |
634 # nested defs are added to the class |
640 # nested defs are added to the class |
635 cur_class = classstack[csi][0] |
641 cur_class = classstack[csi][0] |
636 csi -= 1 |
642 csi -= 1 |
637 if cur_class is None: |
643 if cur_class is None: |
638 continue |
644 continue |
639 |
645 |
640 if isinstance(cur_class, Class): |
646 if isinstance(cur_class, Class): |
641 # it's a class method |
647 # it's a class method |
642 f = Function( |
648 f = Function( |
643 None, meth_name, None, lineno, |
649 None, |
644 meth_sig, meth_pyqtSig, modifierType=modifier, |
650 meth_name, |
645 annotation=meth_ret) |
651 None, |
|
652 lineno, |
|
653 meth_sig, |
|
654 meth_pyqtSig, |
|
655 modifierType=modifier, |
|
656 annotation=meth_ret, |
|
657 ) |
646 self.__py_setVisibility(f) |
658 self.__py_setVisibility(f) |
647 cur_class.addMethod(meth_name, f) |
659 cur_class.addMethod(meth_name, f) |
648 break |
660 break |
649 else: |
661 else: |
650 # it's a nested function of a module function |
662 # it's a nested function of a module function |
651 f = Function( |
663 f = Function( |
652 self.name, meth_name, self.file, lineno, |
664 self.name, |
653 meth_sig, meth_pyqtSig, modifierType=modifier, |
665 meth_name, |
654 annotation=meth_ret) |
666 self.file, |
|
667 lineno, |
|
668 meth_sig, |
|
669 meth_pyqtSig, |
|
670 modifierType=modifier, |
|
671 annotation=meth_ret, |
|
672 ) |
655 self.__py_setVisibility(f) |
673 self.__py_setVisibility(f) |
656 self.addFunction(meth_name, f) |
674 self.addFunction(meth_name, f) |
657 else: |
675 else: |
658 # it's a module function |
676 # it's a module function |
659 f = Function(self.name, meth_name, self.file, lineno, |
677 f = Function( |
660 meth_sig, meth_pyqtSig, modifierType=modifier, |
678 self.name, |
661 annotation=meth_ret) |
679 meth_name, |
|
680 self.file, |
|
681 lineno, |
|
682 meth_sig, |
|
683 meth_pyqtSig, |
|
684 modifierType=modifier, |
|
685 annotation=meth_ret, |
|
686 ) |
662 self.__py_setVisibility(f) |
687 self.__py_setVisibility(f) |
663 self.addFunction(meth_name, f) |
688 self.addFunction(meth_name, f) |
664 endlineno = calculateEndline(lineno, srcLines, thisindent) |
689 endlineno = calculateEndline(lineno, srcLines, thisindent) |
665 f.setEndLine(endlineno) |
690 f.setEndLine(endlineno) |
666 cur_obj = f |
691 cur_obj = f |
667 classstack.append((None, thisindent)) # Marker for nested fns |
692 classstack.append((None, thisindent)) # Marker for nested fns |
668 |
693 |
669 # reset the modifier settings |
694 # reset the modifier settings |
670 modifierType = Function.General |
695 modifierType = Function.General |
671 modifierIndent = -1 |
696 modifierIndent = -1 |
672 |
697 |
673 elif m.start("Docstring") >= 0: |
698 elif m.start("Docstring") >= 0: |
674 contents = m.group("DocstringContents3") |
699 contents = m.group("DocstringContents3") |
675 if contents is not None: |
700 if contents is not None: |
676 contents = _hashsub(r"\1", contents) |
701 contents = _hashsub(r"\1", contents) |
677 else: |
702 else: |
678 if self.file.lower().endswith('.ptl'): |
703 if self.file.lower().endswith(".ptl"): |
679 contents = "" |
704 contents = "" |
680 else: |
705 else: |
681 contents = ( |
706 contents = m.group("DocstringContents1") or m.group( |
682 m.group("DocstringContents1") or |
707 "DocstringContents2" |
683 m.group("DocstringContents2") |
|
684 ) |
708 ) |
685 if cur_obj: |
709 if cur_obj: |
686 cur_obj.addDescription(contents) |
710 cur_obj.addDescription(contents) |
687 |
711 |
688 elif m.start("String") >= 0: |
712 elif m.start("String") >= 0: |
689 if ( |
713 if modulelevel and ( |
690 modulelevel and ( |
714 src[start - len("\r\n") : start] == "\r\n" |
691 src[start - len('\r\n'):start] == '\r\n' or |
715 or src[start - len("\n") : start] == "\n" |
692 src[start - len('\n'):start] == '\n' or |
716 or src[start - len("\r") : start] == "\r" |
693 src[start - len('\r'):start] == '\r' |
|
694 ) |
|
695 ): |
717 ): |
696 contents = m.group("StringContents3") |
718 contents = m.group("StringContents3") |
697 if contents is not None: |
719 if contents is not None: |
698 contents = _hashsub(r"\1", contents) |
720 contents = _hashsub(r"\1", contents) |
699 else: |
721 else: |
700 if self.file.lower().endswith('.ptl'): |
722 if self.file.lower().endswith(".ptl"): |
701 contents = "" |
723 contents = "" |
702 else: |
724 else: |
703 contents = ( |
725 contents = m.group("StringContents1") or m.group( |
704 m.group("StringContents1") or |
726 "StringContents2" |
705 m.group("StringContents2") |
|
706 ) |
727 ) |
707 if cur_obj: |
728 if cur_obj: |
708 cur_obj.addDescription(contents) |
729 cur_obj.addDescription(contents) |
709 |
730 |
710 elif m.start("Class") >= 0: |
731 elif m.start("Class") >= 0: |
711 # we found a class definition |
732 # we found a class definition |
712 thisindent = _indent(m.group("ClassIndent")) |
733 thisindent = _indent(m.group("ClassIndent")) |
713 lineno += src.count('\n', last_lineno_pos, start) |
734 lineno += src.count("\n", last_lineno_pos, start) |
714 last_lineno_pos = start |
735 last_lineno_pos = start |
715 # close all classes indented at least as much |
736 # close all classes indented at least as much |
716 while classstack and classstack[-1][1] >= thisindent: |
737 while classstack and classstack[-1][1] >= thisindent: |
717 del classstack[-1] |
738 del classstack[-1] |
718 class_name = m.group("ClassName") |
739 class_name = m.group("ClassName") |
719 inherit = m.group("ClassSupers") |
740 inherit = m.group("ClassSupers") |
720 if inherit: |
741 if inherit: |
721 # the class inherits from other classes |
742 # the class inherits from other classes |
722 inherit = inherit[1:-1].strip() |
743 inherit = inherit[1:-1].strip() |
723 inherit = _commentsub('', inherit) |
744 inherit = _commentsub("", inherit) |
724 names = [] |
745 names = [] |
725 for n in inherit.split(','): |
746 for n in inherit.split(","): |
726 n = n.strip() |
747 n = n.strip() |
727 if n: |
748 if n: |
728 if n in self.classes: |
749 if n in self.classes: |
729 # we know this super class |
750 # we know this super class |
730 n = self.classes[n].name |
751 n = self.classes[n].name |
731 else: |
752 else: |
732 c = n.split('.') |
753 c = n.split(".") |
733 if len(c) > 1: |
754 if len(c) > 1: |
734 # super class is of the |
755 # super class is of the |
735 # form module.class: |
756 # form module.class: |
736 # look in module for class |
757 # look in module for class |
737 m = c[-2] |
758 m = c[-2] |
743 inherit = names |
764 inherit = names |
744 # modify indentation level for conditional defines |
765 # modify indentation level for conditional defines |
745 if conditionalsstack: |
766 if conditionalsstack: |
746 if thisindent > conditionalsstack[-1]: |
767 if thisindent > conditionalsstack[-1]: |
747 if not deltaindentcalculated: |
768 if not deltaindentcalculated: |
748 deltastack.append( |
769 deltastack.append(thisindent - conditionalsstack[-1]) |
749 thisindent - conditionalsstack[-1] |
770 deltaindent = reduce(lambda x, y: x + y, deltastack) |
750 ) |
|
751 deltaindent = reduce( |
|
752 lambda x, y: x + y, deltastack |
|
753 ) |
|
754 deltaindentcalculated = True |
771 deltaindentcalculated = True |
755 thisindent -= deltaindent |
772 thisindent -= deltaindent |
756 else: |
773 else: |
757 while ( |
774 while conditionalsstack and conditionalsstack[-1] >= thisindent: |
758 conditionalsstack and |
|
759 conditionalsstack[-1] >= thisindent |
|
760 ): |
|
761 del conditionalsstack[-1] |
775 del conditionalsstack[-1] |
762 if deltastack: |
776 if deltastack: |
763 del deltastack[-1] |
777 del deltastack[-1] |
764 deltaindentcalculated = False |
778 deltaindentcalculated = False |
765 # remember this class |
779 # remember this class |
766 cur_class = Class(self.name, class_name, inherit, |
780 cur_class = Class(self.name, class_name, inherit, self.file, lineno) |
767 self.file, lineno) |
|
768 self.__py_setVisibility(cur_class) |
781 self.__py_setVisibility(cur_class) |
769 endlineno = calculateEndline(lineno, srcLines, thisindent) |
782 endlineno = calculateEndline(lineno, srcLines, thisindent) |
770 cur_class.setEndLine(endlineno) |
783 cur_class.setEndLine(endlineno) |
771 cur_obj = cur_class |
784 cur_obj = cur_class |
772 self.addClass(class_name, cur_class) |
785 self.addClass(class_name, cur_class) |
773 # add nested classes to the module |
786 # add nested classes to the module |
774 classstack.append((cur_class, thisindent)) |
787 classstack.append((cur_class, thisindent)) |
775 |
788 |
776 elif m.start("Attribute") >= 0: |
789 elif m.start("Attribute") >= 0: |
777 lineno += src.count('\n', last_lineno_pos, start) |
790 lineno += src.count("\n", last_lineno_pos, start) |
778 last_lineno_pos = start |
791 last_lineno_pos = start |
779 index = -1 |
792 index = -1 |
780 while index >= -len(classstack): |
793 while index >= -len(classstack): |
781 if classstack[index][0] is not None: |
794 if classstack[index][0] is not None: |
782 attrName = m.group("AttributeName") |
795 attrName = m.group("AttributeName") |
783 attr = Attribute( |
796 attr = Attribute(self.name, attrName, self.file, lineno) |
784 self.name, attrName, self.file, lineno) |
|
785 self.__py_setVisibility(attr) |
797 self.__py_setVisibility(attr) |
786 classstack[index][0].addAttribute(attrName, attr) |
798 classstack[index][0].addAttribute(attrName, attr) |
787 break |
799 break |
788 else: |
800 else: |
789 index -= 1 |
801 index -= 1 |
790 |
802 |
791 elif m.start("Main") >= 0: |
803 elif m.start("Main") >= 0: |
792 # 'main' part of the script, reset class stack |
804 # 'main' part of the script, reset class stack |
793 lineno += src.count('\n', last_lineno_pos, start) |
805 lineno += src.count("\n", last_lineno_pos, start) |
794 last_lineno_pos = start |
806 last_lineno_pos = start |
795 classstack = [] |
807 classstack = [] |
796 |
808 |
797 elif m.start("Variable") >= 0: |
809 elif m.start("Variable") >= 0: |
798 thisindent = _indent(m.group("VariableIndent")) |
810 thisindent = _indent(m.group("VariableIndent")) |
799 variable_name = m.group("VariableName") |
811 variable_name = m.group("VariableName") |
800 isSignal = m.group("VariableSignal") != "" |
812 isSignal = m.group("VariableSignal") != "" |
801 lineno += src.count('\n', last_lineno_pos, start) |
813 lineno += src.count("\n", last_lineno_pos, start) |
802 last_lineno_pos = start |
814 last_lineno_pos = start |
803 if thisindent == 0: |
815 if thisindent == 0: |
804 # global variable |
816 # global variable |
805 attr = Attribute( |
817 attr = Attribute( |
806 self.name, variable_name, self.file, lineno, |
818 self.name, variable_name, self.file, lineno, isSignal=isSignal |
807 isSignal=isSignal) |
819 ) |
808 self.__py_setVisibility(attr) |
820 self.__py_setVisibility(attr) |
809 self.addGlobal(variable_name, attr) |
821 self.addGlobal(variable_name, attr) |
810 else: |
822 else: |
811 index = -1 |
823 index = -1 |
812 while index >= -len(classstack): |
824 while index >= -len(classstack): |
813 if classstack[index][1] >= thisindent: |
825 if classstack[index][1] >= thisindent: |
814 index -= 1 |
826 index -= 1 |
815 else: |
827 else: |
816 if ( |
828 if classstack[index][0] is not None and isinstance( |
817 classstack[index][0] is not None and |
829 classstack[index][0], Class |
818 isinstance(classstack[index][0], Class) |
|
819 ): |
830 ): |
820 attr = Attribute( |
831 attr = Attribute( |
821 self.name, variable_name, self.file, |
832 self.name, |
822 lineno, isSignal=isSignal) |
833 variable_name, |
|
834 self.file, |
|
835 lineno, |
|
836 isSignal=isSignal, |
|
837 ) |
823 self.__py_setVisibility(attr) |
838 self.__py_setVisibility(attr) |
824 classstack[index][0].addGlobal( |
839 classstack[index][0].addGlobal(variable_name, attr) |
825 variable_name, attr) |
|
826 break |
840 break |
827 |
841 |
828 elif m.start("Import") >= 0: |
842 elif m.start("Import") >= 0: |
829 #- import module |
843 # - import module |
830 names = [n.strip() for n in |
844 names = [ |
831 "".join(m.group("ImportList").splitlines()) |
845 n.strip() |
832 .replace("\\", "").split(',')] |
846 for n in "".join(m.group("ImportList").splitlines()) |
|
847 .replace("\\", "") |
|
848 .split(",") |
|
849 ] |
833 self.imports.extend( |
850 self.imports.extend( |
834 [name for name in names |
851 [name for name in names if name not in self.imports] |
835 if name not in self.imports]) |
852 ) |
836 |
853 |
837 elif m.start("ImportFrom") >= 0: |
854 elif m.start("ImportFrom") >= 0: |
838 #- from module import stuff |
855 # - from module import stuff |
839 mod = m.group("ImportFromPath") |
856 mod = m.group("ImportFromPath") |
840 namesLines = (m.group("ImportFromList") |
857 namesLines = ( |
841 .replace("(", "").replace(")", "") |
858 m.group("ImportFromList") |
842 .replace("\\", "") |
859 .replace("(", "") |
843 .strip().splitlines()) |
860 .replace(")", "") |
844 namesLines = [line.split("#")[0].strip() |
861 .replace("\\", "") |
845 for line in namesLines] |
862 .strip() |
846 names = [n.strip() for n in |
863 .splitlines() |
847 "".join(namesLines) |
864 ) |
848 .split(',')] |
865 namesLines = [line.split("#")[0].strip() for line in namesLines] |
|
866 names = [n.strip() for n in "".join(namesLines).split(",")] |
849 if mod not in self.from_imports: |
867 if mod not in self.from_imports: |
850 self.from_imports[mod] = [] |
868 self.from_imports[mod] = [] |
851 self.from_imports[mod].extend( |
869 self.from_imports[mod].extend( |
852 [name for name in names |
870 [name for name in names if name not in self.from_imports[mod]] |
853 if name not in self.from_imports[mod]]) |
871 ) |
854 |
872 |
855 elif m.start("ConditionalDefine") >= 0: |
873 elif m.start("ConditionalDefine") >= 0: |
856 # a conditional function/method definition |
874 # a conditional function/method definition |
857 thisindent = _indent(m.group("ConditionalDefineIndent")) |
875 thisindent = _indent(m.group("ConditionalDefineIndent")) |
858 while ( |
876 while conditionalsstack and conditionalsstack[-1] >= thisindent: |
859 conditionalsstack and |
|
860 conditionalsstack[-1] >= thisindent |
|
861 ): |
|
862 del conditionalsstack[-1] |
877 del conditionalsstack[-1] |
863 if deltastack: |
878 if deltastack: |
864 del deltastack[-1] |
879 del deltastack[-1] |
865 conditionalsstack.append(thisindent) |
880 conditionalsstack.append(thisindent) |
866 deltaindentcalculated = 0 |
881 deltaindentcalculated = 0 |
867 |
882 |
868 elif m.start("Comment") >= 0 and modulelevel: |
883 elif m.start("Comment") >= 0 and modulelevel: |
869 continue |
884 continue |
870 |
885 |
871 modulelevel = False |
886 modulelevel = False |
872 |
887 |
873 def __rb_scan(self, src): |
888 def __rb_scan(self, src): |
874 """ |
889 """ |
875 Private method to scan the source text of a Python module and retrieve |
890 Private method to scan the source text of a Python module and retrieve |
876 the relevant information. |
891 the relevant information. |
877 |
892 |
878 @param src the source text to be scanned |
893 @param src the source text to be scanned |
879 @type str |
894 @type str |
880 """ |
895 """ |
881 lineno, last_lineno_pos = 1, 0 |
896 lineno, last_lineno_pos = 1, 0 |
882 classstack = [] # stack of (class, indent) pairs |
897 classstack = [] # stack of (class, indent) pairs |
883 acstack = [] # stack of (access control, indent) pairs |
898 acstack = [] # stack of (access control, indent) pairs |
884 indent = 0 |
899 indent = 0 |
885 i = 0 |
900 i = 0 |
886 cur_obj = self |
901 cur_obj = self |
887 lastGlobalEntry = None |
902 lastGlobalEntry = None |
888 while True: |
903 while True: |
889 m = self._getnext(src, i) |
904 m = self._getnext(src, i) |
890 if not m: |
905 if not m: |
891 break |
906 break |
892 start, i = m.span() |
907 start, i = m.span() |
893 |
908 |
894 if m.start("Method") >= 0: |
909 if m.start("Method") >= 0: |
895 # found a method definition or function |
910 # found a method definition or function |
896 thisindent = indent |
911 thisindent = indent |
897 indent += 1 |
912 indent += 1 |
898 meth_name = ( |
913 meth_name = ( |
899 m.group("MethodName") or |
914 m.group("MethodName") |
900 m.group("MethodName2") or |
915 or m.group("MethodName2") |
901 m.group("MethodName3") |
916 or m.group("MethodName3") |
902 ) |
917 ) |
903 meth_sig = m.group("MethodSignature") |
918 meth_sig = m.group("MethodSignature") |
904 meth_sig = meth_sig and meth_sig.replace('\\\n', '') or '' |
919 meth_sig = meth_sig and meth_sig.replace("\\\n", "") or "" |
905 lineno += src.count('\n', last_lineno_pos, start) |
920 lineno += src.count("\n", last_lineno_pos, start) |
906 last_lineno_pos = start |
921 last_lineno_pos = start |
907 if meth_name.startswith('self.'): |
922 if meth_name.startswith("self."): |
908 meth_name = meth_name[5:] |
923 meth_name = meth_name[5:] |
909 elif meth_name.startswith('self::'): |
924 elif meth_name.startswith("self::"): |
910 meth_name = meth_name[6:] |
925 meth_name = meth_name[6:] |
911 # close all classes/modules indented at least as much |
926 # close all classes/modules indented at least as much |
912 while classstack and classstack[-1][1] >= thisindent: |
927 while classstack and classstack[-1][1] >= thisindent: |
913 if ( |
928 if classstack[-1][0] is not None and isinstance( |
914 classstack[-1][0] is not None and |
929 classstack[-1][0], (Class, Function, RbModule) |
915 isinstance(classstack[-1][0], |
|
916 (Class, Function, RbModule)) |
|
917 ): |
930 ): |
918 # record the end line of this class, function or module |
931 # record the end line of this class, function or module |
919 classstack[-1][0].setEndLine(lineno - 1) |
932 classstack[-1][0].setEndLine(lineno - 1) |
920 del classstack[-1] |
933 del classstack[-1] |
921 while acstack and acstack[-1][1] >= thisindent: |
934 while acstack and acstack[-1][1] >= thisindent: |
949 f.setProtected() |
960 f.setProtected() |
950 elif accesscontrol == "public": |
961 elif accesscontrol == "public": |
951 f.setPublic() |
962 f.setPublic() |
952 else: |
963 else: |
953 # it's a function |
964 # it's a function |
954 f = Function( |
965 f = Function(self.name, meth_name, self.file, lineno, meth_sig) |
955 self.name, meth_name, self.file, lineno, meth_sig) |
|
956 self.addFunction(meth_name, f) |
966 self.addFunction(meth_name, f) |
957 if not classstack: |
967 if not classstack: |
958 if lastGlobalEntry: |
968 if lastGlobalEntry: |
959 lastGlobalEntry.setEndLine(lineno - 1) |
969 lastGlobalEntry.setEndLine(lineno - 1) |
960 lastGlobalEntry = f |
970 lastGlobalEntry = f |
961 if cur_obj and isinstance(cur_obj, Function): |
971 if cur_obj and isinstance(cur_obj, Function): |
962 cur_obj.setEndLine(lineno - 1) |
972 cur_obj.setEndLine(lineno - 1) |
963 cur_obj = f |
973 cur_obj = f |
964 classstack.append((None, thisindent)) # Marker for nested fns |
974 classstack.append((None, thisindent)) # Marker for nested fns |
965 |
975 |
966 elif m.start("Docstring") >= 0: |
976 elif m.start("Docstring") >= 0: |
967 contents = m.group("DocstringContents") |
977 contents = m.group("DocstringContents") |
968 if contents is not None: |
978 if contents is not None: |
969 contents = _hashsub(r"\1", contents) |
979 contents = _hashsub(r"\1", contents) |
970 if cur_obj: |
980 if cur_obj: |
971 cur_obj.addDescription(contents) |
981 cur_obj.addDescription(contents) |
972 |
982 |
973 elif m.start("Class") >= 0: |
983 elif m.start("Class") >= 0: |
974 # we found a class definition |
984 # we found a class definition |
975 thisindent = indent |
985 thisindent = indent |
976 indent += 1 |
986 indent += 1 |
977 lineno += src.count('\n', last_lineno_pos, start) |
987 lineno += src.count("\n", last_lineno_pos, start) |
978 last_lineno_pos = start |
988 last_lineno_pos = start |
979 # close all classes/modules indented at least as much |
989 # close all classes/modules indented at least as much |
980 while classstack and classstack[-1][1] >= thisindent: |
990 while classstack and classstack[-1][1] >= thisindent: |
981 if ( |
991 if classstack[-1][0] is not None and isinstance( |
982 classstack[-1][0] is not None and |
992 classstack[-1][0], (Class, Function, RbModule) |
983 isinstance(classstack[-1][0], |
|
984 (Class, Function, RbModule)) |
|
985 ): |
993 ): |
986 # record the end line of this class, function or module |
994 # record the end line of this class, function or module |
987 classstack[-1][0].setEndLine(lineno - 1) |
995 classstack[-1][0].setEndLine(lineno - 1) |
988 del classstack[-1] |
996 del classstack[-1] |
989 class_name = m.group("ClassName") or m.group("ClassName2") |
997 class_name = m.group("ClassName") or m.group("ClassName2") |
990 inherit = m.group("ClassSupers") |
998 inherit = m.group("ClassSupers") |
991 if inherit: |
999 if inherit: |
992 # the class inherits from other classes |
1000 # the class inherits from other classes |
993 inherit = inherit[1:].strip() |
1001 inherit = inherit[1:].strip() |
994 inherit = [_commentsub('', inherit)] |
1002 inherit = [_commentsub("", inherit)] |
995 # remember this class |
1003 # remember this class |
996 cur_class = Class(self.name, class_name, inherit, |
1004 cur_class = Class(self.name, class_name, inherit, self.file, lineno) |
997 self.file, lineno) |
|
998 # add nested classes to the file |
1005 # add nested classes to the file |
999 if classstack and isinstance(classstack[-1][0], RbModule): |
1006 if classstack and isinstance(classstack[-1][0], RbModule): |
1000 parent_obj = classstack[-1][0] |
1007 parent_obj = classstack[-1][0] |
1001 else: |
1008 else: |
1002 parent_obj = self |
1009 parent_obj = self |
1003 if class_name in parent_obj.classes: |
1010 if class_name in parent_obj.classes: |
1004 cur_class = parent_obj.classes[class_name] |
1011 cur_class = parent_obj.classes[class_name] |
1005 elif ( |
1012 elif ( |
1006 classstack and |
1013 classstack |
1007 isinstance(classstack[-1][0], Class) and |
1014 and isinstance(classstack[-1][0], Class) |
1008 class_name == "self" |
1015 and class_name == "self" |
1009 ): |
1016 ): |
1010 cur_class = classstack[-1][0] |
1017 cur_class = classstack[-1][0] |
1011 else: |
1018 else: |
1012 parent_obj.addClass(class_name, cur_class) |
1019 parent_obj.addClass(class_name, cur_class) |
1013 if not classstack: |
1020 if not classstack: |
1018 classstack.append((cur_class, thisindent)) |
1025 classstack.append((cur_class, thisindent)) |
1019 while acstack and acstack[-1][1] >= thisindent: |
1026 while acstack and acstack[-1][1] >= thisindent: |
1020 del acstack[-1] |
1027 del acstack[-1] |
1021 acstack.append(["public", thisindent]) |
1028 acstack.append(["public", thisindent]) |
1022 # default access control is 'public' |
1029 # default access control is 'public' |
1023 |
1030 |
1024 elif m.start("Module") >= 0: |
1031 elif m.start("Module") >= 0: |
1025 # we found a module definition |
1032 # we found a module definition |
1026 thisindent = indent |
1033 thisindent = indent |
1027 indent += 1 |
1034 indent += 1 |
1028 lineno += src.count('\n', last_lineno_pos, start) |
1035 lineno += src.count("\n", last_lineno_pos, start) |
1029 last_lineno_pos = start |
1036 last_lineno_pos = start |
1030 # close all classes/modules indented at least as much |
1037 # close all classes/modules indented at least as much |
1031 while classstack and classstack[-1][1] >= thisindent: |
1038 while classstack and classstack[-1][1] >= thisindent: |
1032 if ( |
1039 if classstack[-1][0] is not None and isinstance( |
1033 classstack[-1][0] is not None and |
1040 classstack[-1][0], (Class, Function, RbModule) |
1034 isinstance(classstack[-1][0], |
|
1035 (Class, Function, RbModule)) |
|
1036 ): |
1041 ): |
1037 # record the end line of this class, function or module |
1042 # record the end line of this class, function or module |
1038 classstack[-1][0].setEndLine(lineno - 1) |
1043 classstack[-1][0].setEndLine(lineno - 1) |
1039 del classstack[-1] |
1044 del classstack[-1] |
1040 module_name = m.group("ModuleName") |
1045 module_name = m.group("ModuleName") |
1041 # remember this class |
1046 # remember this class |
1042 cur_class = RbModule(self.name, module_name, |
1047 cur_class = RbModule(self.name, module_name, self.file, lineno) |
1043 self.file, lineno) |
|
1044 # add nested Ruby modules to the file |
1048 # add nested Ruby modules to the file |
1045 if module_name in self.modules: |
1049 if module_name in self.modules: |
1046 cur_class = self.modules[module_name] |
1050 cur_class = self.modules[module_name] |
1047 else: |
1051 else: |
1048 self.addModule(module_name, cur_class) |
1052 self.addModule(module_name, cur_class) |
1100 break |
1104 break |
1101 else: |
1105 else: |
1102 index -= 1 |
1106 index -= 1 |
1103 |
1107 |
1104 elif m.start("Attribute") >= 0: |
1108 elif m.start("Attribute") >= 0: |
1105 lineno += src.count('\n', last_lineno_pos, start) |
1109 lineno += src.count("\n", last_lineno_pos, start) |
1106 last_lineno_pos = start |
1110 last_lineno_pos = start |
1107 index = -1 |
1111 index = -1 |
1108 while index >= -len(classstack): |
1112 while index >= -len(classstack): |
1109 if ( |
1113 if ( |
1110 classstack[index][0] is not None and |
1114 classstack[index][0] is not None |
1111 not isinstance(classstack[index][0], Function) and |
1115 and not isinstance(classstack[index][0], Function) |
1112 classstack[index][1] < indent |
1116 and classstack[index][1] < indent |
1113 ): |
1117 ): |
1114 attrName = m.group("AttributeName") |
1118 attrName = m.group("AttributeName") |
1115 attr = Attribute( |
1119 attr = Attribute(self.name, attrName, self.file, lineno) |
1116 self.name, attrName, self.file, lineno) |
|
1117 if attrName.startswith("@@") or attrName[0].isupper(): |
1120 if attrName.startswith("@@") or attrName[0].isupper(): |
1118 classstack[index][0].addGlobal(attrName, attr) |
1121 classstack[index][0].addGlobal(attrName, attr) |
1119 else: |
1122 else: |
1120 classstack[index][0].addAttribute(attrName, attr) |
1123 classstack[index][0].addAttribute(attrName, attr) |
1121 break |
1124 break |
1122 else: |
1125 else: |
1123 index -= 1 |
1126 index -= 1 |
1124 else: |
1127 else: |
1125 attrName = m.group("AttributeName") |
1128 attrName = m.group("AttributeName") |
1126 if attrName[0] != "@": |
1129 if attrName[0] != "@": |
1127 attr = Attribute( |
1130 attr = Attribute(self.name, attrName, self.file, lineno) |
1128 self.name, attrName, self.file, lineno) |
|
1129 self.addGlobal(attrName, attr) |
1131 self.addGlobal(attrName, attr) |
1130 if lastGlobalEntry: |
1132 if lastGlobalEntry: |
1131 lastGlobalEntry.setEndLine(lineno - 1) |
1133 lastGlobalEntry.setEndLine(lineno - 1) |
1132 lastGlobalEntry = None |
1134 lastGlobalEntry = None |
1133 |
1135 |
1134 elif m.start("Attr") >= 0: |
1136 elif m.start("Attr") >= 0: |
1135 lineno += src.count('\n', last_lineno_pos, start) |
1137 lineno += src.count("\n", last_lineno_pos, start) |
1136 last_lineno_pos = start |
1138 last_lineno_pos = start |
1137 index = -1 |
1139 index = -1 |
1138 while index >= -len(classstack): |
1140 while index >= -len(classstack): |
1139 if ( |
1141 if ( |
1140 classstack[index][0] is not None and |
1142 classstack[index][0] is not None |
1141 not isinstance(classstack[index][0], Function) and |
1143 and not isinstance(classstack[index][0], Function) |
1142 classstack[index][1] < indent |
1144 and classstack[index][1] < indent |
1143 ): |
1145 ): |
1144 parent = classstack[index][0] |
1146 parent = classstack[index][0] |
1145 if m.group("AttrType") is None: |
1147 if m.group("AttrType") is None: |
1146 nv = m.group("AttrList").split(",") |
1148 nv = m.group("AttrList").split(",") |
1147 if not nv: |
1149 if not nv: |
1148 break |
1150 break |
1149 # get rid of leading ':' |
1151 # get rid of leading ':' |
1150 name = nv[0].strip()[1:] |
1152 name = nv[0].strip()[1:] |
1151 attr = ( |
1153 attr = ( |
1152 parent.getAttribute("@" + name) or |
1154 parent.getAttribute("@" + name) |
1153 parent.getAttribute("@@" + name) or |
1155 or parent.getAttribute("@@" + name) |
1154 Attribute( |
1156 or Attribute(self.name, "@" + name, self.file, lineno) |
1155 self.name, "@" + name, self.file, lineno) |
|
1156 ) |
1157 ) |
1157 if len(nv) == 1 or nv[1].strip() == "false": |
1158 if len(nv) == 1 or nv[1].strip() == "false": |
1158 attr.setProtected() |
1159 attr.setProtected() |
1159 elif nv[1].strip() == "true": |
1160 elif nv[1].strip() == "true": |
1160 attr.setPublic() |
1161 attr.setPublic() |
1184 index -= 1 |
1185 index -= 1 |
1185 |
1186 |
1186 elif m.start("Begin") >= 0: |
1187 elif m.start("Begin") >= 0: |
1187 # a begin of a block we are not interested in |
1188 # a begin of a block we are not interested in |
1188 indent += 1 |
1189 indent += 1 |
1189 |
1190 |
1190 elif m.start("End") >= 0: |
1191 elif m.start("End") >= 0: |
1191 # an end of a block |
1192 # an end of a block |
1192 indent -= 1 |
1193 indent -= 1 |
1193 if indent < 0: |
1194 if indent < 0: |
1194 # no negative indent allowed |
1195 # no negative indent allowed |
1195 if classstack: |
1196 if classstack: |
1196 # it's a class/module method |
1197 # it's a class/module method |
1197 indent = classstack[-1][1] |
1198 indent = classstack[-1][1] |
1198 else: |
1199 else: |
1199 indent = 0 |
1200 indent = 0 |
1200 |
1201 |
1201 elif ( |
1202 elif ( |
1202 m.start("String") >= 0 or |
1203 m.start("String") >= 0 |
1203 m.start("Comment") >= 0 or |
1204 or m.start("Comment") >= 0 |
1204 m.start("ClassIgnored") >= 0 or |
1205 or m.start("ClassIgnored") >= 0 |
1205 m.start("BeginEnd") >= 0 |
1206 or m.start("BeginEnd") >= 0 |
1206 ): |
1207 ): |
1207 pass |
1208 pass |
1208 |
1209 |
1209 def createHierarchy(self): |
1210 def createHierarchy(self): |
1210 """ |
1211 """ |
1211 Public method to build the inheritance hierarchy for all classes of |
1212 Public method to build the inheritance hierarchy for all classes of |
1212 this module. |
1213 this module. |
1213 |
1214 |
1214 @return A dictionary with inheritance hierarchies. |
1215 @return A dictionary with inheritance hierarchies. |
1215 """ |
1216 """ |
1216 hierarchy = {} |
1217 hierarchy = {} |
1217 for class_ in self.classes: |
1218 for class_ in self.classes: |
1218 self.assembleHierarchy(class_, self.classes, [class_], hierarchy) |
1219 self.assembleHierarchy(class_, self.classes, [class_], hierarchy) |
1219 for module in self.modules: |
1220 for module in self.modules: |
1220 self.assembleHierarchy(module, self.modules, [module], hierarchy) |
1221 self.assembleHierarchy(module, self.modules, [module], hierarchy) |
1221 return hierarchy |
1222 return hierarchy |
1222 |
1223 |
1223 def assembleHierarchy(self, name, classes, path, result): |
1224 def assembleHierarchy(self, name, classes, path, result): |
1224 """ |
1225 """ |
1225 Public method to assemble the inheritance hierarchy. |
1226 Public method to assemble the inheritance hierarchy. |
1226 |
1227 |
1227 This method will traverse the class hierarchy, from a given class |
1228 This method will traverse the class hierarchy, from a given class |
1228 and build up a nested dictionary of super-classes. The result is |
1229 and build up a nested dictionary of super-classes. The result is |
1229 intended to be inverted, i.e. the highest level are the super classes. |
1230 intended to be inverted, i.e. the highest level are the super classes. |
1230 |
1231 |
1231 This code is borrowed from Boa Constructor. |
1232 This code is borrowed from Boa Constructor. |
1232 |
1233 |
1233 @param name name of class to assemble hierarchy (string) |
1234 @param name name of class to assemble hierarchy (string) |
1234 @param classes A dictionary of classes to look in. |
1235 @param classes A dictionary of classes to look in. |
1235 @param path |
1236 @param path |
1236 @param result The resultant hierarchy |
1237 @param result The resultant hierarchy |
1237 """ |
1238 """ |
1324 self.methods = {} |
1326 self.methods = {} |
1325 self.attributes = {} |
1327 self.attributes = {} |
1326 self.globals = {} |
1328 self.globals = {} |
1327 self.file = file |
1329 self.file = file |
1328 self.lineno = lineno |
1330 self.lineno = lineno |
1329 self.endlineno = -1 # marker for "not set" |
1331 self.endlineno = -1 # marker for "not set" |
1330 self.description = "" |
1332 self.description = "" |
1331 self.setPublic() |
1333 self.setPublic() |
1332 |
1334 |
1333 def addMethod(self, name, function): |
1335 def addMethod(self, name, function): |
1334 """ |
1336 """ |
1335 Public method to add information about a method. |
1337 Public method to add information about a method. |
1336 |
1338 |
1337 @param name name of method to be added (string) |
1339 @param name name of method to be added (string) |
1338 @param function Function object to be added |
1340 @param function Function object to be added |
1339 """ |
1341 """ |
1340 self.methods[name] = function |
1342 self.methods[name] = function |
1341 |
1343 |
1342 def getMethod(self, name): |
1344 def getMethod(self, name): |
1343 """ |
1345 """ |
1344 Public method to retrieve a method by name. |
1346 Public method to retrieve a method by name. |
1345 |
1347 |
1346 @param name name of the method (string) |
1348 @param name name of the method (string) |
1347 @return the named method or None |
1349 @return the named method or None |
1348 """ |
1350 """ |
1349 try: |
1351 try: |
1350 return self.methods[name] |
1352 return self.methods[name] |
1351 except KeyError: |
1353 except KeyError: |
1352 return None |
1354 return None |
1353 |
1355 |
1354 def addAttribute(self, name, attr): |
1356 def addAttribute(self, name, attr): |
1355 """ |
1357 """ |
1356 Public method to add information about attributes. |
1358 Public method to add information about attributes. |
1357 |
1359 |
1358 @param name name of the attribute to add (string) |
1360 @param name name of the attribute to add (string) |
1359 @param attr Attribute object to be added |
1361 @param attr Attribute object to be added |
1360 """ |
1362 """ |
1361 if name not in self.attributes: |
1363 if name not in self.attributes: |
1362 self.attributes[name] = attr |
1364 self.attributes[name] = attr |
1363 else: |
1365 else: |
1364 self.attributes[name].addAssignment(attr.lineno) |
1366 self.attributes[name].addAssignment(attr.lineno) |
1365 |
1367 |
1366 def getAttribute(self, name): |
1368 def getAttribute(self, name): |
1367 """ |
1369 """ |
1368 Public method to retrieve an attribute by name. |
1370 Public method to retrieve an attribute by name. |
1369 |
1371 |
1370 @param name name of the attribute (string) |
1372 @param name name of the attribute (string) |
1371 @return the named attribute or None |
1373 @return the named attribute or None |
1372 """ |
1374 """ |
1373 try: |
1375 try: |
1374 return self.attributes[name] |
1376 return self.attributes[name] |
1375 except KeyError: |
1377 except KeyError: |
1376 return None |
1378 return None |
1377 |
1379 |
1378 def addGlobal(self, name, attr): |
1380 def addGlobal(self, name, attr): |
1379 """ |
1381 """ |
1380 Public method to add information about global (class) variables. |
1382 Public method to add information about global (class) variables. |
1381 |
1383 |
1382 @param name name of the global to add (string) |
1384 @param name name of the global to add (string) |
1383 @param attr Attribute object to be added |
1385 @param attr Attribute object to be added |
1384 """ |
1386 """ |
1385 if name not in self.globals: |
1387 if name not in self.globals: |
1386 self.globals[name] = attr |
1388 self.globals[name] = attr |
1387 else: |
1389 else: |
1388 self.globals[name].addAssignment(attr.lineno) |
1390 self.globals[name].addAssignment(attr.lineno) |
1389 |
1391 |
1390 def addDescription(self, description): |
1392 def addDescription(self, description): |
1391 """ |
1393 """ |
1392 Public method to store the class docstring. |
1394 Public method to store the class docstring. |
1393 |
1395 |
1394 @param description the docstring to be stored (string) |
1396 @param description the docstring to be stored (string) |
1395 """ |
1397 """ |
1396 self.description = description |
1398 self.description = description |
1397 |
1399 |
1398 def setEndLine(self, endLineNo): |
1400 def setEndLine(self, endLineNo): |
1399 """ |
1401 """ |
1400 Public method to record the number of the last line of a class. |
1402 Public method to record the number of the last line of a class. |
1401 |
1403 |
1402 @param endLineNo number of the last line (integer) |
1404 @param endLineNo number of the last line (integer) |
1403 """ |
1405 """ |
1404 self.endlineno = endLineNo |
1406 self.endlineno = endLineNo |
1405 |
1407 |
1406 |
1408 |
1407 class RbModule(Class): |
1409 class RbModule(Class): |
1408 """ |
1410 """ |
1409 Class to represent a Ruby module. |
1411 Class to represent a Ruby module. |
1410 """ |
1412 """ |
|
1413 |
1411 def __init__(self, module, name, file, lineno): |
1414 def __init__(self, module, name, file, lineno): |
1412 """ |
1415 """ |
1413 Constructor |
1416 Constructor |
1414 |
1417 |
1415 @param module name of module containing this class (string) |
1418 @param module name of module containing this class (string) |
1416 @param name name of the class (string) |
1419 @param name name of the class (string) |
1417 @param file name of file containing this class (string) |
1420 @param file name of file containing this class (string) |
1418 @param lineno linenumber of the class definition (integer) |
1421 @param lineno linenumber of the class definition (integer) |
1419 """ |
1422 """ |
1420 Class.__init__(self, module, name, None, file, lineno) |
1423 Class.__init__(self, module, name, None, file, lineno) |
1421 self.classes = {} |
1424 self.classes = {} |
1422 |
1425 |
1423 def addClass(self, name, _class): |
1426 def addClass(self, name, _class): |
1424 """ |
1427 """ |
1425 Public method to add information about a class. |
1428 Public method to add information about a class. |
1426 |
1429 |
1427 @param name name of class to be added (string) |
1430 @param name name of class to be added (string) |
1428 @param _class Class object to be added |
1431 @param _class Class object to be added |
1429 """ |
1432 """ |
1430 self.classes[name] = _class |
1433 self.classes[name] = _class |
1431 |
1434 |
1432 |
1435 |
1433 class Function(VisibilityBase): |
1436 class Function(VisibilityBase): |
1434 """ |
1437 """ |
1435 Class to represent a Python function or method. |
1438 Class to represent a Python function or method. |
1436 """ |
1439 """ |
|
1440 |
1437 General = 0 |
1441 General = 0 |
1438 Static = 1 |
1442 Static = 1 |
1439 Class = 2 |
1443 Class = 2 |
1440 |
1444 |
1441 def __init__(self, module, name, file, lineno, signature='', |
1445 def __init__( |
1442 pyqtSignature=None, modifierType=General, annotation=""): |
1446 self, |
|
1447 module, |
|
1448 name, |
|
1449 file, |
|
1450 lineno, |
|
1451 signature="", |
|
1452 pyqtSignature=None, |
|
1453 modifierType=General, |
|
1454 annotation="", |
|
1455 ): |
1443 """ |
1456 """ |
1444 Constructor |
1457 Constructor |
1445 |
1458 |
1446 @param module name of module containing this function (string) |
1459 @param module name of module containing this function (string) |
1447 @param name name of the function (string) |
1460 @param name name of the function (string) |
1448 @param file name of file containing this function (string) |
1461 @param file name of file containing this function (string) |
1449 @param lineno linenumber of the function definition (integer) |
1462 @param lineno linenumber of the function definition (integer) |
1450 @param signature the functions call signature (string) |
1463 @param signature the functions call signature (string) |
1454 """ |
1467 """ |
1455 self.module = module |
1468 self.module = module |
1456 self.name = name |
1469 self.name = name |
1457 self.file = file |
1470 self.file = file |
1458 self.lineno = lineno |
1471 self.lineno = lineno |
1459 self.endlineno = -1 # marker for "not set" |
1472 self.endlineno = -1 # marker for "not set" |
1460 signature = _commentsub('', signature) |
1473 signature = _commentsub("", signature) |
1461 self.parameters = [e.strip() for e in signature.split(',')] |
1474 self.parameters = [e.strip() for e in signature.split(",")] |
1462 self.description = "" |
1475 self.description = "" |
1463 self.pyqtSignature = pyqtSignature |
1476 self.pyqtSignature = pyqtSignature |
1464 self.modifier = modifierType |
1477 self.modifier = modifierType |
1465 self.annotation = annotation |
1478 self.annotation = annotation |
1466 self.setPublic() |
1479 self.setPublic() |
1467 |
1480 |
1468 def addDescription(self, description): |
1481 def addDescription(self, description): |
1469 """ |
1482 """ |
1470 Public method to store the functions docstring. |
1483 Public method to store the functions docstring. |
1471 |
1484 |
1472 @param description the docstring to be stored (string) |
1485 @param description the docstring to be stored (string) |
1473 """ |
1486 """ |
1474 self.description = description |
1487 self.description = description |
1475 |
1488 |
1476 def setEndLine(self, endLineNo): |
1489 def setEndLine(self, endLineNo): |
1477 """ |
1490 """ |
1478 Public method to record the number of the last line of a class. |
1491 Public method to record the number of the last line of a class. |
1479 |
1492 |
1480 @param endLineNo number of the last line (integer) |
1493 @param endLineNo number of the last line (integer) |
1481 """ |
1494 """ |
1482 self.endlineno = endLineNo |
1495 self.endlineno = endLineNo |
1483 |
1496 |
1484 |
1497 |
1485 class Attribute(VisibilityBase): |
1498 class Attribute(VisibilityBase): |
1486 """ |
1499 """ |
1487 Class to represent a Python function or method. |
1500 Class to represent a Python function or method. |
1488 """ |
1501 """ |
|
1502 |
1489 def __init__(self, module, name, file, lineno, isSignal=False): |
1503 def __init__(self, module, name, file, lineno, isSignal=False): |
1490 """ |
1504 """ |
1491 Constructor |
1505 Constructor |
1492 |
1506 |
1493 @param module name of module containing this function (string) |
1507 @param module name of module containing this function (string) |
1494 @param name name of the function (string) |
1508 @param name name of the function (string) |
1495 @param file name of file containing this function (string) |
1509 @param file name of file containing this function (string) |
1496 @param lineno linenumber of the first attribute assignment (integer) |
1510 @param lineno linenumber of the first attribute assignment (integer) |
1497 @param isSignal flag indicating a signal definition (boolean) |
1511 @param isSignal flag indicating a signal definition (boolean) |
1538 (boolean) |
1559 (boolean) |
1539 @return reference to a Module object containing the parsed |
1560 @return reference to a Module object containing the parsed |
1540 module information (Module) |
1561 module information (Module) |
1541 """ |
1562 """ |
1542 global _modules |
1563 global _modules |
1543 |
1564 |
1544 _extensions = ( |
1565 _extensions = ( |
1545 ['.py', '.pyw', '.ptl', '.rb'] |
1566 [".py", ".pyw", ".ptl", ".rb"] if extensions is None else extensions[:] |
1546 if extensions is None else |
|
1547 extensions[:] |
|
1548 ) |
1567 ) |
1549 with contextlib.suppress(ValueError): |
1568 with contextlib.suppress(ValueError): |
1550 _extensions.remove('.py') |
1569 _extensions.remove(".py") |
1551 |
1570 |
1552 modname = module |
1571 modname = module |
1553 |
1572 |
1554 if os.path.exists(module): |
1573 if os.path.exists(module): |
1555 path = [os.path.dirname(module)] |
1574 path = [os.path.dirname(module)] |
1556 if module.lower().endswith(".py"): |
1575 if module.lower().endswith(".py"): |
1557 module = module[:-3] |
1576 module = module[:-3] |
1558 if ( |
1577 if ( |
1559 os.path.exists(os.path.join(path[0], "__init__.py")) or |
1578 os.path.exists(os.path.join(path[0], "__init__.py")) |
1560 os.path.exists(os.path.join(path[0], "__init__.rb")) or |
1579 or os.path.exists(os.path.join(path[0], "__init__.rb")) |
1561 inpackage |
1580 or inpackage |
1562 ): |
1581 ): |
1563 if basename: |
1582 if basename: |
1564 module = module.replace(basename, "") |
1583 module = module.replace(basename, "") |
1565 if os.path.isabs(module): |
1584 if os.path.isabs(module): |
1566 modname = os.path.splitdrive(module)[1][len(os.sep):] |
1585 modname = os.path.splitdrive(module)[1][len(os.sep) :] |
1567 else: |
1586 else: |
1568 modname = module |
1587 modname = module |
1569 modname = modname.replace(os.sep, '.') |
1588 modname = modname.replace(os.sep, ".") |
1570 inpackage = 1 |
1589 inpackage = 1 |
1571 else: |
1590 else: |
1572 modname = os.path.basename(module) |
1591 modname = os.path.basename(module) |
1573 for ext in _extensions: |
1592 for ext in _extensions: |
1574 if modname.lower().endswith(ext): |
1593 if modname.lower().endswith(ext): |
1575 modname = modname[:-len(ext)] |
1594 modname = modname[: -len(ext)] |
1576 break |
1595 break |
1577 module = os.path.basename(module) |
1596 module = os.path.basename(module) |
1578 |
1597 |
1579 if caching and modname in _modules: |
1598 if caching and modname in _modules: |
1580 # we've seen this module before... |
1599 # we've seen this module before... |
1581 return _modules[modname] |
1600 return _modules[modname] |
1582 |
1601 |
1583 if not ignoreBuiltinModules and module in sys.builtin_module_names: |
1602 if not ignoreBuiltinModules and module in sys.builtin_module_names: |
1584 # this is a built-in module |
1603 # this is a built-in module |
1585 mod = Module(modname, None, None) |
1604 mod = Module(modname, None, None) |
1586 if caching: |
1605 if caching: |
1587 _modules[modname] = mod |
1606 _modules[modname] = mod |
1588 return mod |
1607 return mod |
1589 |
1608 |
1590 # search the path for the module |
1609 # search the path for the module |
1591 path = [] if path is None else path[:] |
1610 path = [] if path is None else path[:] |
1592 f = None |
1611 f = None |
1593 if inpackage: |
1612 if inpackage: |
1594 try: |
1613 try: |
1595 f, file, (suff, mode, moduleType) = find_module( |
1614 f, file, (suff, mode, moduleType) = find_module(module, path, _extensions) |
1596 module, path, _extensions) |
|
1597 except ImportError: |
1615 except ImportError: |
1598 f = None |
1616 f = None |
1599 if f is None: |
1617 if f is None: |
1600 fullpath = path[:] + sys.path[:] |
1618 fullpath = path[:] + sys.path[:] |
1601 f, file, (suff, mode, moduleType) = find_module( |
1619 f, file, (suff, mode, moduleType) = find_module(module, fullpath, _extensions) |
1602 module, fullpath, _extensions) |
|
1603 if f: |
1620 if f: |
1604 f.close() |
1621 f.close() |
1605 if moduleType not in SUPPORTED_TYPES: |
1622 if moduleType not in SUPPORTED_TYPES: |
1606 # not supported source, can't do anything with this module |
1623 # not supported source, can't do anything with this module |
1607 _modules[modname] = Module(modname, None, None) |
1624 _modules[modname] = Module(modname, None, None) |
1608 return _modules[modname] |
1625 return _modules[modname] |
1609 |
1626 |
1610 mod = Module(modname, file, moduleType) |
1627 mod = Module(modname, file, moduleType) |
1611 with contextlib.suppress(UnicodeError, OSError): |
1628 with contextlib.suppress(UnicodeError, OSError): |
1612 src = Utilities.readEncodedFile(file)[0] |
1629 src = Utilities.readEncodedFile(file)[0] |
1613 mod.scan(src) |
1630 mod.scan(src) |
1614 if caching: |
1631 if caching: |
1617 |
1634 |
1618 |
1635 |
1619 def _indent(ws): |
1636 def _indent(ws): |
1620 """ |
1637 """ |
1621 Protected function to determine the indent width of a whitespace string. |
1638 Protected function to determine the indent width of a whitespace string. |
1622 |
1639 |
1623 @param ws The whitespace string to be cheked. (string) |
1640 @param ws The whitespace string to be cheked. (string) |
1624 @return Length of the whitespace string after tab expansion. |
1641 @return Length of the whitespace string after tab expansion. |
1625 """ |
1642 """ |
1626 return len(ws.expandtabs(TABWIDTH)) |
1643 return len(ws.expandtabs(TABWIDTH)) |
1627 |
1644 |
1628 |
1645 |
1629 def find_module(name, path, extensions): |
1646 def find_module(name, path, extensions): |
1630 """ |
1647 """ |
1631 Module function to extend the Python module finding mechanism. |
1648 Module function to extend the Python module finding mechanism. |
1632 |
1649 |
1633 This function searches for files in the given path. If the filename |
1650 This function searches for files in the given path. If the filename |
1634 doesn't have an extension or an extension of .py, the normal search |
1651 doesn't have an extension or an extension of .py, the normal search |
1635 implemented in the imp module is used. For all other supported files |
1652 implemented in the imp module is used. For all other supported files |
1636 only path is searched. |
1653 only path is searched. |
1637 |
1654 |
1638 @param name filename or modulename to search for (string) |
1655 @param name filename or modulename to search for (string) |
1639 @param path search path (list of strings) |
1656 @param path search path (list of strings) |
1640 @param extensions list of extensions, which should be considered valid |
1657 @param extensions list of extensions, which should be considered valid |
1641 source file extensions (list of strings) |
1658 source file extensions (list of strings) |
1642 @return tuple of the open file, pathname and description. Description |
1659 @return tuple of the open file, pathname and description. Description |
1643 is a tuple of file suffix, file mode and file type) |
1660 is a tuple of file suffix, file mode and file type) |
1644 @exception ImportError The file or module wasn't found. |
1661 @exception ImportError The file or module wasn't found. |
1645 """ |
1662 """ |
1646 for ext in extensions: |
1663 for ext in extensions: |
1647 if name.lower().endswith(ext): |
1664 if name.lower().endswith(ext): |
1648 for p in path: # only search in path |
1665 for p in path: # only search in path |
1649 if os.path.exists(os.path.join(p, name)): |
1666 if os.path.exists(os.path.join(p, name)): |
1650 pathname = os.path.join(p, name) |
1667 pathname = os.path.join(p, name) |
1651 if ext == '.ptl': |
1668 if ext == ".ptl": |
1652 # Quixote page template |
1669 # Quixote page template |
1653 return ( |
1670 return ( |
1654 open(pathname), pathname, |
1671 open(pathname), # __IGNORE_WARNING_Y115__ |
1655 # __IGNORE_WARNING_Y115__ |
1672 pathname, |
1656 ('.ptl', 'r', PTL_SOURCE) |
1673 (".ptl", "r", PTL_SOURCE), |
1657 ) |
1674 ) |
1658 elif ext == '.rb': |
1675 elif ext == ".rb": |
1659 # Ruby source file |
1676 # Ruby source file |
1660 return ( |
1677 return ( |
1661 open(pathname), pathname, |
1678 open(pathname), # __IGNORE_WARNING_Y115__ |
1662 # __IGNORE_WARNING_Y115__ |
1679 pathname, |
1663 ('.rb', 'r', RB_SOURCE) |
1680 (".rb", "r", RB_SOURCE), |
1664 ) |
1681 ) |
1665 else: |
1682 else: |
1666 return ( |
1683 return ( |
1667 open(pathname), pathname, |
1684 open(pathname), # __IGNORE_WARNING_Y115__ |
1668 # __IGNORE_WARNING_Y115__ |
1685 pathname, |
1669 (ext, 'r', PY_SOURCE) |
1686 (ext, "r", PY_SOURCE), |
1670 ) |
1687 ) |
1671 raise ImportError |
1688 raise ImportError |
1672 |
1689 |
1673 # standard Python module file |
1690 # standard Python module file |
1674 if name.lower().endswith('.py'): |
1691 if name.lower().endswith(".py"): |
1675 name = name[:-3] |
1692 name = name[:-3] |
1676 |
1693 |
1677 spec = importlib.machinery.PathFinder.find_spec(name, path) |
1694 spec = importlib.machinery.PathFinder.find_spec(name, path) |
1678 if spec is None: |
1695 if spec is None: |
1679 raise ImportError |
1696 raise ImportError |
1680 if isinstance(spec.loader, importlib.machinery.SourceFileLoader): |
1697 if isinstance(spec.loader, importlib.machinery.SourceFileLoader): |
1681 ext = os.path.splitext(spec.origin)[-1] |
1698 ext = os.path.splitext(spec.origin)[-1] |
1682 return (open(spec.origin), spec.origin, (ext, 'r', PY_SOURCE)) |
1699 return (open(spec.origin), spec.origin, (ext, "r", PY_SOURCE)) |
1683 # __IGNORE_WARNING_Y115__ |
1700 # __IGNORE_WARNING_Y115__ |
1684 |
1701 |
1685 raise ImportError |
1702 raise ImportError |
1686 |
1703 |
1687 |
1704 |
1688 def resetParsedModules(): |
1705 def resetParsedModules(): |
1689 """ |
1706 """ |
1690 Module function to reset the list of modules already parsed. |
1707 Module function to reset the list of modules already parsed. |
1691 """ |
1708 """ |
1692 _modules.clear() |
1709 _modules.clear() |
1693 |
1710 |
1694 |
1711 |
1695 def resetParsedModule(module, basename=""): |
1712 def resetParsedModule(module, basename=""): |
1696 """ |
1713 """ |
1697 Module function to clear one module from the list of parsed modules. |
1714 Module function to clear one module from the list of parsed modules. |
1698 |
1715 |
1699 @param module Name of the module to be parsed (string) |
1716 @param module Name of the module to be parsed (string) |
1700 @param basename a path basename. This basename is deleted from |
1717 @param basename a path basename. This basename is deleted from |
1701 the filename of the module file to be cleared. (string) |
1718 the filename of the module file to be cleared. (string) |
1702 """ |
1719 """ |
1703 modname = module |
1720 modname = module |
1704 |
1721 |
1705 if os.path.exists(module): |
1722 if os.path.exists(module): |
1706 path = [os.path.dirname(module)] |
1723 path = [os.path.dirname(module)] |
1707 if module.lower().endswith(".py"): |
1724 if module.lower().endswith(".py"): |
1708 module = module[:-3] |
1725 module = module[:-3] |
1709 if os.path.exists(os.path.join(path[0], "__init__.py")): |
1726 if os.path.exists(os.path.join(path[0], "__init__.py")): |
1710 if basename: |
1727 if basename: |
1711 module = module.replace(basename, "") |
1728 module = module.replace(basename, "") |
1712 modname = module.replace(os.sep, '.') |
1729 modname = module.replace(os.sep, ".") |
1713 else: |
1730 else: |
1714 modname = os.path.basename(module) |
1731 modname = os.path.basename(module) |
1715 if ( |
1732 if modname.lower().endswith(".ptl") or modname.lower().endswith(".pyw"): |
1716 modname.lower().endswith(".ptl") or |
|
1717 modname.lower().endswith(".pyw") |
|
1718 ): |
|
1719 modname = modname[:-4] |
1733 modname = modname[:-4] |
1720 elif modname.lower().endswith(".rb"): |
1734 elif modname.lower().endswith(".rb"): |
1721 modname = modname[:-3] |
1735 modname = modname[:-3] |
1722 module = os.path.basename(module) |
1736 module = os.path.basename(module) |
1723 |
1737 |
1724 if modname in _modules: |
1738 if modname in _modules: |
1725 del _modules[modname] |
1739 del _modules[modname] |