Repository: ipython/ipython

Issue:
NotebookApp.webapp_settings static_url_prefix causes crash
on master:

```
{'codename': 'An Afternoon Hack',
 'commit_hash': 'db5ce0e',
 'commit_source': 'repository',
 'default_encoding': 'UTF-8',
 'ipython_path': '/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython',
 'ipython_version': '2.0.0-dev',
 'os_name': 'posix',
 'platform': 'Darwin-12.3.0-x86_64-i386-64bit',
 'sys_executable': '/Users/karissamckelvey/anaconda/bin/python',
 'sys_platform': 'darwin',
 'sys_version': '2.7.5 |Anaconda 1.7.0 (x86_64)| (default, Jun 28 2013, 22:20:13) \n[GCC 4.0.1 (Apple Inc. build 5493)]'}
```
1. Run `$ ipython notebook --NotebookApp.webapp_settings="{'static_url_prefix':'/static/'}"`
2. Open up a new notebook 
3. Can't enter commands into the shell. Get the following stack trace:

`````` bash
2013-10-02 17:44:11.462 [NotebookApp] Using existing profile dir: u'/Users/karissamckelvey/.ipython/profile_default'
2013-10-02 17:44:11.559 [NotebookApp] Using MathJax from CDN: http://cdn.mathjax.org/mathjax/latest/MathJax.js
2013-10-02 17:44:11.575 [NotebookApp] The port 8888 is already in use, trying another random port.
2013-10-02 17:44:11.575 [NotebookApp] Serving notebooks from local directory: /Users/karissamckelvey
2013-10-02 17:44:11.575 [NotebookApp] The IPython Notebook is running at: http://127.0.0.1:8889/
2013-10-02 17:44:11.575 [NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
2013-10-02 17:44:15.198 [tornado.application] ERROR | Uncaught exception POST /kernels?notebook=03fb94ab-98f3-4c18-808b-298ffc79a01a (127.0.0.1)
HTTPRequest(protocol='http', host='127.0.0.1:8889', method='POST', uri='/kernels?notebook=03fb94ab-98f3-4c18-808b-298ffc79a01a', version='HTTP/1.1', remote_ip='127.0.0.1', headers={'Origin': 'http://127.0.0.1:8889', 'Content-Length': '0', 'Accept-Language': 'en-us', 'Accept-Encoding': 'gzip, deflate', 'Host': '127.0.0.1:8889', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.28.10 (KHTML, like Gecko) Version/6.0.3 Safari/536.28.10', 'Connection': 'keep-alive', 'X-Requested-With': 'XMLHttpRequest', 'Referer': 'http://127.0.0.1:8889/03fb94ab-98f3-4c18-808b-298ffc79a01a'})
Traceback (most recent call last):
  File "/Users/karissamckelvey/anaconda/python.app/Contents/lib/python2.7/site-packages/tornado/web.py", line 1141, in _when_complete
    callback()
  File "/Users/karissamckelvey/anaconda/python.app/Contents/lib/python2.7/site-packages/tornado/web.py", line 1162, in _execute_method
    self._when_complete(method(*self.path_args, **self.path_kwargs),
  File "/Users/karissamckelvey/anaconda/python.app/Contents/lib/python2.7/site-packages/tornado/web.py", line 2297, in wrapper
    return method(self, *args, **kwargs)
  File "/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython/html/services/kernels/handlers.py", line 46, in post
    kernel_id = km.start_kernel(notebook_id, cwd=nbm.notebook_dir)
  File "/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython/html/services/kernels/kernelmanager.py", line 86, in start_kernel
    kernel_id = super(MappingKernelManager, self).start_kernel(**kwargs)
  File "/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython/kernel/multikernelmanager.py", line 115, in start_kernel
    km.start_kernel(**kwargs)
  File "/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython/kernel/manager.py", line 201, in start_kernel
    kernel_cmd = self.format_kernel_cmd(**kw)
  File "/Users/karissamckelvey/dev/continuum/thirdparty/ipythonprivate/IPython/kernel/manager.py", line 154, in format_kernel_cmd
    return [ c.format(**ns) for c in cmd ]
KeyError: u"'static_url_prefix'"
2013-10-02 17:44:15.200 [tornado.access] ERROR | 500 POST /kernels?notebook=03fb94ab-98f3-4c18-808b-298ffc79a01a (127.0.0.1) 12.20ms```
``````



Discussion:
It should work fine to specify this value in a config file, rather than on the command-line in the meantime.

That's fine, but we really need this on the command line. 


Resolving patch:
diff --git a/IPython/kernel/manager.py b/IPython/kernel/manager.py
--- a/IPython/kernel/manager.py
+++ b/IPython/kernel/manager.py
@@ -14,6 +14,7 @@
 from __future__ import absolute_import
 
 # Standard library imports
+import re
 import signal
 import sys
 import time
@@ -140,7 +141,7 @@ def client(self, **kwargs):
     #--------------------------------------------------------------------------
 
     def format_kernel_cmd(self, **kw):
-        """format templated args (e.g. {connection_file})"""
+        """replace templated args (e.g. {connection_file})"""
         if self.kernel_cmd:
             cmd = self.kernel_cmd
         else:
@@ -150,7 +151,13 @@ def format_kernel_cmd(self, **kw):
             )
         ns = dict(connection_file=self.connection_file)
         ns.update(self._launch_args)
-        return [ c.format(**ns) for c in cmd ]
+        
+        pat = re.compile(r'\{([A-Za-z0-9_]+)\}')
+        def from_ns(match):
+            """Get the key out of ns if it's there, otherwise no change."""
+            return ns.get(match.group(1), match.group())
+        
+        return [ pat.sub(from_ns, arg) for arg in cmd ]
 
     def _launch_kernel(self, kernel_cmd, **kw):
         """actually launch the kernel


Test patch: