Repository: jupyterhub/jupyterhub

Issue:
Single user server launch is broken
I think that #261 broke the launching of the single user server. I am seeing the following errors in the nbgrader tests:

```
Traceback (most recent call last):
  File "/Users/jhamrick/.virtualenvs/nbgrader/bin/jupyterhub-singleuser", line 6, in <module>
    exec(compile(open(__file__).read(), __file__, 'exec'))
  File "/Users/jhamrick/project/tools/jupyterhub/scripts/jupyterhub-singleuser", line 4, in <module>
    main()
  File "/Users/jhamrick/project/tools/jupyterhub/jupyterhub/singleuser.py", line 221, in main
    return SingleUserNotebookApp.launch_instance()
  File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/config/application.py", line 573, in launch_instance
    app.initialize(argv)
  File "<string>", line 2, in initialize
  File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/config/application.py", line 75, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/html/notebookapp.py", line 1015, in initialize
    self.init_webapp()
  File "/Users/jhamrick/project/tools/jupyterhub/jupyterhub/singleuser.py", line 191, in init_webapp
    s['user'] = self.user
  File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/traitlets/traitlets.py", line 438, in __get__
    % (self.name, obj))
traitlets.traitlets.TraitError: No default value found for None trait of <jupyterhub.singleuser.SingleUserNotebookApp object at 0x102953b00>
```

If I revert to the version of jupyterhub prior to that PR, this error does not occur. @epifanio reported on gitter seeing the same thing as well, so I don't think it's isolated to nbgrader.

Given the error message, I suspect this has to do with ipython/traitlets#39 and/or ipython/traitlets#40 though I haven't actually tested it. I tried giving the `user` trait a default value but it did not seem to fix the error. I will try to do a bit more debugging, but I fear I don't really understand the internals of traitlets well enough to know exactly what's going on here.

Ping @takluyver and @minrk ?



Discussion:
Min's on his way to the UK, I'll try to look at this in the morning. It
certainly looks like something my traitlets changes could have broken;
sorry about that.
On 23 Jun 2015 10:15 pm, "Jessica B. Hamrick" notifications@github.com
wrote:

> I think that #261 https://github.com/jupyter/jupyterhub/pull/261 broke
> the launching of the single user server. I am seeing the following errors
> in the nbgrader tests:
> 
> Traceback (most recent call last):
>   File "/Users/jhamrick/.virtualenvs/nbgrader/bin/jupyterhub-singleuser", line 6, in <module>
>     exec(compile(open(**file**).read(), **file**, 'exec'))
>   File "/Users/jhamrick/project/tools/jupyterhub/scripts/jupyterhub-singleuser", line 4, in <module>
>     main()
>   File "/Users/jhamrick/project/tools/jupyterhub/jupyterhub/singleuser.py", line 221, in main
>     return SingleUserNotebookApp.launch_instance()
>   File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/config/application.py", line 573, in launch_instance
>     app.initialize(argv)
>   File "<string>", line 2, in initialize
>   File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/config/application.py", line 75, in catch_config_error
>     return method(app, _args, *_kwargs)
>   File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/IPython/html/notebookapp.py", line 1015, in initialize
>     self.init_webapp()
>   File "/Users/jhamrick/project/tools/jupyterhub/jupyterhub/singleuser.py", line 191, in init_webapp
>     s['user'] = self.user
>   File "/Users/jhamrick/.virtualenvs/nbgrader/lib/python3.4/site-packages/traitlets/traitlets.py", line 438, in **get**
>     % (self.name, obj))
> traitlets.traitlets.TraitError: No default value found for None trait of <jupyterhub.singleuser.SingleUserNotebookApp object at 0x102953b00>
> 
> If I revert to the version of jupyterhub prior to that PR, this error does
> not occur. @epifanio https://github.com/epifanio reported on gitter
> seeing the same thing as well, so I don't think it's isolated to nbgrader.
> 
> Given the error message, I suspect this has to do with
> ipython/traitlets#39 https://github.com/ipython/traitlets/pull/39
> and/or ipython/traitlets#40 https://github.com/ipython/traitlets/pull/40
> though I haven't actually tested it. I tried giving the user trait a
> default value but it did not seem to fix the error. I will try to do a bit
> more debugging, but I fear I don't really understand the internals of
> traitlets well enough to know exactly what's going on here.
> 
> Ping @takluyver https://github.com/takluyver and @minrk
> https://github.com/minrk ?
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/jupyter/jupyterhub/issues/262.

Ok, thanks. Not a huge rush for me -- it's not a crucial part of nbgrader and I've marked my failing tests as xfail for now -- but it does seem like it's causing trouble for other people using jupyterhub.

I'm getting the same error trying to login to a local server

I am getting the following error message on a fresh installation:

```
[I 2015-06-24 11:39:48.334 JupyterHub app:1020] JupyterHub is now running at http://192.168.178.54:8000/
[I 2015-06-24 11:40:11.808 JupyterHub spawner:359] Spawning jupyterhub-singleuser --user=jhub --port=60429 --cookie-name=jupyter-hub-token-jhub --base-url=/user/jhub --hub-prefix=/hub/ --hub-api-url=http://localhost:8081/hub/api --ip=localhost '--notebook-dir=~/notebook/'
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 432, in __get__
    value = obj._trait_values[self.name]
KeyError: None

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/jupyterhub-singleuser", line 4, in <module>
    main()
  File "/usr/local/lib/python3.4/dist-packages/jupyterhub/singleuser.py", line 221, in main
    return SingleUserNotebookApp.launch_instance()
  File "/usr/local/lib/python3.4/dist-packages/IPython/config/application.py", line 573, in launch_instance
    app.initialize(argv)
  File "<string>", line 2, in initialize
  File "/usr/local/lib/python3.4/dist-packages/IPython/config/application.py", line 75, in catch_config_error
    return method(app, *args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/IPython/html/notebookapp.py", line 1015, in initialize
    self.init_webapp()
  File "/usr/local/lib/python3.4/dist-packages/jupyterhub/singleuser.py", line 191, in init_webapp
    s['user'] = self.user
  File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 438, in __get__
    % (self.name, obj))
traitlets.traitlets.TraitError: No default value found for None trait of <jupyterhub.singleuser.SingleUserNotebookApp object at 0xb72c302c>

If you suspect this is an IPython bug, please report it at:
    https://github.com/ipython/ipython/issues
or send an email to the mailing list at ipython-dev@scipy.org

You can print a more detailed traceback right now with "%tb", or use "%debug"
to interactively debug it.

Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
    c.Application.verbose_crash=True

11:40:14.820 - error: [ConfigProxy] Proxy error:  code=ECONNRESET
[I 2015-06-24 11:40:14.830 JupyterHub log:100] 302 GET / (@192.168.178.39) 4.76ms
[I 2015-06-24 11:40:14.836 JupyterHub log:100] 302 GET /hub (@192.168.178.39) 0.92ms
[I 2015-06-24 11:40:14.849 JupyterHub log:100] 302 GET /hub/ (jhub@192.168.178.39) 3.92ms
[I 2015-06-24 11:40:14.856 JupyterHub log:100] 302 GET /user/jhub (@192.168.178.39) 1.07ms
[I 2015-06-24 11:40:14.888 JupyterHub log:100] 200 GET /hub/user/jhub (jhub@192.168.178.39) 23.65ms
[W 2015-06-24 11:40:21.821 JupyterHub base:264] User jhub server is slow to start
[I 2015-06-24 11:40:21.831 JupyterHub log:100] 302 GET /hub/user/jhub (jhub@192.168.178.39) 10040.55ms
^C
Interrupted
[I 2015-06-24 11:40:23.357 JupyterHub app:889] Cleaning up single-user servers...
[I 2015-06-24 11:40:23.361 JupyterHub app:900] Cleaning up proxy[13700]...
[I 2015-06-24 11:40:23.361 JupyterHub app:926] ...done
```

Is this connected to this issue?

It appears the issue comes from the `BaseDescriptor` class defaulting `name` to `None` and the `KeyError` exception not acoccunting for a `None`. I'll see if I can generate a pull request on the traitlets project covering it

Yeah, it seemed to me like it had to do with `name` not ever being set -- but I should think that it would be set in this case, because based on my understanding of traitlets, `name` should always be set if the trait is an attribute of an object that inherits from `HasTraits`. But I don't know why it's not being set, then, because `SingleUserNotebookApp` does inherit from `HasTraits` -- and when I looked at the traitlets source, I couldn't actually find any instances of `name` being set anywhere. I think there is probably some fancy metaclass magic going on somewhere that sets it, but at least at 2am last night I was unable to track it down :-)

I thought it might be that the `KeyError` handler has no check for the `allow_none` property which should disallow `None` by default. I could be totally wrong, this traitlets rabbit hole appears to be deeper than first glance.

no luck so far, need sleep. Might continue to chase this down tomorrow if there is no progress. 


Resolving patch:
diff --git a/jupyterhub/singleuser.py b/jupyterhub/singleuser.py
--- a/jupyterhub/singleuser.py
+++ b/jupyterhub/singleuser.py
@@ -17,7 +17,7 @@
 from tornado import ioloop
 from tornado.web import HTTPError
 
-from traitlets import (
+from IPython.utils.traitlets import (
     Integer,
     Unicode,
     CUnicode,


Test patch:
diff --git a/jupyterhub/tests/test_spawner.py b/jupyterhub/tests/test_spawner.py
--- a/jupyterhub/tests/test_spawner.py
+++ b/jupyterhub/tests/test_spawner.py
@@ -56,6 +56,30 @@ def test_spawner(db, io_loop):
     status = io_loop.run_sync(spawner.poll)
     assert status == 1
 
+def test_single_user_spawner(db, io_loop):
+    spawner = new_spawner(db, cmd=[sys.executable, '-m', 'jupyterhub.singleuser'])
+    io_loop.run_sync(spawner.start)
+    assert spawner.user.server.ip == 'localhost'
+    # wait for http server to come up,
+    # checking for early termination every 1s
+    def wait():
+        return spawner.user.server.wait_up(timeout=1, http=True)
+    for i in range(30):
+        status = io_loop.run_sync(spawner.poll)
+        assert status is None
+        try:
+            io_loop.run_sync(wait)
+        except TimeoutError:
+            continue
+        else:
+            break
+    io_loop.run_sync(wait)
+    status = io_loop.run_sync(spawner.poll)
+    assert status == None
+    io_loop.run_sync(spawner.stop)
+    status = io_loop.run_sync(spawner.poll)
+    assert status == 0
+
 
 def test_stop_spawner_sigint_fails(db, io_loop):
     spawner = new_spawner(db, cmd=[sys.executable, '-c', _uninterruptible])