Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
browser.py261 linesDownload Raw Back to idlelib
1"""Module browser.2 3XXX TO DO:4 5- reparse when source changed (maybe just a button would be OK?)6    (or recheck on window popup)7- add popup menu with more options (e.g. doc strings, base classes, imports)8- add base classes to class browser tree9"""10 11import os12import pyclbr13import sys14 15from idlelib.config import idleConf16from idlelib import pyshell17from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas18from idlelib.util import py_extensions19from idlelib.window import ListedToplevel20 21 22file_open = None  # Method...Item and Class...Item use this.23# Normally pyshell.flist.open, but there is no pyshell.flist for htest.24 25# The browser depends on pyclbr and importlib which do not support .pyi files.26browseable_extension_blocklist = ('.pyi',)27 28 29def is_browseable_extension(path):30    _, ext = os.path.splitext(path)31    ext = os.path.normcase(ext)32    return ext in py_extensions and ext not in browseable_extension_blocklist33 34 35def transform_children(child_dict, modname=None):36    """Transform a child dictionary to an ordered sequence of objects.37 38    The dictionary maps names to pyclbr information objects.39    Filter out imported objects.40    Augment class names with bases.41    The insertion order of the dictionary is assumed to have been in line42    number order, so sorting is not necessary.43 44    The current tree only calls this once per child_dict as it saves45    TreeItems once created.  A future tree and tests might violate this,46    so a check prevents multiple in-place augmentations.47    """48    obs = []  # Use list since values should already be sorted.49    for key, obj in child_dict.items():50        if modname is None or obj.module == modname:51            if hasattr(obj, 'super') and obj.super and obj.name == key:52                # If obj.name != key, it has already been suffixed.53                supers = []54                for sup in obj.super:55                    if isinstance(sup, str):56                        sname = sup57                    else:58                        sname = sup.name59                        if sup.module != obj.module:60                            sname = f'{sup.module}.{sname}'61                    supers.append(sname)62                obj.name += '({})'.format(', '.join(supers))63            obs.append(obj)64    return obs65 66 67class ModuleBrowser:68    """Browse module classes and functions in IDLE.69    """70    # This class is also the base class for pathbrowser.PathBrowser.71    # Init and close are inherited, other methods are overridden.72    # PathBrowser.__init__ does not call __init__ below.73 74    def __init__(self, master, path, *, _htest=False, _utest=False):75        """Create a window for browsing a module's structure.76 77        Args:78            master: parent for widgets.79            path: full path of file to browse.80            _htest - bool; change box location when running htest.81            -utest - bool; suppress contents when running unittest.82 83        Global variables:84            file_open: Function used for opening a file.85 86        Instance variables:87            name: Module name.88            file: Full path and module with supported extension.89                Used in creating ModuleBrowserTreeItem as the rootnode for90                the tree and subsequently in the children.91        """92        self.master = master93        self.path = path94        self._htest = _htest95        self._utest = _utest96        self.init()97 98    def close(self, event=None):99        "Dismiss the window and the tree nodes."100        self.top.destroy()101        self.node.destroy()102 103    def init(self):104        "Create browser tkinter widgets, including the tree."105        global file_open106        root = self.master107        flist = (pyshell.flist if not (self._htest or self._utest)108                 else pyshell.PyShellFileList(root))109        file_open = flist.open110        pyclbr._modules.clear()111 112        # create top113        self.top = top = ListedToplevel(root)114        top.protocol("WM_DELETE_WINDOW", self.close)115        top.bind("<Escape>", self.close)116        if self._htest: # place dialog below parent if running htest117            top.geometry("+%d+%d" %118                (root.winfo_rootx(), root.winfo_rooty() + 200))119        self.settitle()120        top.focus_set()121 122        # create scrolled canvas123        theme = idleConf.CurrentTheme()124        background = idleConf.GetHighlight(theme, 'normal')['background']125        sc = ScrolledCanvas(top, bg=background, highlightthickness=0,126                            takefocus=1)127        sc.frame.pack(expand=1, fill="both")128        item = self.rootnode()129        self.node = node = TreeNode(sc.canvas, None, item)130        if not self._utest:131            node.update()132            node.expand()133 134    def settitle(self):135        "Set the window title."136        self.top.wm_title("Module Browser - " + os.path.basename(self.path))137        self.top.wm_iconname("Module Browser")138 139    def rootnode(self):140        "Return a ModuleBrowserTreeItem as the root of the tree."141        return ModuleBrowserTreeItem(self.path)142 143 144class ModuleBrowserTreeItem(TreeItem):145    """Browser tree for Python module.146 147    Uses TreeItem as the basis for the structure of the tree.148    Used by both browsers.149    """150 151    def __init__(self, file):152        """Create a TreeItem for the file.153 154        Args:155            file: Full path and module name.156        """157        self.file = file158 159    def GetText(self):160        "Return the module name as the text string to display."161        return os.path.basename(self.file)162 163    def GetIconName(self):164        "Return the name of the icon to display."165        return "python"166 167    def GetSubList(self):168        "Return ChildBrowserTreeItems for children."169        return [ChildBrowserTreeItem(obj) for obj in self.listchildren()]170 171    def OnDoubleClick(self):172        "Open a module in an editor window when double clicked."173        if not is_browseable_extension(self.file):174            return175        if not os.path.exists(self.file):176            return177        file_open(self.file)178 179    def IsExpandable(self):180        "Return True if Python file."181        return is_browseable_extension(self.file)182 183    def listchildren(self):184        "Return sequenced classes and functions in the module."185        if not is_browseable_extension(self.file):186            return []187        dir, base = os.path.split(self.file)188        name, _ = os.path.splitext(base)189        try:190            tree = pyclbr.readmodule_ex(name, [dir] + sys.path)191        except ImportError:192            return []193        return transform_children(tree, name)194 195 196class ChildBrowserTreeItem(TreeItem):197    """Browser tree for child nodes within the module.198 199    Uses TreeItem as the basis for the structure of the tree.200    """201 202    def __init__(self, obj):203        "Create a TreeItem for a pyclbr class/function object."204        self.obj = obj205        self.name = obj.name206        self.isfunction = isinstance(obj, pyclbr.Function)207 208    def GetText(self):209        "Return the name of the function/class to display."210        name = self.name211        if self.isfunction:212            return "def " + name + "(...)"213        else:214            return "class " + name215 216    def GetIconName(self):217        "Return the name of the icon to display."218        if self.isfunction:219            return "python"220        else:221            return "folder"222 223    def IsExpandable(self):224        "Return True if self.obj has nested objects."225        return self.obj.children != {}226 227    def GetSubList(self):228        "Return ChildBrowserTreeItems for children."229        return [ChildBrowserTreeItem(obj)230                for obj in transform_children(self.obj.children)]231 232    def OnDoubleClick(self):233        "Open module with file_open and position to lineno."234        try:235            edit = file_open(self.obj.file)236            edit.gotoline(self.obj.lineno)237        except (OSError, AttributeError):238            pass239 240 241def _module_browser(parent): # htest #242    if len(sys.argv) > 1:  # If pass file on command line.243        file = sys.argv[1]244    else:245        file = __file__246        # Add nested objects for htest.247        class Nested_in_func(TreeNode):248            def nested_in_class(): pass249        def closure():250            class Nested_in_closure: pass251    ModuleBrowser(parent, file, _htest=True)252 253 254if __name__ == "__main__":255    if len(sys.argv) == 1:  # If pass file on command line, unittest fails.256        from unittest import main257        main('idlelib.idle_test.test_browser', verbosity=2, exit=False)258 259    from idlelib.idle_test.htest import run260    run(_module_browser)261 
codekingpro/portable-devtools · Team Ai