Skip to content

IDLE: Calltip fails if __getattr__ raises exception #60834

Closed

Description

@serwy
mannequin
BPO 16630
Nosy @terryjreedy, @serwy, @serhiy-storchaka
Dependencies
  • bpo-20122: Move CallTips tests to idle_tests
  • Files
  • calltips_getattr_error.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/terryjreedy'
    closed_at = <Date 2014-01-21.20:48:10.825>
    created_at = <Date 2012-12-07.01:46:15.521>
    labels = ['easy', 'expert-IDLE', 'type-bug']
    title = 'IDLE: Calltip fails if __getattr__ raises exception'
    updated_at = <Date 2014-01-21.20:48:10.824>
    user = 'https://github.com/serwy'

    bugs.python.org fields:

    activity = <Date 2014-01-21.20:48:10.824>
    actor = 'terry.reedy'
    assignee = 'terry.reedy'
    closed = True
    closed_date = <Date 2014-01-21.20:48:10.825>
    closer = 'terry.reedy'
    components = ['IDLE']
    creation = <Date 2012-12-07.01:46:15.521>
    creator = 'roger.serwy'
    dependencies = ['20122']
    files = ['28231']
    hgrepos = []
    issue_num = 16630
    keywords = ['patch', 'easy', 'needs review']
    message_count = 5.0
    messages = ['177064', '177076', '207820', '208701', '208703']
    nosy_count = 4.0
    nosy_names = ['terry.reedy', 'roger.serwy', 'python-dev', 'serhiy.storchaka']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue16630'
    versions = ['Python 2.7', 'Python 3.3', 'Python 3.4']

    Activity

    1. serwy commented on Dec 7, 2012

      serwymannequin
      MannequinAuthor

      The calltip fails if __getattr__ raises an exception. Take as an example:

      Python 3.4.0a0 (default:0238cc842805+, Dec  6 2012, 19:17:04) 
      [GCC 4.7.2] on linux
      Type "copyright", "credits" or "license()" for more information.
      >>> class Test:
      	def __getattr__(self, name):
      		raise Exception()

      >> a = Test()
      >> a(

      This traceback is sent to stderr:

      Exception in Tkinter callback
      Traceback (most recent call last):
        File "/home/serwy/Code/python/cpython/Lib/tkinter/__init__.py", line 1442, in __call__
          return self.func(*args)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/MultiCall.py", line 166, in handler
          r = l[i](event)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/CallTips.py", line 56, in try_open_calltip_event
          self.open_calltip(False)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/CallTips.py", line 75, in open_calltip
          argspec = self.fetch_tip(expression)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/CallTips.py", line 101, in fetch_tip
          (expression,), {})
        File "/home/serwy/Code/python/cpython/Lib/idlelib/rpc.py", line 216, in remotecall
          return self.asyncreturn(seq)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/rpc.py", line 247, in asyncreturn
          return self.decoderesponse(response)
        File "/home/serwy/Code/python/cpython/Lib/idlelib/rpc.py", line 267, in decoderesponse
          raise what
      Exception

      The attached patch fixes the issue.

    2. serhiy-storchaka commented on Dec 7, 2012

      @serhiy-storchaka
      Member
      1. rpcclt.remotecall also can raise an exception.

      2. I think fetch_tip() should return '' in case of exception as for non-existent arguments or for non-callables. You can add tests for this cases too.

      3. "break" is a reserved word. It's not a good name for an attribute.

      4. It will be better test for exception an instance of the special class and not break TC.

      class Broken:
          def __getattr__(self, name):
              raise Exception('Broken __getattr__')
      
      brocken = Broken()
      test('brocken', '')
    3. terryjreedy commented on Jan 10, 2014

      @terryjreedy
      Member

      Get_entity already has try-except to block exceptions propagating from eval failure, so wrapping it is redundant. We only need worry about get_argspec.

      I presume the failure is in get_argspec in the remote process:
      if hasattr(ob, '__call__'):
      This can be replaced by callable(ob) as it converts exceptions to False. The appropriate return for non-callables is the current default, '', which results in no tip.

      There are, however, other attribute accesses that could fail. I am reluctant to wrap get_argspec in its entirety, as that would mask bugs in Idle code as well as in user snippets. So I think each access should be protected. Since users will expect a tip for something that is a callable, I think a message might be appropriate. I checked that getattr(ob, name, default) does not convert exception to default.

      Their are rpc calls in several places in Idle code. Unless failure can be triggered here in particular by user error, I do not think we should add specific protection here.

    4. python-dev commented on Jan 21, 2014

      python-devmannequin
      Mannequin

      New changeset d55d1cbf5f9a by Terry Jan Reedy in branch '2.7':
      Issue bpo-16630: Make Idle calltips work even when __getattr__ raises.
      http://hg.python.org/cpython/rev/d55d1cbf5f9a

      New changeset 2fe0b2dcc98c by Terry Jan Reedy in branch '3.3':
      Issue bpo-16630: Make Idle calltips work even when __getattr__ raises.
      http://hg.python.org/cpython/rev/2fe0b2dcc98c

    5. terryjreedy commented on Jan 21, 2014

      @terryjreedy
      Member

      I added test_attribute_exception with two subtests for each of two nasty classes. The resulting failures were fixed in CallTips.py by replacing all ob.__call__ references with one reference inside try_except that saved the method for possible later use.

    6. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions