# Buggy code
def init():
    global cache

    if "PWNLIB_NOTERM" not in os.environ:
        # Fix for BPython
        try:
            curses.setupterm()
        except curses.error as e:
            import traceback

            print(
                "Warning:",
                "".join(traceback.format_exception_only(e.__class__, e)),
                file=sys.stderr,
            )

    cache = {}
    # Manually add reset sequence into the cache.
    # Can't look it up using tigetstr.
    cache["reset"] = "\x1b[m"


# Traceback (ImportError)
In 1: from pwn import *
Out 1:
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-1-d810d1e70089> in <module>()
----> 1 from pwn import *

/usr/local/lib/python2.7/dist-packages/pwn/__init__.py in <module>()
1 # Promote useful stuff to toplevel
----> 2 from .toplevel import *
3
4 pwnlib.args.initialize()
5 pwnlib.log.install_default_handler()

/usr/local/lib/python2.7/dist-packages/pwn/toplevel.py in <module>()
18 from pprint import pprint
19
---> 20 import pwnlib
21 from pwnlib import *
22 from pwnlib.asm import *

/usr/local/lib/python2.7/dist-packages/pwnlib/__init__.py in <module>()
38
39 for module in __all__:
---> 40     importlib.import_module('.%s' % module, 'pwnlib')

/usr/lib/python2.7/importlib/__init__.pyc in import_module(name, package)
35             level += 1
36         name = _resolve_name(name[level:], package, level)
---> 37     __import__(name)
38     return sys.modules[name]

/usr/local/lib/python2.7/dist-packages/pwnlib/args.py in <module>()
46 import sys
47
---> 48 from . import term
49 from .context import context
50

/usr/local/lib/python2.7/dist-packages/pwnlib/term/__init__.py in <module>()
1 import sys
2
----> 3 from . import completer
4 from . import key
5 from . import keymap

/usr/local/lib/python2.7/dist-packages/pwnlib/term/completer.py in <module>()
2 import re
3
----> 4 from . import readline
5
6

/usr/local/lib/python2.7/dist-packages/pwnlib/term/readline.py in <module>()
2 from . import keymap as km
3 from . import term
----> 4 from . import text
5
6 cursor = text.reverse

/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.pyc in <module>()
113
114 tether = sys.modules[__name__]
--> 115 sys.modules[__name__] = Module()

/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.pyc in __init__(self)
24         self.__file__ = __file__
25         self.__name__ = __name__
---> 26         self.num_colors = termcap.get('colors', default = 8)
27         self.has_bright = self.num_colors >= 16
28         self.has_gray = self.has_bright

/usr/local/lib/python2.7/dist-packages/pwnlib/term/termcap.pyc in get(cap, *args, **kwargs)
23     s = cache.get(cap)
24     if not s:
---> 25         s = curses.tigetstr(cap)
26         if s == None:
27             s = curses.tigetnum(cap)

error: must call (at least) setupterm() first

​

In 2: import curses

In 3: curses.setupterm()
Out 2:
---------------------------------------------------------------------------
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-5-82805162dd9f> in <module>()
----> 1 curses.setupterm()

/usr/local/lib/python2.7/dist-packages/ipykernel/iostream.pyc in fileno(self)
304
305     def fileno(self):
--> 306         raise UnsupportedOperation("IOStream has no fileno.")
307
308     def write(self, string):

UnsupportedOperation: IOStream has no fileno.

print (curses.initscr(), curses.endwin())

(<_curses.curses window object at 0x7fef5c891a98>, None)

In 4: from pwnlib import *

Out 3:
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-2-5eb1d9485f4c> in <module>()
----> 1 from pwnlib import *

/usr/local/lib/python2.7/dist-packages/pwnlib/__init__.py in <module>()
38
39 for module in __all__:
---> 40     importlib.import_module('.%s' % module, 'pwnlib')

/usr/lib/python2.7/importlib/__init__.pyc in import_module(name, package)
35             level += 1
36         name = _resolve_name(name[level:], package, level)
---> 37     __import__(name)
38     return sys.modules[name]

/usr/local/lib/python2.7/dist-packages/pwnlib/args.py in <module>()
46 import sys
47
---> 48 from . import term
49 from .context import context
50

/usr/local/lib/python2.7/dist-packages/pwnlib/term/__init__.py in <module>()
1 import sys
2
----> 3 from . import completer
4 from . import key
5 from . import keymap

/usr/local/lib/python2.7/dist-packages/pwnlib/term/completer.py in <module>()
2 import re
3
----> 4 from . import readline
5
6

/usr/local/lib/python2.7/dist-packages/pwnlib/term/readline.py in <module>()
----> 1 from . import keyconsts as kc
2 from . import keymap as km
3 from . import term
4 from . import text
5

ImportError: cannot import name keyconsts

​```

# Fixed code
def init():
    global cache

    # Detect running under Jupyter
    try:
        if get_ipython().__class__.__name__ == "ZMQInteractiveShell":
            os.environ["PWNLIB_NOTERM"] = "1"
            os.environ["JUPYTER_DETECTED"] = "yes"
    except NameError:
        pass

    if "PWNLIB_NOTERM" not in os.environ:
        # Fix for BPython
        try:
            curses.setupterm()
        except curses.error as e:
            import traceback

            print(
                "Warning:",
                "".join(traceback.format_exception_only(e.__class__, e)),
                file=sys.stderr,
            )

    cache = {}
    # Manually add reset sequence into the cache.
    # Can't look it up using tigetstr.
    cache["reset"] = "\x1b[m"