Rendier

Code Browser

Jun 22nd, 2021
775
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'rendier'
  4.  
  5. from PyQt5.QtCore import QUrl, QEvent, QVariant, Qt
  6. from PyQt5.QtGui import QIcon, QFont, QImage, QImageReader, QTextDocument, QTextImageFormat, QCursor, QTextCursor, QColor
  7. from PyQt5.QtWidgets import QApplication, QListWidgetItem, QInputDialog, QGridLayout, QAction, qApp, QWidget, QListWidget, QTextEdit, QCheckBox, QDesktopWidget, QMainWindow, QMessageBox
  8.  
  9. from Phaleron.Syntax import PythonHighlighter
  10. from Pharos.Dialogs import Dialogs
  11.  
  12. import sys, os, time, inspect, psutil, types, urllib, prettytable
  13.  
  14.  
  15. # current = dir()
  16.  
  17. # Fix these TODO
  18. # object, instance, enumeration
  19.  
  20. class StdErrHandler():
  21.     """
  22.     http://stackoverflow.com/questions/28505462/display-stderr-in-a-pyqt-qmessagebox
  23.     http://stackoverflow.com/users/3453633/carpecimex
  24.     """
  25.     def __init__(self):
  26.         # pass
  27.         # To instantiate only one message box
  28.         self.err_box = None
  29.  
  30.     def write(self, std_msg):
  31.         # All that stderr or stdout require is a class with a 'write' method.
  32.         if self.err_box is None:
  33.             self.err_box = QMessageBox()
  34.             # Both OK and window delete fire the 'finished' signal
  35.             self.err_box.finished.connect(self.clear)
  36.         # A single error is sent as a string of separate stderr .write() messages,
  37.         # so concatenate them.
  38.         self.err_box.setText(self.err_box.text() + std_msg)
  39.         # .show() is used here because .exec() or .exec_() create multiple
  40.         # MessageBoxes.
  41.         self.err_box.show()
  42.  
  43.     def clear(self):
  44.         # QMessageBox doesn't seem to be actually destroyed when closed, just hidden.
  45.         # This is true even if destroy() is called or if the Qt.WA_DeleteOnClose
  46.         # attribute is set.  Clear text for next time.
  47.         self.err_box.setText('')
  48.  
  49. thatone = StdErrHandler()
  50. # print("TYPE", type(thatone.write))
  51.  
  52. current = dir()
  53.  
  54. class CodeBrowser(QMainWindow):
  55.     """File manager like browser for installed python packages as well as current program scope.
  56.     """
  57.  
  58.     def __init__(self, current, parent=None):
  59.         super(CodeBrowser, self).__init__(parent)
  60.         QMainWindow.__init__(self)
  61.         self.setWindowTitle("Package Browser")
  62.  
  63.         self.debugger = 1
  64.         self.dPrint("INIT")
  65.  
  66.         self.parent = parent
  67.         # self.dPrint(str(self.parent))
  68.  
  69.         if self.parent:
  70.             self.dialogs = self.parent.dialogs
  71.             self.homeDir = self.parent.homeDir
  72.             self.styles = self.parent.styles
  73.  
  74.  
  75.         else:
  76.             self.dialogs = Dialogs(parent=self)
  77.             self.homeDir = "/home/rendier/Ptolemy/"
  78.             self.styles = "QWidget { border: 1px solid white; background-color: black; color: white } " \
  79.                           "QMenuBar::item { background-color: black; color: white } " \
  80.                           "QStatusBar { background-color: black; color: white } " \
  81.                           "QCheckBox {border: 1px solid black; color: white }"
  82.  
  83.         self.imgDir = self.homeDir + "images/Phaleron/old/"
  84.  
  85.         # AttributeError: type object 'WebkitRenderer' has no attribute 'im_class' line 804 repoplist TODO
  86.         self.package = "Current"
  87.         self.crumbs = ['Explorer', 'Current']
  88.         self.exploration = ""
  89.         self.geo = QDesktopWidget().frameGeometry()
  90.  
  91.         self.current = current
  92.         # if curScope:
  93.         #   self.current = curScope
  94.         # else:
  95.         #   self.current = current
  96.         # self.dPrint "self.current =", self.
  97.         self.reimport = 0
  98.         # self.debugger = 1
  99.         self.sitems = []
  100.         self.typelist = ['ellipsis', 'long', 'NoneType', 'bool', 'NotImplementedType', 'complex', 'getset_descriptor', 'classobj', 'unicode', 'code', 'object', 'file', 'member_descriptor', 'generator', 'str', 'traceback', 'slice', 'list', 'set', 'instance', 'buffer', 'frame', 'type', 'dictproxy', 'float', 'function', 'tuple', 'instancemethod', 'class', 'xrange', 'module', 'int', 'dict', 'builtin_function_or_method']
  101.         self.varlist = ['bool', 'complex', 'dict', 'dictproxy', 'float', 'generator', 'int', 'list', 'long', 'slice', 'str', 'set', 'tuple', 'namedtuple']
  102.         self.dirlist = ['class', 'module', 'builtin_method_or_function', 'function', 'method']
  103.  
  104.  
  105.         self.initUI()
  106.  
  107.     # TODO
  108.     def __del__(self):
  109.         pass
  110.  
  111.     def initUI(self):
  112.         self.dPrint('initUI')
  113.         self.setWindowIcon(QIcon(self.imgDir + 'neorendier_small.png'))
  114.  
  115.         # Main Widget
  116.         self.widget = QWidget(self)
  117.         self.widget.setStyleSheet(self.styles)
  118.  
  119.  
  120.         # Widget Instances
  121.         self.list = QListWidget(self.widget)
  122.         self.tlist = QListWidget(self.widget)
  123.         self.text = QTextEdit(self.widget)
  124.         self.bugcheck = QCheckBox(self.widget)
  125.  
  126.         # Actions
  127.         exitAction = QAction(QIcon(self.imgDir + 'exit.png'), 'E&xit', self)
  128.         exitAction.setShortcut('Ctrl+X')
  129.         exitAction.setStatusTip('Exit Application')
  130.         exitAction.triggered.connect(qApp.quit)
  131.  
  132.         openAction = QAction(QIcon(self.imgDir + 'folder_red_open.png'), '&Open', self)
  133.         openAction.setShortcut('Ctrl+O')
  134.         openAction.setStatusTip('Open New Package')
  135.         openAction.triggered.connect(self.importPkg)
  136.  
  137.         searchAction = QAction(QIcon(self.imgDir + 'search-icon.png'), 'Search Contains:', self)
  138.         searchAction.setShortcut('Ctrl+S')
  139.         searchAction.setStatusTip('Search for items that contain the search term')
  140.         searchAction.triggered.connect(self.searchList)
  141.  
  142.         debugAction = QAction(QIcon(self.imgDir + 'debug.png'), 'Debugging', self)
  143.         debugAction.setShortcut('Ctrl+D')
  144.         debugAction.triggered.connect(self.bugcheck.setChecked)
  145.  
  146.         # Menu Bar
  147.         self.topMenu = self.menuBar()
  148.         self.topMenu.setStyleSheet(self.styles)
  149.  
  150.         fileMenu = self.topMenu.addMenu('&File')
  151.         fileMenu.addAction(openAction)
  152.         fileMenu.addSeparator()
  153.         fileMenu.addAction(debugAction)
  154.         fileMenu.addSeparator()
  155.         fileMenu.addAction(exitAction)
  156.  
  157.         searchMenu = self.topMenu.addMenu('&Search')
  158.         searchMenu.addAction(searchAction)
  159.  
  160.         # Status Bar
  161.         self.status = self.statusBar()
  162.         self.status.setStyleSheet(self.styles)
  163.  
  164.         # Directory List Setup
  165.         self.list.setFont(QFont('Monospace', 9))
  166.         self.list.setFixedWidth(300)
  167.         self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  168.         self.list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  169.         self.list.currentItemChanged.connect(self.itemSelect)
  170.         self.list.itemClicked.connect(self.itemSelect)
  171.         self.list.itemDoubleClicked.connect(self.repopList)
  172.         self.list.verticalScrollBar().valueChanged.connect(self.tlist.verticalScrollBar().setValue)
  173.  
  174.         # Type List Setup
  175.         self.tlist.setFont(QFont('Monospace', 9))
  176.         self.tlist.setFixedWidth(300)
  177.         self.tlist.setMaximumWidth(300)
  178.         self.tlist.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  179.         self.tlist.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  180.         self.tlist.verticalScrollBar().valueChanged.connect(self.list.verticalScrollBar().setValue)
  181.         # self.list.currentItemChanged.connect(self.setText)#FOR WHEN TYPE LIST HAS setText TODO
  182.  
  183.         # Textbox Setup
  184.         self.text.setFont(QFont('Monospace', 9))
  185.         self.text.setReadOnly(True)
  186.         self.highlight = PythonHighlighter(self.text.document())
  187.  
  188.         # Debug Setup
  189.         self.bugcheck.setStyleSheet("QCheckBox {border: 1px solid black; color: white }")
  190.         self.bugcheck.setText("Debugging Off")
  191.         self.bugcheck.stateChanged.connect(self.debug)
  192.  
  193.         # Layout Setup
  194.         self.layout = QGridLayout(self.widget)
  195.         self.layout.addWidget(self.list, 0, 0, 10, 2)
  196.         self.layout.addWidget(self.tlist, 0, 2, 10, 1)
  197.         self.layout.addWidget(self.text, 0, 3, 10, 6)
  198.         self.layout.addWidget(self.bugcheck, 11, 0, 1, 1)
  199.  
  200.         self.setCentralWidget(self.widget)
  201.  
  202.         self.addItems()
  203.  
  204.     def addItems(self):  # MAKE TO USE ONLY REPOP LIST TODO
  205.         self.dPrint("\nADDING ITEMS")
  206.  
  207.         self.status.setStatusTip(str(".".join(self.crumbs)))
  208.         self.list.clear()
  209.         self.tlist.clear()
  210.         self.text.clear()
  211.         self.crumbs = [['Explorer', 'Current'] if self.package == 'Current' else ['Explorer', self.package]][0]
  212.         self.icrumbs = []
  213.         # if self.package == "Current":
  214.         if 'Current' in self.crumbs:
  215.             self.dirIter = self.current
  216.         else:
  217.             self.dirIter = dir(self.exploration)
  218.  
  219.         for i in self.dirIter:
  220.             dEntry = i
  221.             code = f"self.entryType = type({dEntry}).__name__"
  222.             code2 = f"self.entryType = type(self.exploration.{dEntry}).__name__"
  223.  
  224.             exec(code if 'Current' in self.crumbs else code2)
  225.  
  226.             if self.entryType not in self.varlist or self.entryType not in self.dirlist:
  227.                 self.entryType = self.wrapper_type(dEntry, self.entryType)
  228.  
  229.             self.typeSort(dEntry, self.entryType)
  230.  
  231.     def eventFilter(self, object, event):
  232.         if object == self.prev and len(self.crumbs[2:]) == 0:
  233.             self.prev.setDisabled(True)
  234.         else:
  235.             self.prev.setDisabled(False)
  236.         if event.type() == QEvent.Enter:
  237.             self.dPrint("Enter Event: Setting Blue")
  238.             object.setStyleSheet("QPushButton { border: 1px solid white; background-color: blue; color: white }")
  239.  
  240.         if event.type() == QEvent.Leave:
  241.             self.dPrint("Leave Event: Setting Blue")
  242.             object.setStyleSheet("QPushButton { border: 1px solid white; background-color: black; color: white }")
  243.  
  244.         return False
  245.  
  246.     def split(self, arr, size):
  247.         arrs = []
  248.         while len(arr) > size:
  249.             pice = arr[:size]
  250.             arrs.append(pice)
  251.             arr = arr[size:]
  252.         arrs.append(arr)
  253.         return arrs
  254.  
  255.     def insertImage(self, filePath, title):
  256.         self.dPrint("\nINSERTING IMAGE")
  257.         """http://stackoverflow.com/questions/15539075/inserting-qimage-after-string-in-qtextedit
  258.         user1006989
  259.         """
  260.         # FIND ICON PACK TO MAKE IMAGES WITH FOR EACH BUILT IN TYPE TODO
  261.         # FIX ENTERING GRAPHIC TITLE TODO
  262.  
  263.         # imageUri = QUrl(QString("./progImages/{0}".format(filePath)))
  264.         imageUri = QUrl(self.imgDir + filePath)
  265.         image = QImage(QImageReader(filePath).read())
  266.         # headerUri = QtCore.QUrl(QtCore.QString("file://home/rendier/JARVIS/working/rectgradient.jpg"))
  267.         headerUri = QUrl(self.imgDir + 'rectgradient.jpg')
  268.         header = QImage(QImageReader(self.imgDir + 'rectgradient.jpg').read())
  269.  
  270.         self.text.document().addResource(QTextDocument.ImageResource, headerUri, QVariant(header))
  271.  
  272.         imageHeader = QTextImageFormat()
  273.         imageHeader.setWidth(240)
  274.         imageHeader.setHeight(88)
  275.         imageHeader.setName(headerUri.toString())
  276.  
  277.         self.text.document().addResource(QTextDocument.ImageResource, imageUri, QVariant(image))
  278.  
  279.         imageFormat = QTextImageFormat()
  280.         imageFormat.setWidth(88)
  281.         imageFormat.setHeight(88)
  282.         imageFormat.setName(imageUri.toString())
  283.  
  284.         textCursor = self.text.textCursor()
  285.         textCursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor)
  286.  
  287.         textCursor.insertImage(imageHeader)
  288.         textCursor.insertImage(imageFormat)
  289.         headerCentered = ((self.centering - len(title)) / 2) - 4
  290.         self.text.append(self.spacer.format(title) + "\n\n")
  291.  
  292.         # This will hide the cursor
  293.         blankCursor = QCursor(Qt.BlankCursor)
  294.         self.text.setCursor(blankCursor)
  295.  
  296.     def importPkg(self):  # FIX INPUT DIALOG COLORS and from and multi import TODO
  297.         self.dPrint("\nIMPORTING PACKAGE")
  298.         # self.dPrint("importPkg", dir())
  299.  
  300.         if self.reimport == 0:
  301.             text, ok = QInputDialog.getText(self, 'Package Chooser',
  302.                                             "Please Select Package\n__main__ for Current Program Scope")
  303.  
  304.         else:
  305.             text, ok = QInputDialog.getText(self, 'Package Chooser',
  306.                                             "Package Does Not Exist\n\nPlease Select Differenet Package")
  307.             self.reimport = 0
  308.  
  309.         if ok:
  310.             if text == "":
  311.                 self.setWindowTitle("Browsing Current Scope")
  312.             else:
  313.                 self.setWindowTitle(f"Browsing Python {text} Module")
  314.             self.package = str(text)
  315.             # self.dPrint("package", self.package)
  316.             if self.package == "":
  317.                 self.package = "Current"
  318.                 self.exploration = current
  319.                 self.addItems()
  320.  
  321.             elif self.package.count(".") == 1:
  322.                 try:
  323.                     self.dPrint("SINGLE DOT")
  324.                     parts = self.package.split(".")
  325.                     self.package = str(parts[1])
  326.                     code = f"self.exploration = getattr(__import__('{parts[1]}', globals(), locals(), ['{parts[0]}',]), '{parts[1]}')"
  327.                     code2 = f"from {parts[0]} import {parts[1]}"
  328.                     self.dPrint("from import", code2)
  329.                     eval(str(self.package))
  330.                     self.addItems()
  331.  
  332.                 except ImportError:
  333.                     self.dPrint(f"Module {'.'.join(parts)} does not exist")
  334.                     self.reimport = 1
  335.                     self.importPkg()
  336.  
  337.             elif self.package.count(".") > 1:  # FIX MULTI IMPORT (OR LEARN WHY NOT) TODO
  338.  
  339.                 parts = list(self.package.split("."))
  340.                 self.package = str(parts[-1])
  341.                 try:
  342.                     code = f"self.exploration = getattr(__import__('{'.'.join(parts[:-1])}', globals(), locals(), ['{parts[-1]}',], -1), '{parts[-1]}')"
  343.                     # self.dPrint("multi import code", code)
  344.                     exec(code)
  345.                     self.addItems()
  346.  
  347.                 except ImportError:
  348.                     try:
  349.                         # self.dPrint(f"Checking if {parts[-1]} is builtin...")
  350.                         code = f"self.exploration = __import__('{parts[-1]}')"
  351.                         # self.dPrint("import error builtin check code", code)
  352.                         exec(code)
  353.                         self.addItems()
  354.  
  355.                     except ImportError:
  356.                         self.dPrint(f"Module {'.'.join(parts)} does not exist")
  357.                         self.reimport = 1
  358.                         self.importPkg()
  359.  
  360.  
  361.             else:
  362.                 try:
  363.                     code = f"self.exploration = __import__('{self.package}')"
  364.                     # self.dPrint("import code", code)
  365.                     exec(code)
  366.                     self.addItems()
  367.  
  368.                 except ImportError:
  369.                     # self.dPrint(f"Module {self.package} does not exist")
  370.                     self.reimport = 1
  371.                     self.importPkg()
  372.  
  373.     def searchList(self):
  374.         if self.sitems:
  375.             self.sitems = []
  376.             self.repopList('reload')
  377.  
  378.         term, ok = QInputDialog.getText(self, "List Search", "Enter Search Term for Current List")
  379.  
  380.         if ok:
  381.             self.sitems = self.list.findItems(term, Qt.MatchContains)
  382.             for i in self.sitems:
  383.                 i.setForeground(QColor('red'))
  384.  
  385.             dlist = self.modDir
  386.             longest = len(max(self.modDir, key=len))
  387.             # self.dPrint("longest item", longest)
  388.             tdir = self.makeTable(dlist, longest)
  389.  
  390.             entry = [str(i.text()) for i in self.sitems]
  391.             longest = len(max(entry, key=len))
  392.             # self.dPrint("longest item", longest)
  393.             table = self.split(entry, 3)
  394.             result = self.makeTable(table)
  395.             self.setText(str(result), 'search-icon.png', 'Search Results')
  396.  
  397.     def wrapper_type(self, dEntry, entryType):
  398.         self.dPrint("\nWRAPPER TYPE")
  399.         self.dPrint(f"ENTRY TYPE: {entryType}, dEntry: {dEntry}")
  400.  
  401.         if eval(f'inspect.isclass({dEntry})' if 'Current' in self.crumbs else f"inspect.isclass(self.exploration.{dEntry})"):
  402.             entryType = 'class'
  403.         elif eval(f'inspect.isbuiltin({dEntry})' if 'Current' in self.crumbs else f"inspect.isbuiltin(self.exploration.{dEntry})"):
  404.             entryType = 'builtin_function_or_method'
  405.         elif eval(f'inspect.isfunction({dEntry})' if 'Current' in self.crumbs else f"inspect.isfunction(self.exploration.{dEntry})"):
  406.             entryType = 'function'
  407.         elif eval(f'inspect.ismethod({dEntry})' if 'Current' in self.crumbs else f"inspect.ismethod(self.exploration.{dEntry})"):
  408.             entryType = 'method'
  409.         elif eval(f'inspect.ismodule({dEntry})' if 'Current' in self.crumbs else f"inspect.ismodule(self.exploration.{dEntry})"):
  410.             entryType = 'module'
  411.  
  412.         elif "." in entryType:
  413.             self.dPrint("INSTANCE")
  414.             if eval(f"isinstance({dEntry}, type({dEntry}))"):
  415.                 entryType = 'instance'
  416.  
  417.         else:
  418.             try:
  419.                 entryType = eval(f"{dEntry}.__module__" if 'Current' in self.crumbs else f"self.exploration.{dEntry}.__module__")# + str(entryType)
  420.             except AttributeError:
  421.                 pass
  422.  
  423.  
  424.         return entryType
  425.  
  426.     def typeSort(self, dEntry, entryType):
  427.         # self.dPrint("\nSORTING")
  428.         # self.dPrint(f"{'*' * 50}\nARGS: {dEntry}, {entryType}, {type(entryType)}")
  429.  
  430.         if 'wrapper' in entryType:  # MAKE SO CAN ALTER FOR SDK WRAPPERS TODO
  431.             self.listsEntry(dEntry, 'black', 'light green', entryType)
  432.  
  433.         elif entryType not in self.typelist:
  434.             self.listsEntry(dEntry, "black", 'light blue', entryType)
  435.  
  436.         elif entryType in self.varlist:
  437.             self.listsEntry(dEntry, 'black', 'yellow', entryType)
  438.  
  439.         elif entryType == 'NoneType':
  440.             self.listsEntry(dEntry, 'black', 'light grey', entryType)
  441.  
  442.         elif entryType == 'type':
  443.             self.listsEntry(dEntry, 'black', 'orange', entryType)
  444.  
  445.         elif eval(f'inspect.isbuiltin({dEntry if "Current" in self.crumbs else f"self.exploration.{dEntry}"})'):
  446.             self.listsEntry(dEntry, 'white', 'black', entryType)
  447.  
  448.         elif eval(f'inspect.isfunction({dEntry if "Current" in self.crumbs else f"self.exploration.{dEntry}"})'):
  449.             self.listsEntry(dEntry, 'white', 'dark green', entryType)
  450.  
  451.         elif eval(f'inspect.isclass({dEntry if "Current" in self.crumbs else f"self.exploration.{dEntry}"})'):
  452.             self.listsEntry(dEntry, 'white', 'dark red', entryType)
  453.  
  454.         elif eval(f'inspect.ismodule({dEntry if "Current" in self.crumbs else f"self.exploration.{dEntry}"})'):
  455.             self.listsEntry(dEntry, 'white', 'dark blue', entryType)
  456.  
  457.         elif eval(f'inspect.ismethod({dEntry if "Current" in self.crumbs else f"self.exploration.{dEntry}"})'):
  458.             self.listsEntry(dEntry, 'black', 'magenta', entryType)
  459.  
  460.         else:
  461.             entryType = self.wrapper_type(dEntry, entryType)
  462.             self.listsEntry(dEntry, 'black', 'white', entryType)
  463.  
  464.     def debug(self, state):
  465.         if state == Qt.Checked:
  466.             self.debugger = 1
  467.             self.bugcheck.setText("DEBUGGING ON")
  468.         else:
  469.             self.debugger = 0
  470.             self.bugcheck.setText("Debuging Off")
  471.  
  472.     def dPrint(self, label, data=None):
  473.         if self.debugger == 1:
  474.             if not data:
  475.                 print(f"{label}")
  476.  
  477.             else:
  478.                 print(f"{label} = {str(data)}")
  479.  
  480.     def makeTable(self, dlist, longest):
  481.         self.dPrint("\nMAKING TABLE")
  482.         # self.dPrint("dlist", dlist)
  483.         textwidth = self.text.frameGeometry().width() / 7
  484.         # self.dPrint("textwidth", textwidth)
  485.         cols = int(textwidth / longest)
  486.         # self.dPrint("columns", cols)
  487.         code = f"self.pTable = prettytable.PrettyTable({[i for i in range(cols)]})"
  488.         # self.dPrint("PrettyTable code", code)
  489.         exec(code)
  490.         # self.pTable = PrettyTable(["0", "1", "2"])
  491.         # self.dPrint("self.pTable\n", self.pTable)
  492.         self.pTable.padding_width = 0
  493.         self.pTable.align = "l"
  494.         self.pTable.header = False
  495.  
  496.         table = self.split(dlist, cols)
  497.         # self.dPrint("table", table)
  498.  
  499.         for i in table:
  500.             # self.dPrint("list item", i)
  501.             try:
  502.                 # self.dPrint("try", i)
  503.                 self.pTable.add_row(i)
  504.  
  505.             except Exception:
  506.                 # self.dPrint("except", len(i))
  507.                 fix = (cols - len(i))
  508.                 # self.dPrint("fix", fix)
  509.                 for j in range(fix):
  510.                     # self.dPrint("fixing", i)
  511.                     i.append("#")
  512.                 # self.dPrint("fixed eye", i)
  513.                 self.pTable.add_row(i)
  514.         # self.dPrint(str(self.pTable))
  515.         return self.pTable
  516.  
  517.     def itemSelect(self, item):
  518.         self.dPrint("\nITEM SELECT")
  519.         # self.dPrint("clicked item", item)
  520.         # self.dPrint("THISONE", type(item))
  521.         # self.dPrint("THATONE", item.text())
  522.         self.centering = self.text.width() / 7
  523.         self.cent = r"{: ^" + str(self.centering - 8) + r"s}"
  524.         # self.dPrint('num string', self.cent)
  525.         self.spacer = r"{:_^" + str(self.centering - 8) + r"s}"
  526.         # self.dPrint(item.text())
  527.         self.codeS = self.spacer.format("Code") + "\n\n"
  528.         self.contS = self.spacer.format("Contents") + "\n\n"
  529.         self.docS = self.spacer.format("Document String") + "\n\n"
  530.         self.valS = self.spacer.format("Value") + "\n\n"
  531.         if item != None:
  532.             self.pkg = f"{item.text()}"
  533.         self.pkg2 = self.pkg if not "." in self.pkg else self.pkg.split(".")[-1]
  534.         self.icrumbs = str(".".join(self.crumbs[2:]))
  535.         # self.dPrint("self.pkg", self.pkg)
  536.         # self.dPrint("crumbs", self.crumbs)
  537.         # self.dPrint("icrumbs", self.icrumbs)
  538.         # self.dPrint("Exploration", self.exploration)
  539.  
  540.         try:
  541.             if len(self.crumbs) >= 2:
  542.                 if len(self.crumbs[2:]) == 0:
  543.                     # self.dPrint("len(self.crumbs[2:]) == 0:")
  544.                     code = f"self.itemType = type({self.pkg}).__name__; self.docstr = {self.pkg}.__doc__"
  545.                     code2 = f"self.itemType = type(self.exploration.{self.pkg2}).__name__; self.docstr = self.exploration.{self.pkg2}.__doc__"
  546.  
  547.                     exec(code if 'Current' in self.crumbs else code2)
  548.  
  549.                 else:
  550.                     if self.pkg == "..":
  551.                         code = f"self.itemType = type({self.icrumbs}); self.docstr = {self.icrumbs}.__doc__"
  552.                         code2 = f"self.itemType = type(self.exploration.{self.icrumbs}).__name__; self.docstr = self.exploration.{self.icrumbs}.__doc__"
  553.                         exec(code if 'Current' in self.crumbs else code2)
  554.  
  555.                     else:
  556.                         code = f"self.itemType = type({self.icrumbs}.{self.pkg2}).__name__; self.docstr = {self.icrumbs}.{self.pkg2}.__doc__"
  557.                         code2 = f"self.itemType = type(self.exploration.{self.icrumbs}.{self.pkg2}).__name__; self.docstr = self.exploration.{self.icrumbs}.{self.pkg2}"
  558.                         exec(code if 'Current' in self.crumbs else code2)
  559.  
  560.             else:
  561.                 code = f"self.itemType = type(self.exploration.{self.icrumbs}); self.docstr = self.exploration.{self.icrumbs}"
  562.                 code2 = f"self.itemType = type(self.exploration.{self.icrumbs}.{self.pkg}).__name__; self.docstr = self.exploration.{self.icrumbs}.{self.pkg}"
  563.                 exec(code if self.pkg == '..' else code2)
  564.  
  565.             if self.docstr == None:
  566.                 self.docstr = "No Documentation For Selected Item"
  567.  
  568.             self.docstr = f"{self.docS}\n\n{self.docstr}\n\n"
  569.             # self.dPrint("self.itemType", str(self.itemType))
  570.             # self.dPrint("self.docstr", str(self.docstr))
  571.             self.getText()
  572.  
  573.         except AttributeError:
  574.             raise AttributeError
  575.             pass
  576.  
  577.     def getcode(self, obj):
  578.         self.dPrint("\nGETCODE")
  579.         try:
  580.             sourceLines = "".join(inspect.getsourcelines(self.obj)[0]).replace("\t", "    ")
  581.  
  582.         except (IOError, TypeError):
  583.             sourceLines = "NO CODE AVAILABLE FIX THIS TODO"  # FIX THIS WITH MATH2 TODO
  584.  
  585.         return sourceLines
  586.  
  587.     def parse_crumbs(self):
  588.         self.dPrint("\nPARSE CRUMBS")
  589.         self.pkg2 = self.pkg if not "." in self.pkg else self.pkg.split(".")[-1]
  590.         if len(self.crumbs[2:]) == 0:
  591.             code = f"self.table = dir({self.pkg}); self.obj = {self.pkg}"
  592.             code2 = f"self.table = dir(self.exploration.{self.pkg}); self.obj = self.exploration.{self.pkg}"
  593.             exec(code if 'Current' in self.crumbs else code2)
  594.  
  595.             # if len(self.crumbs[2:]) == 0:
  596.             #   code = f"self.table = dir({self.pkg}); self.obj = {self.pkg}"
  597.             #   self.dPrint("current short self.modDir code", code)
  598.             #   exec(code)
  599.             # else:
  600.             #   code = f"self.table = dir({self.icrumbs}.{self.pkg2}); self.obj = {self.icrumbs}.{self.pkg2}"
  601.             #   self.dPrint("current long self.modDir code", code)
  602.             #   exec(code)
  603.         # elif len(self.crumbs[2:]) == 0:
  604.         #   code = f"self.table = dir(self.exploration.{self.pkg}); self.obj = self.exploration.{self.pkg}"
  605.         #   # self.dPrint("short self.modDir code", code)
  606.         #   exec(code)
  607.         else:
  608.             code = f"self.table = dir({self.icrumbs}.{self.pkg2}); self.obj = {self.icrumbs}.{self.pkg2}"
  609.             code2 = f"self.table = dir(self.exploration.{self.icrumbs}.{self.pkg2}); self.obj = self.exploration.{self.icrumbs}.{self.pkg2}"
  610.             # self.dPrint("long self.modDir code", code)
  611.             exec(code if 'Current' in self.crumbs else code2)
  612.  
  613.         return self.table, self.obj
  614.  
  615.     def typeModule(self):
  616.         self.dPrint("\n<MODULE>")
  617.  
  618.         self.modDir, self.obj = self.parse_crumbs()
  619.  
  620.         sourceLines = self.getcode(self.obj)
  621.  
  622.         longest = len(max(self.modDir, key=len))
  623.         # self.dPrint("longest item", longest)
  624.         tdir = self.makeTable(self.modDir, longest)
  625.  
  626.         self.highlight.setDocument(self.text.document())
  627.  
  628.         entry = f"{self.docstr}{self.contS}{str(tdir)}\n\n{self.codeS}{sourceLines}"
  629.         self.setText(entry, 'blueberry_folder.png', 'Module Object')
  630.  
  631.     def typeClass(self):
  632.         self.dPrint("\n<CLASSOBJ>")
  633.  
  634.         self.classDir, self.obj = self.parse_crumbs()
  635.         sourceLines = self.getcode(self.obj)
  636.         # self.dPrint("sourceLines", sourceLines)
  637.  
  638.         longest = len(max(self.classDir, key=len))
  639.         # self.dPrint("longest item", longest)
  640.         tdir = self.makeTable(self.classDir, longest)
  641.  
  642.         self.highlight.setDocument(self.text.document())
  643.  
  644.         entry = "{0}{1}{2}\n\n{3}{4}".format(self.docstr, self.contS, str(tdir), self.codeS, sourceLines)
  645.  
  646.         self.setText(entry, "ruby_folder.png", "Class Object")
  647.  
  648.     def typeMethod(self):# Fix instance method of code TODO
  649.         self.dPrint("\n<INSTANCE METHOD>")
  650.  
  651.         self.methodOf, self.obj = self.parse_crumbs()
  652.  
  653.         methodTitle = self.cent.format(f"Instance Method of {'.'.join(self.crumbs[2:])}.{self.obj.__name__}\n\n")
  654.  
  655.         sourceLines = self.getcode(self.obj)
  656.         # self.dPrint("sourceLines", sourceLines)
  657.  
  658.         self.highlight.setDocument(self.text.document())
  659.  
  660.         # self.dPrint("methodOf", self.methodOf)
  661.         # self.dPrint("sourceLines", sourceLines)
  662.  
  663.         entry = f"{methodTitle}{self.docstr}{self.codeS}{sourceLines}"
  664.         self.setText(entry, 'parentheses.png', "Instance Method")
  665.  
  666.     def typeFunction(self): # Fix function of code TODO
  667.         self.dPrint("\n<FUNCTION>")
  668.  
  669.         self.functionOf, self.obj = self.parse_crumbs()
  670.         # self.dPrint("obj", self.obj)
  671.  
  672.         functionTitle = self.cent.format(f"Function of {self.functionOf}\n\n")
  673.  
  674.         sourceLines = self.getcode(self.obj)
  675.         # self.dPrint("sourceLines", sourceLines)
  676.  
  677.         # self.highlight.setDocument(self.text.document())
  678.  
  679.         entry = f"{functionTitle}{self.docstr}{self.codeS}#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n{sourceLines}"
  680.         self.highlight.setDocument(self.text.document())
  681.  
  682.         self.setText(entry, 'python-bytecode.png', "Function Code")
  683.  
  684.     def typeWrapper(self):
  685.         self.dPrint("\n<WRAPPERTYPE>")
  686.         # self.dPrint('package:', self.pkg)
  687.  
  688.         self.classDir, self.obj = self.parse_crumbs()
  689.  
  690.         # self.dPrint("OBJ:", self.obj)
  691.         sourceLines = self.getcode(self.obj)
  692.         # self.dPrint("sourceLines", sourceLines)
  693.  
  694.         self.highlight.setDocument(self.text.document())
  695.         #self.highlight.highlightBlock(sourceLines)
  696.  
  697.         entry = f"{self.cent.format(self.pkg)}\n\n{self.cent.format(self.itemType)}\n\n{self.docstr}{self.codeS}{sourceLines}"
  698.         # self.dPrint('entry', entry)
  699.         self.setText(entry, "ruby_folder.png", "Wrapper Object")
  700.  
  701.     def typeBuiltin(self):
  702.         self.dPrint("\n<BUILTIN>")
  703.         entry = f"\n\n{self.cent.format('CODE CANNOT BE RETRIEVED FOR BUILTIN FUNCTIONS')}\n\n\nYET\n\n{self.docstr}"
  704.         # self.dPrint("entry", entry)
  705.         self.setText(entry, 'python-builtins.png', "Builtin Functions")
  706.  
  707.     def typeType(self):
  708.         self.dPrint("\n<TYPE>")
  709.         entry = f"{self.docstr}\n\n{self.cent.format('NO DATA FOR TYPE <TYPE>')}\n\n\nYET"
  710.         # self.dPrint("entry", entry)
  711.         self.setText(entry, 'python-type.png', 'Type Type')
  712.  
  713.     def typeVariables(self):
  714.         self.dPrint("\n<COLLECTION>")
  715.  
  716.         _, self.dataObj = self.parse_crumbs()
  717.  
  718.         entry = f"{self.docstr}{self.valS}{self.dataObj}"
  719.         # self.dPrint('entry', entry)
  720.         self.highlight.setDocument(self.text.document())
  721.  
  722.         self.setText(entry, 'stickynotes.png', "Collection Object")
  723.  
  724.     def typePrevious(self):  # ADD PREVIOUS self.direcTORY STRUCTURE TO DOCSTR TODO
  725.         self.dPrint("\n<PREVIOUS>")
  726.         entry = "Put Previous self.directory name and listing here"
  727.         self.setText(entry, "previous.png", "Previous self.directory")
  728.  
  729.     def typeUnknown(self):  # DOCUMENT SOMETHING HERE SUCH AS DOCSTRING & self.direcTORY TODO
  730.         self.dPrint("\n<UNKNOWN TYPE>")
  731.         entry = f"{self.docstr}"
  732.         # self.dPrint("entry", entry)
  733.         self.setText(entry, 'unknown.png', "Unknown Types")
  734.  
  735.     def getText(self):
  736.         self.dPrint("\nGETTING TEXT")
  737.         # print("itemType:", self.itemType)
  738.         self.highlight.setDocument(None)
  739.         # self.itemType = self.entryType
  740.  
  741.         if str(self.pkg) == "..":
  742.             self.typePrevious()
  743.  
  744.         elif str(self.itemType) == 'wrappertype':
  745.             self.typeWrapper()
  746.  
  747.         elif self.itemType == 'class':
  748.             self.typeClass()
  749.  
  750.         elif self.itemType == 'function':
  751.             self.typeFunction()
  752.  
  753.         elif self.itemType == 'builtin_function_or_method':
  754.             self.typeBuiltin()
  755.  
  756.         elif self.itemType == 'type':
  757.             self.typeType()
  758.  
  759.         elif self.itemType == 'module':
  760.             self.typeModule()
  761.  
  762.         elif self.itemType == 'method':
  763.             self.typeMethod()
  764.  
  765.         elif self.itemType in self.varlist:
  766.             self.typeVariables()
  767.  
  768.         else:
  769.             self.dPrint("\n<???UNKNOWN???>")
  770.  
  771.             self.setText(f"{self.itemType}\n{self.docstr}", 'unknown.png', 'UNKNOWN')
  772.  
  773.     def setText(self, entry, headImg, title):
  774.         self.dPrint("\nSETTING TEXT")
  775.         self.text.clear()
  776.         self.insertImage(headImg, title)
  777.         self.text.append(entry)
  778.         self.text.verticalScrollBar().setValue(0)
  779.  
  780.     def repopList(self, item):
  781.         self.dPrint("\nREPOPULATING LIST")
  782.         # self.dPrint("clicked item", item)
  783.         try:
  784.             entry = str(item.text())
  785.             # self.dPrint('item text', entry)
  786.         except AttributeError:
  787.             entry = str(item)
  788.  
  789.         # self.dPrint("entry", entry)
  790.         self.list.clear()
  791.         self.tlist.clear()
  792.  
  793.         if entry == "..":
  794.             self.dPrint("\nREPOP PREVIOUS")
  795.             # self.dPrint(self.crumbs)
  796.             self.crumbs.pop()
  797.             # self.dPrint(self.crumbs)
  798.  
  799.             if len(self.crumbs) > 2:
  800.                 self.listsEntry('..', 'white', 'black', 'Previous')
  801.  
  802.             self.setStatusTip(str(".".join(self.crumbs)))
  803.  
  804.             if len(self.crumbs[2:]) == 0:
  805.  
  806.                 code = "self.direc = current"
  807.                 code2 = "self.direc = dir(self.exploration)"
  808.                 exec(code if 'Current' in self.crumbs else code2)
  809.  
  810.             else:
  811.  
  812.                 code = f"self.direc = dir({'.'.join(self.crumbs[2:])})"
  813.                 code2 = f"self.direc = dir(self.exploration.{'.'.join(self.crumbs[2:])})"
  814.                 exec(code if 'Current' in self.crumbs else code2)
  815.  
  816.             self.dPrint("prev self.direc", self.direc)
  817.  
  818.         elif entry == 'reload':
  819.             self.dPrint("\nRELOADING")
  820.             if len(self.crumbs) > 2:
  821.                 self.listsEntry('..', 'white', 'black', 'Previous')
  822.  
  823.         else:
  824.             self.dPrint("\nREPOP FORWARD")
  825.             self.crumbs.append(entry if not "." in entry else entry.split('.')[-1])
  826.             # self.dPrint("crumbs", self.crumbs)
  827.             self.setStatusTip(str(".".join(self.crumbs)))
  828.  
  829.             code = "self.direc = dir({0})".format(".".join(self.crumbs[2:]))
  830.             code2 = "self.direc = dir(self.exploration.{0})".format(".".join(self.crumbs[2:]))
  831.             exec(code  if 'Current' in self.crumbs else code2)
  832.  
  833.             self.listsEntry("..", "white", 'black', 'Previous')
  834.  
  835.         for i in self.direc:
  836.             dEntry = str(i)
  837.             # self.dPrint("dEntry", dEntry)
  838.             self.crumbs.append(dEntry)
  839.             # self.dPrint("dEntry in crumbs", self.crumbs)
  840.             if "Current" in self.crumbs:
  841.  
  842.                 code = f"self.entryType = type({self.pkg})"
  843.                 code2 = f"self.entryType = type({'.'.join(self.crumbs[2:])}).__name__"
  844.                 exec(code if len(self.crumbs[2:]) == 0 else code2)
  845.  
  846.             else:
  847.                 code = f"self.entryType = type(self.exploration.{'.'.join(self.crumbs[2:])}).__name__"
  848.                 self.dPrint("second self.entryType code", code)
  849.                 exec(code)
  850.  
  851.             # self.dPrint("self.entryType", self.entryType)
  852.             self.typeSort(f'{".".join(self.crumbs[2:])}', self.entryType)
  853.             self.crumbs.remove(dEntry)
  854.             # self.dPrint("dEntry out crumbs", self.crumbs)
  855.             # self.dPrint("THISONEHERE")
  856.  
  857.     def listsEntry(self, text, tcolor, bcolor, entryType):
  858.         # self.dPrint("\nENTERING LIST ITEM")
  859.         # self.dPrint(f"ARGS: {text}, {tcolor}, {bcolor}, {entryType}")
  860.         itemIn = QListWidgetItem(text)
  861.         itemIn.setForeground(QColor(tcolor))
  862.         itemIn.setBackground(QColor(bcolor))
  863.         entry = str(entryType)
  864.         typeIn = QListWidgetItem(entry)
  865.         typeIn.setForeground(QColor(tcolor))
  866.  
  867.         typeIn.setToolTip(str(entryType.__doc__))
  868.         typeIn.setBackground(QColor(bcolor))
  869.         self.list.addItem(itemIn)
  870.         self.tlist.addItem(typeIn)
  871.  
  872.     def setCurrent(self, cursco):
  873.         self.dPrint("\nSET CURRENT")
  874.         self.current = cursco
  875.  
  876.  
  877. def main(current):
  878.  
  879.     app = QApplication(sys.argv)
  880.     app.setApplicationName('Package Browser')
  881.     # app.setStyleSheet("QMainWindow { background-color: black; color: white }")
  882.     Explorer = CodeBrowser(current)
  883.     # Explorer.resize((Explorer.geo.width()/6)*4, (Explorer.geo.height()/4)*3)
  884.     Explorer.setWindowTitle("Package Browser")
  885.     # Explorer.setWindowFlags(Explorer.windowFlags() | QtCore.Qt.FramelessWindowHint)
  886.     Explorer.setStyleSheet("QMainWindow { background-color: black; color: white }")
  887.     # Explorer.resizeEvent.connect()
  888.     # Explorer.showMaximized()
  889.     Explorer.show()
  890.  
  891.     # stdErrHandler = StdErrHandler() TODO
  892.     # sys.stderr = stdErrHandler
  893.     # It's exec_ because exec is a reserved word in Python
  894.     sys.exit(app.exec_())
  895.  
  896.  
  897.  
  898. # self.dPrint "after import", current
  899.  
  900. if __name__ == "__main__":
  901.     main(current)
RAW Paste Data