# Buggy code
def dispatch_custom_completer(self, text):
    # io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
    line = self.line_buffer
    if not line.strip():
        return None

    # Create a little structure to pass all the relevant information about
    # the current completion to any custom completer.
    event = Bunch()
    event.line = line
    event.symbol = text
    cmd = line.split(None, 1)[0]
    event.command = cmd
    event.text_until_cursor = self.text_until_cursor

    # print "\ncustom:{%s]\n" % event # dbg

    # for foo etc, try also to find completer for %foo
    if not cmd.startswith(self.magic_escape):
        try_magic = self.custom_completers.s_matches(self.magic_escape + cmd)
    else:
        try_magic = []

    for c in itertools.chain(
        self.custom_completers.s_matches(cmd),
        try_magic,
        self.custom_completers.flat_matches(self.text_until_cursor),
    ):
        # print "try",c # dbg
        try:
            res = c(event)
            if res:
                # first, try case sensitive match
                withcase = [r for r in res if r.startswith(text)]
                if withcase:
                    return withcase
                # if none, then case insensitive ones are ok too
                text_low = text.lower()
                return [r for r in res if r.lower().startswith(text_low)]
        except TryNext:
            pass

    return None


# Traceback (TypeError)
Python 2.7.11+ (default, Mar 30 2016, 21:00:42)
Type "copyright", "credits" or "license" for more information.

IPython 5.0.0.dev -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: dException in thread Thread-7:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/prompt_toolkit/interface.py", line 742, in run
completions = list(buffer.completer.get_completions(document, complete_event))
File "/home/bwillar0/projects/python/ipython/IPython/terminal/ptshell.py", line 55, in gets
m = unicodedata.normalize('NFC', m)
TypeError: normalize() argument 2 must be unicode, not str

# Fixed code
def dispatch_custom_completer(self, text):
    line = self.line_buffer
    if not line.strip():
        return None

    # Create a little structure to pass all the relevant information about
    # the current completion to any custom completer.
    event = Bunch()
    event.line = line
    event.symbol = text
    cmd = line.split(None, 1)[0]
    event.command = cmd
    event.text_until_cursor = self.text_until_cursor

    # print "\ncustom:{%s]\n" % event # dbg

    # for foo etc, try also to find completer for %foo
    if not cmd.startswith(self.magic_escape):
        try_magic = self.custom_completers.s_matches(self.magic_escape + cmd)
    else:
        try_magic = []

    for c in itertools.chain(
        self.custom_completers.s_matches(cmd),
        try_magic,
        self.custom_completers.flat_matches(self.text_until_cursor),
    ):
        try:
            res = c(event)
            if res:
                # first, try case sensitive match
                withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
                if withcase:
                    return withcase
                # if none, then case insensitive ones are ok too
                text_low = text.lower()
                return [
                    cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)
                ]
        except TryNext:
            pass

    return None