Repository: tornadoweb/tornado

Issue:
tornado 4.5 Breaks `jupyter notebook`
I am not 100% about the integrity of my python installation but after upgrading to Tornado 4.5 I get the following error:
```
λ evan [~] → jupyter notebook                              
Traceback (most recent call last):
  File "/usr/lib/python3.4/site-packages/traitlets/traitlets.py", line 528, in get
    value = obj._trait_values[self.name]
KeyError: 'log'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/jupyter-notebook", line 11, in <module>
    sys.exit(main())
  File "/usr/lib/python3.4/site-packages/jupyter_core/application.py", line 267, in launch_instance
    return super(JupyterApp, cls).launch_instance(argv=argv, **kwargs)
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 657, in launch_instance
    app.initialize(argv)
  File "<decorator-gen-7>", line 2, in initialize
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/usr/lib/python3.4/site-packages/notebook/notebookapp.py", line 1290, in initialize
    super(NotebookApp, self).initialize(argv)
  File "<decorator-gen-6>", line 2, in initialize
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/usr/lib/python3.4/site-packages/jupyter_core/application.py", line 239, in initialize
    self.parse_command_line(argv)
  File "/usr/lib/python3.4/site-packages/notebook/notebookapp.py", line 1007, in parse_command_line
    super(NotebookApp, self).parse_command_line(argv)
  File "<decorator-gen-4>", line 2, in parse_command_line
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 536, in parse_command_line
    flags=flags, log=self.log)
  File "/usr/lib/python3.4/site-packages/traitlets/traitlets.py", line 556, in __get__
    return self.get(obj, cls)
  File "/usr/lib/python3.4/site-packages/traitlets/traitlets.py", line 535, in get
    value = self._validate(obj, dynamic_default())
  File "/usr/lib/python3.4/site-packages/traitlets/config/application.py", line 226, in _log_default
    _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)
  File "/usr/lib64/python3.4/site-packages/tornado/log.py", line 154, in __init__
    raise RuntimeError("No supported color terminal library")
RuntimeError: No supported color terminal library
```
After downgrading to `4.4.3` like so:
```
λ evan [~] → sudo pip3 install --ignore-installed tornado==4.4.3 
```
Jupyter runs just fine.

This SO answer suggested the downgrade: http://stackoverflow.com/a/43444780/2661491

**Specifics:**
openSuse 42.2
Python 3.4.5
Jupyter 4.3.0


Discussion:
Duplicate of #2013. Fix is being developed in #2014.
Wait, this is happening on linux? Interesting. Is there something wrong with the `curses` package in your installation of python?
@bdarnell How would I go about checking? Like I said I am not 100% sure if my Python 3.4.5 install is up to snuff, I just got done messing around with some issues building 3.4.6 (w/ altinstall).
Does it work if you `import curses` at a python prompt? Or maybe jupyter is doing something funny with stderr that's breaking tornado/log.py?
Huh, turns out `curses` was not installed/was not installed correctly. `jupyter` now works with both `tornado 4.4.3` and `tornado 4.5`.

I guess downgrading just happened to work out for me.

Thanks for the help!

Resolving patch:
diff --git a/tornado/log.py b/tornado/log.py
--- a/tornado/log.py
+++ b/tornado/log.py
@@ -54,18 +54,21 @@
 
 
 def _stderr_supports_color():
-    color = False
-    if hasattr(sys.stderr, 'isatty') and sys.stderr.isatty():
-        if curses:
-            try:
+    try:
+        if hasattr(sys.stderr, 'isatty') and sys.stderr.isatty():
+            if curses:
                 curses.setupterm()
                 if curses.tigetnum("colors") > 0:
-                    color = True
-            except Exception:
-                pass
-        elif colorama:
-            color = True
-    return color
+                    return True
+            elif colorama:
+                if sys.stderr is getattr(colorama.initialise, 'wrapped_stderr',
+                                         object()):
+                    return True
+    except Exception:
+        # Very broad exception handling because it's always better to
+        # fall back to non-colored logs than to break at startup.
+        pass
+    return False
 
 
 def _safe_unicode(s):
@@ -146,12 +149,12 @@ def __init__(self, fmt=DEFAULT_FORMAT, datefmt=DEFAULT_DATE_FORMAT,
                 for levelno, code in colors.items():
                     self._colors[levelno] = unicode_type(curses.tparm(fg_color, code), "ascii")
                 self._normal = unicode_type(curses.tigetstr("sgr0"), "ascii")
-            elif sys.stderr is getattr(colorama, 'wrapped_stderr', object()):
+            else:
+                # If curses is not present (currently we'll only get here for
+                # colorama on windows), assume hard-coded ANSI color codes.
                 for levelno, code in colors.items():
                     self._colors[levelno] = '\033[2;3%dm' % code
                 self._normal = '\033[0m'
-            else:
-                raise RuntimeError("No supported color terminal library")
         else:
             self._normal = ''
 


Test patch: