Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
CallTips.py220 linesDownload Raw Back to idle
1# CallTips.py - An IDLE extension that provides "Call Tips" - ie, a floating window that2# displays parameter information as you open parens.3 4import inspect5import string6import sys7import traceback8 9 10class CallTips:11    menudefs = []12 13    keydefs = {14        "<<paren-open>>": ["<Key-parenleft>"],15        "<<paren-close>>": ["<Key-parenright>"],16        "<<check-calltip-cancel>>": ["<KeyRelease>"],17        "<<calltip-cancel>>": ["<ButtonPress>", "<Key-Escape>"],18    }19 20    windows_keydefs = {}21 22    unix_keydefs = {}23 24    def __init__(self, editwin):25        self.editwin = editwin26        self.text = editwin.text27        self.calltip = None28        if hasattr(self.text, "make_calltip_window"):29            self._make_calltip_window = self.text.make_calltip_window30        else:31            self._make_calltip_window = self._make_tk_calltip_window32 33    def close(self):34        self._make_calltip_window = None35 36    # Makes a Tk based calltip window.  Used by IDLE, but not Pythonwin.37    # See __init__ above for how this is used.38    def _make_tk_calltip_window(self):39        import CallTipWindow40 41        return CallTipWindow.CallTip(self.text)42 43    def _remove_calltip_window(self):44        if self.calltip:45            self.calltip.hidetip()46            self.calltip = None47 48    def paren_open_event(self, event):49        self._remove_calltip_window()50        arg_text = get_arg_text(self.get_object_at_cursor())51        if arg_text:52            self.calltip_start = self.text.index("insert")53            self.calltip = self._make_calltip_window()54            self.calltip.showtip(arg_text)55        return ""  # so the event is handled normally.56 57    def paren_close_event(self, event):58        # Now just hides, but later we should check if other59        # paren'd expressions remain open.60        self._remove_calltip_window()61        return ""  # so the event is handled normally.62 63    def check_calltip_cancel_event(self, event):64        if self.calltip:65            # If we have moved before the start of the calltip,66            # or off the calltip line, then cancel the tip.67            # (Later need to be smarter about multi-line, etc)68            if self.text.compare(69                "insert", "<=", self.calltip_start70            ) or self.text.compare("insert", ">", self.calltip_start + " lineend"):71                self._remove_calltip_window()72        return ""  # so the event is handled normally.73 74    def calltip_cancel_event(self, event):75        self._remove_calltip_window()76        return ""  # so the event is handled normally.77 78    def get_object_at_cursor(79        self,80        wordchars="._"81        + string.ascii_uppercase82        + string.ascii_lowercase83        + string.digits,84    ):85        # XXX - This needs to be moved to a better place86        # so the "." attribute lookup code can also use it.87        text = self.text88        chars = text.get("insert linestart", "insert")89        i = len(chars)90        while i and chars[i - 1] in wordchars:91            i = i - 192        word = chars[i:]93        if word:94            # How is this for a hack!95            import __main__96 97            namespace = sys.modules.copy()98            namespace.update(__main__.__dict__)99            try:100                return eval(word, namespace)101            except:102                pass103        return None  # Can't find an object.104 105 106def _find_constructor(class_ob):107    # Given a class object, return a function object used for the108    # constructor (ie, __init__() ) or None if we can't find one.109    try:110        return class_ob.__init__111    except AttributeError:112        for base in class_ob.__bases__:113            rc = _find_constructor(base)114            if rc is not None:115                return rc116    return None117 118 119def get_arg_text(ob):120    # Get a string describing the arguments for the given object.121    argText = ""122    if ob is not None:123        if inspect.isclass(ob):124            # Look for the highest __init__ in the class chain.125            fob = _find_constructor(ob)126            if fob is None:127                fob = lambda: None128        else:129            fob = ob130        if inspect.isfunction(fob) or inspect.ismethod(fob):131            try:132                argText = str(inspect.signature(fob))133            except:134                print("Failed to format the args")135                traceback.print_exc()136        # See if we can use the docstring137        if hasattr(ob, "__doc__"):138            doc = ob.__doc__139            try:140                doc = doc.strip()141                pos = doc.find("\n")142            except AttributeError:143                ## New style classes may have __doc__ slot without actually144                ## having a string assigned to it145                pass146            else:147                if pos < 0 or pos > 70:148                    pos = 70149                if argText:150                    argText = argText + "\n"151                argText = argText + doc[:pos]152 153    return argText154 155 156#################################################157#158# Test code159#160if __name__ == "__main__":161 162    def t1():163        "()"164 165    def t2(a, b=None):166        "(a, b=None)"167 168    def t3(a, *args):169        "(a, *args)"170 171    def t4(*args):172        "(*args)"173 174    def t5(a, *args):175        "(a, *args)"176 177    def t6(a, b=None, *args, **kw):178        "(a, b=None, *args, **kw)"179 180    class TC:181        "(self, a=None, *b)"182 183        def __init__(self, a=None, *b):184            "(self, a=None, *b)"185 186        def t1(self):187            "(self)"188 189        def t2(self, a, b=None):190            "(self, a, b=None)"191 192        def t3(self, a, *args):193            "(self, a, *args)"194 195        def t4(self, *args):196            "(self, *args)"197 198        def t5(self, a, *args):199            "(self, a, *args)"200 201        def t6(self, a, b=None, *args, **kw):202            "(self, a, b=None, *args, **kw)"203 204    def test(tests):205        failed = []206        for t in tests:207            expected = t.__doc__ + "\n" + t.__doc__208            if get_arg_text(t) != expected:209                failed.append(t)210                print(211                    "%s - expected %s, but got %s"212                    % (t, repr(expected), repr(get_arg_text(t)))213                )214        print("%d of %d tests failed" % (len(failed), len(tests)))215 216    tc = TC()217    tests = t1, t2, t3, t4, t5, t6, TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6218 219    test(tests)220 
codekingpro/portable-devtools · Team Ai