We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DirectoryHandler does not handle ipynb files correctly
The documentation says that the ``DirectoryHandler`` allows serving main.ipynb notebook files inside a directory and the code does have codepaths that mention notebooks. However the implementation tries to load notebook files as if they were normal scripts, leading to immediate errors because notebook files are actually JSON. If the DirectoryHandler finds an ipynb file it should apply the same nbconvert transform used by the NotebookHandler.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bokeh/application/handlers/directory.py`
Content:
```
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2012 - 2019, Anaconda, Inc., and Bokeh Contributors.
3 # All rights reserved.
4 #
5 # The full license is in the file LICENSE.txt, distributed with this software.
6 #-----------------------------------------------------------------------------
7 '''  Provide a Bokeh Application Handler to build up documents by running
8 the code from ``main.py`` or ``main.ipynb`` files in specified directories.
9 
10 The directory may also optionally contain:
11 
12 * A ``server_lifecyle.py`` module to provide lifecycle callbacks for the
13   application and sessions.
14 
15 * A ``static`` subdirectory containing app-specific static resources to
16   serve.
17 
18 * A ``theme.yaml`` file containing a Bokeh theme to automatically apply to
19   all new documents.
20 
21 * A ``templates`` subdirectory containing templates for app display
22 
23 A full directory layout might look like:
24 
25 .. code-block:: none
26 
27     myapp
28        |
29        +---main.py
30        +---server_lifecycle.py
31        +---static
32        +---theme.yaml
33        +---templates
34             +---index.html
35 
36 '''
37 
38 #-----------------------------------------------------------------------------
39 # Boilerplate
40 #-----------------------------------------------------------------------------
41 from __future__ import absolute_import, division, print_function, unicode_literals
42 
43 import logging
44 log = logging.getLogger(__name__)
45 
46 #-----------------------------------------------------------------------------
47 # Imports
48 #-----------------------------------------------------------------------------
49 
50 # Standard library imports
51 from os.path import basename, dirname, exists, join
52 
53 # External imports
54 from jinja2 import Environment, FileSystemLoader
55 
56 # Bokeh imports
57 from .handler import Handler
58 from .script import ScriptHandler
59 from .server_lifecycle import ServerLifecycleHandler
60 
61 #-----------------------------------------------------------------------------
62 # Globals and constants
63 #-----------------------------------------------------------------------------
64 
65 __all__ = (
66     'DirectoryHandler',
67 )
68 
69 #-----------------------------------------------------------------------------
70 # General API
71 #-----------------------------------------------------------------------------
72 
73 #-----------------------------------------------------------------------------
74 # Dev API
75 #-----------------------------------------------------------------------------
76 
77 class DirectoryHandler(Handler):
78     ''' Load an application directory which modifies a Document.
79 
80     '''
81 
82     def __init__(self, *args, **kwargs):
83         '''
84         Keywords:
85             filename (str) : a path to an application directory with either "main.py" or "main.ipynb"
86 
87             argv (list[str], optional) : a list of string arguments to make available as sys.argv to main.py
88         '''
89         super(DirectoryHandler, self).__init__(*args, **kwargs)
90 
91         if 'filename' not in kwargs:
92             raise ValueError('Must pass a filename to DirectoryHandler')
93         src_path = kwargs['filename']
94         argv = kwargs.get('argv', [])
95 
96         main_py = join(src_path, 'main.py')
97         main_ipy = join(src_path, 'main.ipynb')
98         if exists(main_py) and exists(main_ipy):
99             log.warning("Found both 'main.py' and 'main.ipynb' in %s, using 'main.py'" % (src_path))
100             main = main_py
101         elif exists(main_py):
102             main = main_py
103         elif exists(main_ipy):
104             main = main_ipy
105         else:
106             raise ValueError("No 'main.py' or 'main.ipynb' in %s" % (src_path))
107         self._path = src_path
108         self._main = main
109         self._main_handler = ScriptHandler(filename=self._main, argv=argv)
110 
111         lifecycle = join(src_path, 'server_lifecycle.py')
112         if exists(lifecycle):
113             self._lifecycle = lifecycle
114             self._lifecycle_handler = ServerLifecycleHandler(filename=self._lifecycle, argv=argv)
115         else:
116             self._lifecycle = None
117             self._lifecycle_handler = Handler() # no-op handler
118 
119         self._theme = None
120         themeyaml = join(src_path, 'theme.yaml')
121         if exists(themeyaml):
122             from bokeh.themes import Theme
123             self._theme = Theme(filename=themeyaml)
124 
125         appstatic = join(src_path, 'static')
126         if exists(appstatic):
127             self._static = appstatic
128 
129         self._template = None
130         appindex = join(src_path, 'templates', 'index.html')
131         if exists(appindex):
132             env = Environment(loader=FileSystemLoader(dirname(appindex)))
133             self._template = env.get_template('index.html')
134 
135     # Properties --------------------------------------------------------------
136 
137     @property
138     def error(self):
139         ''' If the handler fails, may contain a related error message.
140 
141         '''
142         return self._main_handler.error or self._lifecycle_handler.error
143 
144     @property
145     def error_detail(self):
146         ''' If the handler fails, may contain a traceback or other details.
147 
148         '''
149         return self._main_handler.error_detail or self._lifecycle_handler.error_detail
150 
151     @property
152     def failed(self):
153         ''' ``True`` if the handler failed to modify the doc
154 
155         '''
156         return self._main_handler.failed or self._lifecycle_handler.failed
157 
158     @property
159     def safe_to_fork(self):
160         ''' Whether it is still safe for the Bokeh server to fork new workers.
161 
162         ``False`` if the configured code (script, notebook, etc.) has already
163         been run.
164 
165         '''
166         return self._main_handler.safe_to_fork
167 
168     # Public methods ----------------------------------------------------------
169 
170     def modify_document(self, doc):
171         ''' Execute the configured ``main.py`` or ``main.ipynb`` to modify the
172         document.
173 
174         This method will also search the app directory for any theme or
175         template files, and automatically configure the document with them
176         if they are found.
177 
178         '''
179         if self._lifecycle_handler.failed:
180             return
181         # Note: we do NOT copy self._theme, which assumes the Theme
182         # class is immutable (has no setters)
183         if self._theme is not None:
184             doc.theme = self._theme
185 
186         if self._template is not None:
187             doc.template = self._template
188 
189         # This internal handler should never add a template
190         self._main_handler.modify_document(doc)
191 
192     def on_server_loaded(self, server_context):
193         ''' Execute `on_server_unloaded`` from ``server_lifecycle.py`` (if
194         it is defined) when the server is first started.
195 
196         Args:
197             server_context (ServerContext) :
198 
199         '''
200         return self._lifecycle_handler.on_server_loaded(server_context)
201 
202     def on_server_unloaded(self, server_context):
203         ''' Execute ``on_server_unloaded`` from ``server_lifecycle.py`` (if
204         it is defined) when the server cleanly exits. (Before stopping the
205         server's ``IOLoop``.)
206 
207         Args:
208             server_context (ServerContext) :
209 
210         .. warning::
211             In practice this code may not run, since servers are often killed
212             by a signal.
213 
214 
215         '''
216         return self._lifecycle_handler.on_server_unloaded(server_context)
217 
218     def on_session_created(self, session_context):
219         ''' Execute ``on_session_created`` from ``server_lifecycle.py`` (if
220         it is defined) when a new session is created.
221 
222         Args:
223             session_context (SessionContext) :
224 
225         '''
226         return self._lifecycle_handler.on_session_created(session_context)
227 
228     def on_session_destroyed(self, session_context):
229         ''' Execute ``on_session_destroyed`` from ``server_lifecycle.py`` (if
230         it is defined) when a session is destroyed.
231 
232         Args:
233             session_context (SessionContext) :
234 
235         '''
236         return self._lifecycle_handler.on_session_destroyed(session_context)
237 
238     def url_path(self):
239         ''' The last path component for the basename of the path to the
240         configured directory.
241 
242         '''
243         if self.failed:
244             return None
245         else:
246             # TODO should fix invalid URL characters
247             return '/' + basename(self._path)
248 
249 #-----------------------------------------------------------------------------
250 # Private API
251 #-----------------------------------------------------------------------------
252 
253 #-----------------------------------------------------------------------------
254 # Code
255 #-----------------------------------------------------------------------------
256
```
--- 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()

```

diff --git a/bokeh/application/handlers/directory.py b/bokeh/application/handlers/directory.py
--- a/bokeh/application/handlers/directory.py
+++ b/bokeh/application/handlers/directory.py
@@ -55,6 +55,7 @@
 
 # Bokeh imports
 from .handler import Handler
+from .notebook import NotebookHandler
 from .script import ScriptHandler
 from .server_lifecycle import ServerLifecycleHandler
 
@@ -106,7 +107,9 @@
             raise ValueError("No 'main.py' or 'main.ipynb' in %s" % (src_path))
         self._path = src_path
         self._main = main
-        self._main_handler = ScriptHandler(filename=self._main, argv=argv)
+
+        handler = NotebookHandler if main.endswith('.ipynb') else ScriptHandler
+        self._main_handler = handler(filename=self._main, argv=argv)
 
         lifecycle = join(src_path, 'server_lifecycle.py')
         if exists(lifecycle):

{"golden_diff": "diff --git a/bokeh/application/handlers/directory.py b/bokeh/application/handlers/directory.py\n--- a/bokeh/application/handlers/directory.py\n+++ b/bokeh/application/handlers/directory.py\n@@ -55,6 +55,7 @@\n \n # Bokeh imports\n from .handler import Handler\n+from .notebook import NotebookHandler\n from .script import ScriptHandler\n from .server_lifecycle import ServerLifecycleHandler\n \n@@ -106,7 +107,9 @@\n             raise ValueError(\"No 'main.py' or 'main.ipynb' in %s\" % (src_path))\n         self._path = src_path\n         self._main = main\n-        self._main_handler = ScriptHandler(filename=self._main, argv=argv)\n+\n+        handler = NotebookHandler if main.endswith('.ipynb') else ScriptHandler\n+        self._main_handler = handler(filename=self._main, argv=argv)\n \n         lifecycle = join(src_path, 'server_lifecycle.py')\n         if exists(lifecycle):\n", "issue": "DirectoryHandler does not handle ipynb files correctly\nThe documentation says that the ``DirectoryHandler`` allows serving main.ipynb notebook files inside a directory and the code does have codepaths that mention notebooks. However the implementation tries to load notebook files as if they were normal scripts, leading to immediate errors because notebook files are actually JSON. If the DirectoryHandler finds an ipynb file it should apply the same nbconvert transform used by the NotebookHandler.\n", "before_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2012 - 2019, Anaconda, Inc., and Bokeh Contributors.\n# All rights reserved.\n#\n# The full license is in the file LICENSE.txt, distributed with this software.\n#-----------------------------------------------------------------------------\n'''  Provide a Bokeh Application Handler to build up documents by running\nthe code from ``main.py`` or ``main.ipynb`` files in specified directories.\n\nThe directory may also optionally contain:\n\n* A ``server_lifecyle.py`` module to provide lifecycle callbacks for the\n  application and sessions.\n\n* A ``static`` subdirectory containing app-specific static resources to\n  serve.\n\n* A ``theme.yaml`` file containing a Bokeh theme to automatically apply to\n  all new documents.\n\n* A ``templates`` subdirectory containing templates for app display\n\nA full directory layout might look like:\n\n.. code-block:: none\n\n    myapp\n       |\n       +---main.py\n       +---server_lifecycle.py\n       +---static\n       +---theme.yaml\n       +---templates\n            +---index.html\n\n'''\n\n#-----------------------------------------------------------------------------\n# Boilerplate\n#-----------------------------------------------------------------------------\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\nlog = logging.getLogger(__name__)\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\n\n# Standard library imports\nfrom os.path import basename, dirname, exists, join\n\n# External imports\nfrom jinja2 import Environment, FileSystemLoader\n\n# Bokeh imports\nfrom .handler import Handler\nfrom .script import ScriptHandler\nfrom .server_lifecycle import ServerLifecycleHandler\n\n#-----------------------------------------------------------------------------\n# Globals and constants\n#-----------------------------------------------------------------------------\n\n__all__ = (\n    'DirectoryHandler',\n)\n\n#-----------------------------------------------------------------------------\n# General API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Dev API\n#-----------------------------------------------------------------------------\n\nclass DirectoryHandler(Handler):\n    ''' Load an application directory which modifies a Document.\n\n    '''\n\n    def __init__(self, *args, **kwargs):\n        '''\n        Keywords:\n            filename (str) : a path to an application directory with either \"main.py\" or \"main.ipynb\"\n\n            argv (list[str], optional) : a list of string arguments to make available as sys.argv to main.py\n        '''\n        super(DirectoryHandler, self).__init__(*args, **kwargs)\n\n        if 'filename' not in kwargs:\n            raise ValueError('Must pass a filename to DirectoryHandler')\n        src_path = kwargs['filename']\n        argv = kwargs.get('argv', [])\n\n        main_py = join(src_path, 'main.py')\n        main_ipy = join(src_path, 'main.ipynb')\n        if exists(main_py) and exists(main_ipy):\n            log.warning(\"Found both 'main.py' and 'main.ipynb' in %s, using 'main.py'\" % (src_path))\n            main = main_py\n        elif exists(main_py):\n            main = main_py\n        elif exists(main_ipy):\n            main = main_ipy\n        else:\n            raise ValueError(\"No 'main.py' or 'main.ipynb' in %s\" % (src_path))\n        self._path = src_path\n        self._main = main\n        self._main_handler = ScriptHandler(filename=self._main, argv=argv)\n\n        lifecycle = join(src_path, 'server_lifecycle.py')\n        if exists(lifecycle):\n            self._lifecycle = lifecycle\n            self._lifecycle_handler = ServerLifecycleHandler(filename=self._lifecycle, argv=argv)\n        else:\n            self._lifecycle = None\n            self._lifecycle_handler = Handler() # no-op handler\n\n        self._theme = None\n        themeyaml = join(src_path, 'theme.yaml')\n        if exists(themeyaml):\n            from bokeh.themes import Theme\n            self._theme = Theme(filename=themeyaml)\n\n        appstatic = join(src_path, 'static')\n        if exists(appstatic):\n            self._static = appstatic\n\n        self._template = None\n        appindex = join(src_path, 'templates', 'index.html')\n        if exists(appindex):\n            env = Environment(loader=FileSystemLoader(dirname(appindex)))\n            self._template = env.get_template('index.html')\n\n    # Properties --------------------------------------------------------------\n\n    @property\n    def error(self):\n        ''' If the handler fails, may contain a related error message.\n\n        '''\n        return self._main_handler.error or self._lifecycle_handler.error\n\n    @property\n    def error_detail(self):\n        ''' If the handler fails, may contain a traceback or other details.\n\n        '''\n        return self._main_handler.error_detail or self._lifecycle_handler.error_detail\n\n    @property\n    def failed(self):\n        ''' ``True`` if the handler failed to modify the doc\n\n        '''\n        return self._main_handler.failed or self._lifecycle_handler.failed\n\n    @property\n    def safe_to_fork(self):\n        ''' Whether it is still safe for the Bokeh server to fork new workers.\n\n        ``False`` if the configured code (script, notebook, etc.) has already\n        been run.\n\n        '''\n        return self._main_handler.safe_to_fork\n\n    # Public methods ----------------------------------------------------------\n\n    def modify_document(self, doc):\n        ''' Execute the configured ``main.py`` or ``main.ipynb`` to modify the\n        document.\n\n        This method will also search the app directory for any theme or\n        template files, and automatically configure the document with them\n        if they are found.\n\n        '''\n        if self._lifecycle_handler.failed:\n            return\n        # Note: we do NOT copy self._theme, which assumes the Theme\n        # class is immutable (has no setters)\n        if self._theme is not None:\n            doc.theme = self._theme\n\n        if self._template is not None:\n            doc.template = self._template\n\n        # This internal handler should never add a template\n        self._main_handler.modify_document(doc)\n\n    def on_server_loaded(self, server_context):\n        ''' Execute `on_server_unloaded`` from ``server_lifecycle.py`` (if\n        it is defined) when the server is first started.\n\n        Args:\n            server_context (ServerContext) :\n\n        '''\n        return self._lifecycle_handler.on_server_loaded(server_context)\n\n    def on_server_unloaded(self, server_context):\n        ''' Execute ``on_server_unloaded`` from ``server_lifecycle.py`` (if\n        it is defined) when the server cleanly exits. (Before stopping the\n        server's ``IOLoop``.)\n\n        Args:\n            server_context (ServerContext) :\n\n        .. warning::\n            In practice this code may not run, since servers are often killed\n            by a signal.\n\n\n        '''\n        return self._lifecycle_handler.on_server_unloaded(server_context)\n\n    def on_session_created(self, session_context):\n        ''' Execute ``on_session_created`` from ``server_lifecycle.py`` (if\n        it is defined) when a new session is created.\n\n        Args:\n            session_context (SessionContext) :\n\n        '''\n        return self._lifecycle_handler.on_session_created(session_context)\n\n    def on_session_destroyed(self, session_context):\n        ''' Execute ``on_session_destroyed`` from ``server_lifecycle.py`` (if\n        it is defined) when a session is destroyed.\n\n        Args:\n            session_context (SessionContext) :\n\n        '''\n        return self._lifecycle_handler.on_session_destroyed(session_context)\n\n    def url_path(self):\n        ''' The last path component for the basename of the path to the\n        configured directory.\n\n        '''\n        if self.failed:\n            return None\n        else:\n            # TODO should fix invalid URL characters\n            return '/' + basename(self._path)\n\n#-----------------------------------------------------------------------------\n# Private API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n", "path": "bokeh/application/handlers/directory.py"}], "after_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2012 - 2019, Anaconda, Inc., and Bokeh Contributors.\n# All rights reserved.\n#\n# The full license is in the file LICENSE.txt, distributed with this software.\n#-----------------------------------------------------------------------------\n'''  Provide a Bokeh Application Handler to build up documents by running\nthe code from ``main.py`` or ``main.ipynb`` files in specified directories.\n\nThe directory may also optionally contain:\n\n* A ``server_lifecyle.py`` module to provide lifecycle callbacks for the\n  application and sessions.\n\n* A ``static`` subdirectory containing app-specific static resources to\n  serve.\n\n* A ``theme.yaml`` file containing a Bokeh theme to automatically apply to\n  all new documents.\n\n* A ``templates`` subdirectory containing templates for app display\n\nA full directory layout might look like:\n\n.. code-block:: none\n\n    myapp\n       |\n       +---main.py\n       +---server_lifecycle.py\n       +---static\n       +---theme.yaml\n       +---templates\n            +---index.html\n\n'''\n\n#-----------------------------------------------------------------------------\n# Boilerplate\n#-----------------------------------------------------------------------------\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\nlog = logging.getLogger(__name__)\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\n\n# Standard library imports\nfrom os.path import basename, dirname, exists, join\n\n# External imports\nfrom jinja2 import Environment, FileSystemLoader\n\n# Bokeh imports\nfrom .handler import Handler\nfrom .notebook import NotebookHandler\nfrom .script import ScriptHandler\nfrom .server_lifecycle import ServerLifecycleHandler\n\n#-----------------------------------------------------------------------------\n# Globals and constants\n#-----------------------------------------------------------------------------\n\n__all__ = (\n    'DirectoryHandler',\n)\n\n#-----------------------------------------------------------------------------\n# General API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Dev API\n#-----------------------------------------------------------------------------\n\nclass DirectoryHandler(Handler):\n    ''' Load an application directory which modifies a Document.\n\n    '''\n\n    def __init__(self, *args, **kwargs):\n        '''\n        Keywords:\n            filename (str) : a path to an application directory with either \"main.py\" or \"main.ipynb\"\n\n            argv (list[str], optional) : a list of string arguments to make available as sys.argv to main.py\n        '''\n        super(DirectoryHandler, self).__init__(*args, **kwargs)\n\n        if 'filename' not in kwargs:\n            raise ValueError('Must pass a filename to DirectoryHandler')\n        src_path = kwargs['filename']\n        argv = kwargs.get('argv', [])\n\n        main_py = join(src_path, 'main.py')\n        main_ipy = join(src_path, 'main.ipynb')\n        if exists(main_py) and exists(main_ipy):\n            log.warning(\"Found both 'main.py' and 'main.ipynb' in %s, using 'main.py'\" % (src_path))\n            main = main_py\n        elif exists(main_py):\n            main = main_py\n        elif exists(main_ipy):\n            main = main_ipy\n        else:\n            raise ValueError(\"No 'main.py' or 'main.ipynb' in %s\" % (src_path))\n        self._path = src_path\n        self._main = main\n\n        handler = NotebookHandler if main.endswith('.ipynb') else ScriptHandler\n        self._main_handler = handler(filename=self._main, argv=argv)\n\n        lifecycle = join(src_path, 'server_lifecycle.py')\n        if exists(lifecycle):\n            self._lifecycle = lifecycle\n            self._lifecycle_handler = ServerLifecycleHandler(filename=self._lifecycle, argv=argv)\n        else:\n            self._lifecycle = None\n            self._lifecycle_handler = Handler() # no-op handler\n\n        self._theme = None\n        themeyaml = join(src_path, 'theme.yaml')\n        if exists(themeyaml):\n            from bokeh.themes import Theme\n            self._theme = Theme(filename=themeyaml)\n\n        appstatic = join(src_path, 'static')\n        if exists(appstatic):\n            self._static = appstatic\n\n        self._template = None\n        appindex = join(src_path, 'templates', 'index.html')\n        if exists(appindex):\n            env = Environment(loader=FileSystemLoader(dirname(appindex)))\n            self._template = env.get_template('index.html')\n\n    # Properties --------------------------------------------------------------\n\n    @property\n    def error(self):\n        ''' If the handler fails, may contain a related error message.\n\n        '''\n        return self._main_handler.error or self._lifecycle_handler.error\n\n    @property\n    def error_detail(self):\n        ''' If the handler fails, may contain a traceback or other details.\n\n        '''\n        return self._main_handler.error_detail or self._lifecycle_handler.error_detail\n\n    @property\n    def failed(self):\n        ''' ``True`` if the handler failed to modify the doc\n\n        '''\n        return self._main_handler.failed or self._lifecycle_handler.failed\n\n    @property\n    def safe_to_fork(self):\n        ''' Whether it is still safe for the Bokeh server to fork new workers.\n\n        ``False`` if the configured code (script, notebook, etc.) has already\n        been run.\n\n        '''\n        return self._main_handler.safe_to_fork\n\n    # Public methods ----------------------------------------------------------\n\n    def modify_document(self, doc):\n        ''' Execute the configured ``main.py`` or ``main.ipynb`` to modify the\n        document.\n\n        This method will also search the app directory for any theme or\n        template files, and automatically configure the document with them\n        if they are found.\n\n        '''\n        if self._lifecycle_handler.failed:\n            return\n        # Note: we do NOT copy self._theme, which assumes the Theme\n        # class is immutable (has no setters)\n        if self._theme is not None:\n            doc.theme = self._theme\n\n        if self._template is not None:\n            doc.template = self._template\n\n        # This internal handler should never add a template\n        self._main_handler.modify_document(doc)\n\n    def on_server_loaded(self, server_context):\n        ''' Execute `on_server_unloaded`` from ``server_lifecycle.py`` (if\n        it is defined) when the server is first started.\n\n        Args:\n            server_context (ServerContext) :\n\n        '''\n        return self._lifecycle_handler.on_server_loaded(server_context)\n\n    def on_server_unloaded(self, server_context):\n        ''' Execute ``on_server_unloaded`` from ``server_lifecycle.py`` (if\n        it is defined) when the server cleanly exits. (Before stopping the\n        server's ``IOLoop``.)\n\n        Args:\n            server_context (ServerContext) :\n\n        .. warning::\n            In practice this code may not run, since servers are often killed\n            by a signal.\n\n\n        '''\n        return self._lifecycle_handler.on_server_unloaded(server_context)\n\n    def on_session_created(self, session_context):\n        ''' Execute ``on_session_created`` from ``server_lifecycle.py`` (if\n        it is defined) when a new session is created.\n\n        Args:\n            session_context (SessionContext) :\n\n        '''\n        return self._lifecycle_handler.on_session_created(session_context)\n\n    def on_session_destroyed(self, session_context):\n        ''' Execute ``on_session_destroyed`` from ``server_lifecycle.py`` (if\n        it is defined) when a session is destroyed.\n\n        Args:\n            session_context (SessionContext) :\n\n        '''\n        return self._lifecycle_handler.on_session_destroyed(session_context)\n\n    def url_path(self):\n        ''' The last path component for the basename of the path to the\n        configured directory.\n\n        '''\n        if self.failed:\n            return None\n        else:\n            # TODO should fix invalid URL characters\n            return '/' + basename(self._path)\n\n#-----------------------------------------------------------------------------\n# Private API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n", "path": "bokeh/application/handlers/directory.py"}]}