prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Fatal error when $TERM is not set
  I am trying to use `pwntools` in a SageMath script. This works great interactively, but when I run my script with `sage foo.sage`, it fails somewhere in terminal code. I have traced this back to sage unsetting $TERM in non-interactive calls due to https://trac.sagemath.org/ticket/12263. Thus, issue can be easily reproduced without SageMath:
  
  ```sh
  ~$ docker run -it pwntools/pwntools:stable
  pwntools@bce19e99e965:~$ TERM= python -c 'import pwn'
  Warning: error: setupterm: could not find terminfo database
  
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/usr/local/lib/python2.7/dist-packages/pwn/__init__.py", line 4, in <module>
      from pwn.toplevel import *
    File "/usr/local/lib/python2.7/dist-packages/pwn/toplevel.py", line 20, in <module>
      import pwnlib
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/__init__.py", line 43, in <module>
      importlib.import_module('.%s' % module, 'pwnlib')
    File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
      __import__(name)
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/args.py", line 62, in <module>
      from pwnlib import term
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/__init__.py", line 6, in <module>
      from pwnlib.term import completer
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/completer.py", line 7, in <module>
      from pwnlib.term import readline
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/readline.py", line 13, in <module>
      from pwnlib.term import text
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.py", line 126, in <module>
      sys.modules[__name__] = Module()
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.py", line 49, in __init__
      s = termcap.get(y)
    File "/usr/local/lib/python2.7/dist-packages/pwnlib/term/unix_termcap.py", line 28, in get
      s = curses.tigetstr(cap)
  _curses.error: must call (at least) setupterm() first
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pwnlib/term/unix_termcap.py`
  Content:
  ```
  1 from __future__ import division
  2 from __future__ import print_function
  3 
  4 __all__ = ['get']
  5 import curses
  6 import os
  7 import sys
  8 
  9 cache = None
  10 
  11 def get(cap, *args, **kwargs):
  12     default = kwargs.pop('default', '')
  13 
  14     if 'PWNLIB_NOTERM' in os.environ:
  15         return ''
  16 
  17     # Hack for readthedocs.org
  18     if 'READTHEDOCS' in os.environ:
  19         return ''
  20 
  21     if kwargs != {}:
  22         raise TypeError("get(): No such argument %r" % kwargs.popitem()[0])
  23 
  24     if cache is None:
  25         init()
  26     s = cache.get(cap)
  27     if not s:
  28         s = curses.tigetstr(cap)
  29         if s is None:
  30             s = curses.tigetnum(cap)
  31             if s == -2:
  32                 s = curses.tigetflag(cap)
  33                 if s == -1:
  34                     # default to empty string so tparm doesn't fail
  35                     s = ''
  36                 else:
  37                     s = bool(s)
  38         cache[cap] = s
  39     # if `s' is not set `curses.tparm' will throw an error if given arguments
  40     if args and s:
  41         return curses.tparm(s, *args)
  42     else:
  43         return s
  44 
  45 def init():
  46     global cache
  47 
  48     # Detect running under Jupyter
  49     try:
  50         if get_ipython().__class__.__name__ == 'ZMQInteractiveShell':
  51             os.environ['PWNLIB_NOTERM'] = '1'
  52             os.environ['JUPYTER_DETECTED'] ='yes'
  53     except NameError:
  54         pass
  55 
  56     if 'PWNLIB_NOTERM' not in os.environ:
  57         # Fix for BPython
  58         try:
  59             curses.setupterm()
  60         except curses.error as e:
  61             import traceback
  62             print('Warning:', ''.join(traceback.format_exception_only(e.__class__, e)), file=sys.stderr)
  63 
  64     cache = {}
  65     # Manually add reset sequence into the cache.
  66     # Can't look it up using tigetstr.
  67     cache['reset'] = '\x1b[m'
  68
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/pwnlib/term/unix_termcap.py b/pwnlib/term/unix_termcap.py
  --- a/pwnlib/term/unix_termcap.py
  +++ b/pwnlib/term/unix_termcap.py
  @@ -60,6 +60,8 @@
           except curses.error as e:
               import traceback
               print('Warning:', ''.join(traceback.format_exception_only(e.__class__, e)), file=sys.stderr)
  +            print('Terminal features will not be available.  Consider setting TERM variable to your current terminal name (or xterm).', file=sys.stderr)
  +            os.environ['PWNLIB_NOTERM'] = '1'
   
       cache = {}
       # Manually add reset sequence into the cache.
  
verification_info: {"golden_diff": "diff --git a/pwnlib/term/unix_termcap.py b/pwnlib/term/unix_termcap.py\n--- a/pwnlib/term/unix_termcap.py\n+++ b/pwnlib/term/unix_termcap.py\n@@ -60,6 +60,8 @@\n         except curses.error as e:\n             import traceback\n             print('Warning:', ''.join(traceback.format_exception_only(e.__class__, e)), file=sys.stderr)\n+            print('Terminal features will not be available.  Consider setting TERM variable to your current terminal name (or xterm).', file=sys.stderr)\n+            os.environ['PWNLIB_NOTERM'] = '1'\n \n     cache = {}\n     # Manually add reset sequence into the cache.\n", "issue": "Fatal error when $TERM is not set\nI am trying to use `pwntools` in a SageMath script. This works great interactively, but when I run my script with `sage foo.sage`, it fails somewhere in terminal code. I have traced this back to sage unsetting $TERM in non-interactive calls due to https://trac.sagemath.org/ticket/12263. Thus, issue can be easily reproduced without SageMath:\r\n\r\n```sh\r\n~$ docker run -it pwntools/pwntools:stable\r\npwntools@bce19e99e965:~$ TERM= python -c 'import pwn'\r\nWarning: error: setupterm: could not find terminfo database\r\n\r\nTraceback (most recent call last):\r\n  File \"<string>\", line 1, in <module>\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwn/__init__.py\", line 4, in <module>\r\n    from pwn.toplevel import *\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwn/toplevel.py\", line 20, in <module>\r\n    import pwnlib\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/__init__.py\", line 43, in <module>\r\n    importlib.import_module('.%s' % module, 'pwnlib')\r\n  File \"/usr/lib/python2.7/importlib/__init__.py\", line 37, in import_module\r\n    __import__(name)\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/args.py\", line 62, in <module>\r\n    from pwnlib import term\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/__init__.py\", line 6, in <module>\r\n    from pwnlib.term import completer\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/completer.py\", line 7, in <module>\r\n    from pwnlib.term import readline\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/readline.py\", line 13, in <module>\r\n    from pwnlib.term import text\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.py\", line 126, in <module>\r\n    sys.modules[__name__] = Module()\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/text.py\", line 49, in __init__\r\n    s = termcap.get(y)\r\n  File \"/usr/local/lib/python2.7/dist-packages/pwnlib/term/unix_termcap.py\", line 28, in get\r\n    s = curses.tigetstr(cap)\r\n_curses.error: must call (at least) setupterm() first\r\n```\n", "before_files": [{"content": "from __future__ import division\nfrom __future__ import print_function\n\n__all__ = ['get']\nimport curses\nimport os\nimport sys\n\ncache = None\n\ndef get(cap, *args, **kwargs):\n    default = kwargs.pop('default', '')\n\n    if 'PWNLIB_NOTERM' in os.environ:\n        return ''\n\n    # Hack for readthedocs.org\n    if 'READTHEDOCS' in os.environ:\n        return ''\n\n    if kwargs != {}:\n        raise TypeError(\"get(): No such argument %r\" % kwargs.popitem()[0])\n\n    if cache is None:\n        init()\n    s = cache.get(cap)\n    if not s:\n        s = curses.tigetstr(cap)\n        if s is None:\n            s = curses.tigetnum(cap)\n            if s == -2:\n                s = curses.tigetflag(cap)\n                if s == -1:\n                    # default to empty string so tparm doesn't fail\n                    s = ''\n                else:\n                    s = bool(s)\n        cache[cap] = s\n    # if `s' is not set `curses.tparm' will throw an error if given arguments\n    if args and s:\n        return curses.tparm(s, *args)\n    else:\n        return s\n\ndef init():\n    global cache\n\n    # Detect running under Jupyter\n    try:\n        if get_ipython().__class__.__name__ == 'ZMQInteractiveShell':\n            os.environ['PWNLIB_NOTERM'] = '1'\n            os.environ['JUPYTER_DETECTED'] ='yes'\n    except NameError:\n        pass\n\n    if 'PWNLIB_NOTERM' not in os.environ:\n        # Fix for BPython\n        try:\n            curses.setupterm()\n        except curses.error as e:\n            import traceback\n            print('Warning:', ''.join(traceback.format_exception_only(e.__class__, e)), file=sys.stderr)\n\n    cache = {}\n    # Manually add reset sequence into the cache.\n    # Can't look it up using tigetstr.\n    cache['reset'] = '\\x1b[m'\n", "path": "pwnlib/term/unix_termcap.py"}], "after_files": [{"content": "from __future__ import division\nfrom __future__ import print_function\n\n__all__ = ['get']\nimport curses\nimport os\nimport sys\n\ncache = None\n\ndef get(cap, *args, **kwargs):\n    default = kwargs.pop('default', '')\n\n    if 'PWNLIB_NOTERM' in os.environ:\n        return ''\n\n    # Hack for readthedocs.org\n    if 'READTHEDOCS' in os.environ:\n        return ''\n\n    if kwargs != {}:\n        raise TypeError(\"get(): No such argument %r\" % kwargs.popitem()[0])\n\n    if cache is None:\n        init()\n    s = cache.get(cap)\n    if not s:\n        s = curses.tigetstr(cap)\n        if s is None:\n            s = curses.tigetnum(cap)\n            if s == -2:\n                s = curses.tigetflag(cap)\n                if s == -1:\n                    # default to empty string so tparm doesn't fail\n                    s = ''\n                else:\n                    s = bool(s)\n        cache[cap] = s\n    # if `s' is not set `curses.tparm' will throw an error if given arguments\n    if args and s:\n        return curses.tparm(s, *args)\n    else:\n        return s\n\ndef init():\n    global cache\n\n    # Detect running under Jupyter\n    try:\n        if get_ipython().__class__.__name__ == 'ZMQInteractiveShell':\n            os.environ['PWNLIB_NOTERM'] = '1'\n            os.environ['JUPYTER_DETECTED'] ='yes'\n    except NameError:\n        pass\n\n    if 'PWNLIB_NOTERM' not in os.environ:\n        # Fix for BPython\n        try:\n            curses.setupterm()\n        except curses.error as e:\n            import traceback\n            print('Warning:', ''.join(traceback.format_exception_only(e.__class__, e)), file=sys.stderr)\n            print('Terminal features will not be available.  Consider setting TERM variable to your current terminal name (or xterm).', file=sys.stderr)\n            os.environ['PWNLIB_NOTERM'] = '1'\n\n    cache = {}\n    # Manually add reset sequence into the cache.\n    # Can't look it up using tigetstr.\n    cache['reset'] = '\\x1b[m'\n", "path": "pwnlib/term/unix_termcap.py"}]}