# Buggy code
def get_tokens(cli):
    result = []
    append = result.append
    Signature = Token.Toolbar.Signature

    if python_input.signatures:
        sig = python_input.signatures[0]  # Always take the first one.

        append((Signature, " "))
        try:
            append((Signature, sig.full_name))
        except IndexError:
            # Workaround for #37: https://github.com/jonathanslenders/python-prompt-toolkit/issues/37
            # See also: https://github.com/davidhalter/jedi/issues/490
            return []

        append((Signature.Operator, "("))

        for i, p in enumerate(sig.params):
            # Workaround for #47: 'p' is None when we hit the '*' in the signature.
            #                     and sig has no 'index' attribute.
            # See: https://github.com/jonathanslenders/ptpython/issues/47
            #      https://github.com/davidhalter/jedi/issues/598
            description = p.description if p else "*"  # or '*'
            sig_index = getattr(sig, "index", 0)

            if i == sig_index:
                # Note: we use `_Param.description` instead of
                #       `_Param.name`, that way we also get the '*' before args.
                append((Signature.CurrentName, str(description)))
            else:
                append((Signature, str(description)))
            append((Signature.Operator, ", "))

        if sig.params:
            # Pop last comma
            result.pop()

        append((Signature.Operator, ")"))
        append((Signature, " "))
    return result


# Traceback (KeyError)
from lxml.html import builder as E

E.HTML(
Traceback (most recent call last):
File "/usr/lib/python3.5/site-packages/prompt_toolkit/cache.py", line 32, in get
return self._data[key]
KeyError: 51

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/bin/ptpython", line 9, in <module>
load_entry_point('ptpython==0.35', 'console_scripts', 'ptpython')()
File "/usr/lib/python3.5/site-packages/ptpython/entry_points/run_ptpython.py", line 71, in run
title='Python REPL (ptpython)')
File "/usr/lib/python3.5/site-packages/ptpython/repl.py", line 315, in embed
cli.run()
File "/usr/lib/python3.5/site-packages/prompt_toolkit/interface.py", line 389, in run
self.eventloop.run(self.input, self.create_eventloop_callbacks())
File "/usr/lib/python3.5/site-packages/prompt_toolkit/eventloop/posix.py", line 154, in run
t()
File "/usr/lib/python3.5/site-packages/prompt_toolkit/interface.py", line 326, in redraw
self._redraw()
File "/usr/lib/python3.5/site-packages/prompt_toolkit/interface.py", line 346, in _redraw
self.renderer.render(self, self.layout, is_done=self.is_done)
File "/usr/lib/python3.5/site-packages/prompt_toolkit/renderer.py", line 429, in render
extended_height=size.rows,
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 157, in write_to_screen
c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, width, s))
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 348, in write_to_screen
c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, s, height))
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 157, in write_to_screen
c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, width, s))
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 428, in write_to_screen
width = fl.content.preferred_width(cli, write_position.width).preferred
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 1644, in preferred_width
return self.content.preferred_width(cli, max_available_width)
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/containers.py", line 980, in preferred_width
cli, max_available_width - total_margin_width)
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/controls.py", line 249, in preferred_width
text = token_list_to_text(self._get_tokens_cached(cli))
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/controls.py", line 239, in _get_tokens_cached
cli.render_counter, lambda: self.get_tokens(cli))
File "/usr/lib/python3.5/site-packages/prompt_toolkit/cache.py", line 35, in get
value = getter_func()
File "/usr/lib/python3.5/site-packages/prompt_toolkit/layout/controls.py", line 239, in <lambda>
cli.render_counter, lambda: self.get_tokens(cli))
File "/usr/lib/python3.5/site-packages/ptpython/layout.py", line 211, in get_tokens
for i, p in enumerate(sig.params):
File "/usr/lib/python3.5/site-packages/jedi/evaluate/cache.py", line 41, in wrapper
rv = function(obj, *args, **kwargs)
File "/usr/lib/python3.5/site-packages/jedi/api/classes.py", line 348, in params
sub = followed.get_subscope_by_name('__init__')
File "/usr/lib/python3.5/site-packages/jedi/evaluate/representation.py", line 563, in __getattr__
return getattr(self.base_func, name)
AttributeError: 'Lambda' object has no attribute 'get_subscope_by_name'

# Fixed code
def get_tokens(cli):
    result = []
    append = result.append
    Signature = Token.Toolbar.Signature

    if python_input.signatures:
        sig = python_input.signatures[0]  # Always take the first one.

        append((Signature, " "))
        try:
            append((Signature, sig.full_name))
        except IndexError:
            # Workaround for #37: https://github.com/jonathanslenders/python-prompt-toolkit/issues/37
            # See also: https://github.com/davidhalter/jedi/issues/490
            return []

        append((Signature.Operator, "("))

        try:
            enumerated_params = enumerate(sig.params)
        except AttributeError:
            # Workaround for #136: https://github.com/jonathanslenders/ptpython/issues/136
            # AttributeError: 'Lambda' object has no attribute 'get_subscope_by_name'
            return []

        for i, p in enumerated_params:
            # Workaround for #47: 'p' is None when we hit the '*' in the signature.
            #                     and sig has no 'index' attribute.
            # See: https://github.com/jonathanslenders/ptpython/issues/47
            #      https://github.com/davidhalter/jedi/issues/598
            description = p.description if p else "*"  # or '*'
            sig_index = getattr(sig, "index", 0)

            if i == sig_index:
                # Note: we use `_Param.description` instead of
                #       `_Param.name`, that way we also get the '*' before args.
                append((Signature.CurrentName, str(description)))
            else:
                append((Signature, str(description)))
            append((Signature.Operator, ", "))

        if sig.params:
            # Pop last comma
            result.pop()

        append((Signature.Operator, ")"))
        append((Signature, " "))
    return result