77from textwrap import dedent
88from urllib .parse import urlparse
99
10+ from jupyter_core .application import JupyterApp
1011from jupyterhub .services .auth import HubOAuthCallbackHandler
1112from jupyterhub .utils import make_ssl_context
1213from tornado import httpclient , httpserver , ioloop , web
1314from tornado .web import RedirectHandler
14- from traitlets .config import Application as TraitletsApplication
1515from traitlets .traitlets import Bool , Int , Unicode , default , validate
1616
1717from ..config import ServerProcess
1818from .activity import start_activity_update
1919from .proxy import make_standalone_proxy
2020
2121
22- class StandaloneProxyServer (TraitletsApplication , ServerProcess ):
22+ class StandaloneProxyServer (JupyterApp , ServerProcess ):
2323 name = "jupyter-standalone-proxy"
2424 description = """
2525 Wrap an arbitrary web service so it can be used in place of 'jupyterhub-singleuser'
2626 in a JupyterHub setting.
2727
2828 Usage: jupyter standaloneproxy [options] -- <command>
2929
30- The <command> will be executed to start the web service once the proxy receives the first request. The command can
31- contain the placeholders '{{port}}', '{{unix_socket}}' and '{{base_url}}', which will be replaced with the
32- appropriate values once the application starts.
33-
3430 For more details, see the jupyter-server-proxy documentation.
3531 """
32+ examples = "jupyter standaloneproxy -- voila --port={port} --no-browser /path/to/notebook.ipynb"
3633
3734 base_url = Unicode (
3835 help = """
@@ -152,19 +149,21 @@ def __init__(self, **kwargs):
152149 # exeptions we do not need, for easier use of the CLI
153150 # We don't need "command" here, as we will take it from the extra_args
154151 ignore_traits = [
152+ "name" ,
155153 "launcher_entry" ,
156154 "new_browser_tab" ,
157155 "rewrite_response" ,
158156 "update_last_activity" ,
159157 "command" ,
160158 ]
161159 server_process_aliases = {
162- trait : f"ServerProcess .{ trait } "
160+ trait : f"StandaloneProxyServer .{ trait } "
163161 for trait in ServerProcess .class_traits (config = True )
164162 if trait not in ignore_traits and trait not in self .flags
165163 }
166164
167165 self .aliases = {
166+ ** super ().aliases ,
168167 ** server_process_aliases ,
169168 "base_url" : "StandaloneProxyServer.base_url" ,
170169 "address" : "StandaloneProxyServer.address" ,
@@ -174,6 +173,17 @@ def __init__(self, **kwargs):
174173 "websocket_max_message_size" : "StandaloneProxyServer.websocket_max_message_size" ,
175174 }
176175
176+ def emit_alias_help (self ):
177+ yield from super ().emit_alias_help ()
178+ yield ""
179+
180+ # Manually yield the help for command, which we will get from extra_args
181+ command_help = StandaloneProxyServer .class_get_trait_help (
182+ ServerProcess .command
183+ ).split ("\n " )
184+ yield command_help [0 ].replace ("--StandaloneProxyServer.command" , "command" )
185+ yield from command_help [1 :]
186+
177187 def get_proxy_base_class (self ) -> tuple [type | None , dict ]:
178188 cls , kwargs = super ().get_proxy_base_class ()
179189 if cls is None :
0 commit comments