Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Jan 17, 2024
1 parent 32b06a6 commit ae94f01
Show file tree
Hide file tree
Showing 22 changed files with 341 additions and 114 deletions.
4 changes: 3 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ async def initialize_app():
jp_asyncio_loop.run_until_complete(initialize_app())
# Reroute all logging StreamHandlers away from stdin/stdout since pytest hijacks
# these streams and closes them at unfortunate times.
stream_handlers = [h for h in app.log.handlers if isinstance(h, logging.StreamHandler)]
stream_handlers = [
h for h in app.log.handlers if isinstance(h, logging.StreamHandler)
]
for handler in stream_handlers:
handler.setStream(jp_logging_stream)
app.log.propagate = True
Expand Down
4 changes: 3 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "kernel_gateway", "Kernel Gateway Documentation", [author], 1)]
man_pages = [
(master_doc, "kernel_gateway", "Kernel Gateway Documentation", [author], 1)
]

# If true, show URL addresses after external links.
# man_show_urls = False
Expand Down
8 changes: 6 additions & 2 deletions etc/api_examples/api_intro.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,9 @@
"body = req[\"body\"]\n",
"contact_id = req[\"path\"][\"contact_id\"]\n",
"if contact_id in contacts:\n",
" contacts[contact_id].update({field: body[field] for field in fields if field in body})\n",
" contacts[contact_id].update(\n",
" {field: body[field] for field in fields if field in body}\n",
" )\n",
" status = 200\n",
" print(json.dumps({\"contact_id\": contacts[contact_id]}))\n",
"else:\n",
Expand Down Expand Up @@ -618,7 +620,9 @@
" first_contact_id = post_resp.json()[\"contact_id\"]\n",
"\n",
" # update the contact\n",
" put_resp = requests.put(URL + \"/contacts/\" + first_contact_id, {\"phone\": \"919-444-5601\"})\n",
" put_resp = requests.put(\n",
" URL + \"/contacts/\" + first_contact_id, {\"phone\": \"919-444-5601\"}\n",
" )\n",
" put_resp.raise_for_status()\n",
" print(\"\\nupdated a contact:\", put_resp.json())\n",
"\n",
Expand Down
5 changes: 4 additions & 1 deletion kernel_gateway/base/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@


class APIVersionHandler(
TokenAuthorizationMixin, CORSMixin, JSONErrorsMixin, server_handlers.APIVersionHandler
TokenAuthorizationMixin,
CORSMixin,
JSONErrorsMixin,
server_handlers.APIVersionHandler,
):
"""Extends the notebook server base API handler with token auth, CORS, and
JSON errors.
Expand Down
74 changes: 55 additions & 19 deletions kernel_gateway/gatewayapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,26 @@
from jupyter_core.paths import secure_write
from jupyter_server.auth.authorizer import AllowAllAuthorizer, Authorizer
from jupyter_server.serverapp import random_ports
from jupyter_server.services.kernels.connection.base import BaseKernelWebsocketConnection
from jupyter_server.services.kernels.connection.channels import ZMQChannelsWebsocketConnection
from jupyter_server.services.kernels.connection.base import (
BaseKernelWebsocketConnection,
)
from jupyter_server.services.kernels.connection.channels import (
ZMQChannelsWebsocketConnection,
)
from jupyter_server.services.kernels.kernelmanager import MappingKernelManager
from tornado import httpserver, ioloop, web
from tornado.log import LogFormatter, enable_pretty_logging
from traitlets import Bytes, CBool, Instance, Integer, List, Type, Unicode, default, observe
from traitlets import (
Bytes,
CBool,
Instance,
Integer,
List,
Type,
Unicode,
default,
observe,
)

from ._version import __version__
from .auth.identity import GatewayIdentityProvider
Expand Down Expand Up @@ -84,7 +98,9 @@ class KernelGatewayApp(JupyterApp):
port_env = "KG_PORT"
port_default_value = 8888
port = Integer(
port_default_value, config=True, help="Port on which to listen (KG_PORT env var)"
port_default_value,
config=True,
help="Port on which to listen (KG_PORT env var)",
)

@default("port")
Expand All @@ -106,7 +122,9 @@ def port_retries_default(self):
ip_env = "KG_IP"
ip_default_value = "127.0.0.1"
ip = Unicode(
ip_default_value, config=True, help="IP address on which to listen (KG_IP env var)"
ip_default_value,
config=True,
help="IP address on which to listen (KG_IP env var)",
)

@default("ip")
Expand All @@ -129,7 +147,8 @@ def base_url_default(self):
# Token authorization
auth_token_env = "KG_AUTH_TOKEN"
auth_token = Unicode(
config=True, help="Authorization token required for all requests (KG_AUTH_TOKEN env var)"
config=True,
help="Authorization token required for all requests (KG_AUTH_TOKEN env var)",
)

@default("auth_token")
Expand All @@ -149,7 +168,8 @@ def allow_credentials_default(self):

allow_headers_env = "KG_ALLOW_HEADERS"
allow_headers = Unicode(
config=True, help="Sets the Access-Control-Allow-Headers header. (KG_ALLOW_HEADERS env var)"
config=True,
help="Sets the Access-Control-Allow-Headers header. (KG_ALLOW_HEADERS env var)",
)

@default("allow_headers")
Expand All @@ -158,7 +178,8 @@ def allow_headers_default(self):

allow_methods_env = "KG_ALLOW_METHODS"
allow_methods = Unicode(
config=True, help="Sets the Access-Control-Allow-Methods header. (KG_ALLOW_METHODS env var)"
config=True,
help="Sets the Access-Control-Allow-Methods header. (KG_ALLOW_METHODS env var)",
)

@default("allow_methods")
Expand All @@ -167,7 +188,8 @@ def allow_methods_default(self):

allow_origin_env = "KG_ALLOW_ORIGIN"
allow_origin = Unicode(
config=True, help="Sets the Access-Control-Allow-Origin header. (KG_ALLOW_ORIGIN env var)"
config=True,
help="Sets the Access-Control-Allow-Origin header. (KG_ALLOW_ORIGIN env var)",
)

@default("allow_origin")
Expand Down Expand Up @@ -381,7 +403,9 @@ def _default_cookie_secret(self):

def _write_cookie_secret_file(self, secret):
"""write my secret to my secret_file"""
self.log.info("Writing Jupyter server cookie secret to %s", self.cookie_secret_file)
self.log.info(
"Writing Jupyter server cookie secret to %s", self.cookie_secret_file
)
try:
with secure_write(self.cookie_secret_file, True) as f:
f.write(secret)
Expand All @@ -404,16 +428,16 @@ def _write_cookie_secret_file(self, secret):

@default("ws_ping_interval")
def _ws_ping_interval_default(self) -> int:
return int(os.getenv(self.ws_ping_interval_env, self.ws_ping_interval_default_value))
return int(
os.getenv(self.ws_ping_interval_env, self.ws_ping_interval_default_value)
)

_log_formatter_cls = LogFormatter # traitlet default is LevelFormatter

@default("log_format")
def _default_log_format(self) -> str:
"""override default log format to include milliseconds"""
return (
"%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s]%(end_color)s %(message)s"
)
return "%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s]%(end_color)s %(message)s"

kernel_spec_manager = Instance(KernelSpecManager, allow_none=True)

Expand Down Expand Up @@ -571,7 +595,9 @@ def init_configurables(self):
**kwargs,
)

self.session_manager = SessionManager(log=self.log, kernel_manager=self.kernel_manager)
self.session_manager = SessionManager(
log=self.log, kernel_manager=self.kernel_manager
)
self.contents_manager = None

self.identity_provider = self.identity_provider_class(parent=self, log=self.log)
Expand Down Expand Up @@ -643,7 +669,9 @@ def init_webapp(self):
)

# promote the current personality's "config" tagged traitlet values to webapp settings
for trait_name, trait_value in self.personality.class_traits(config=True).items():
for trait_name, trait_value in self.personality.class_traits(
config=True
).items():
kg_name = "kg_" + trait_name
# a personality's traitlets may not overwrite the kernel gateway's
if kg_name not in self.web_app.settings:
Expand Down Expand Up @@ -695,9 +723,14 @@ def init_http_server(self):
self.http_server.listen(port, self.ip)
except OSError as e:
if e.errno == errno.EADDRINUSE:
self.log.info("The port %i is already in use, trying another port." % port)
self.log.info(
"The port %i is already in use, trying another port." % port
)
continue
elif e.errno in (errno.EACCES, getattr(errno, "WSAEACCES", errno.EACCES)):
elif e.errno in (
errno.EACCES,
getattr(errno, "WSAEACCES", errno.EACCES),
):
self.log.warning("Permission to listen on port %i denied" % port)
continue
else:
Expand Down Expand Up @@ -786,7 +819,10 @@ def start_app(self):
super().start()
self.log.info(
"Jupyter Kernel Gateway {} is available at http{}://{}:{}".format(
KernelGatewayApp.version, "s" if self.keyfile else "", self.ip, self.port
KernelGatewayApp.version,
"s" if self.keyfile else "",
self.ip,
self.port,
)
)

Expand Down
8 changes: 6 additions & 2 deletions kernel_gateway/jupyter_websocket/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
from ..base.handlers import default_handlers as default_base_handlers
from ..services.kernels.handlers import default_handlers as default_kernel_handlers
from ..services.kernels.pool import KernelPool
from ..services.kernelspecs.handlers import default_handlers as default_kernelspec_handlers
from ..services.kernelspecs.handlers import (
default_handlers as default_kernelspec_handlers,
)
from ..services.sessions.handlers import default_handlers as default_session_handlers
from .handlers import default_handlers as default_api_handlers

Expand Down Expand Up @@ -51,7 +53,9 @@ def __init__(self, *args, **kwargs):
self.kernel_pool = KernelPool()

async def init_configurables(self):
await self.kernel_pool.initialize(self.parent.prespawn_count, self.parent.kernel_manager)
await self.kernel_pool.initialize(
self.parent.prespawn_count, self.parent.kernel_manager
)

def create_request_handlers(self):
"""Create default Jupyter handlers and redefine them off of the
Expand Down
36 changes: 26 additions & 10 deletions kernel_gateway/notebook_http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ class NotebookHTTPPersonality(LoggingConfigurable):

@default("cell_parser")
def cell_parser_default(self):
return os.getenv(self.cell_parser_env, "kernel_gateway.notebook_http.cell.parser")
return os.getenv(
self.cell_parser_env, "kernel_gateway.notebook_http.cell.parser"
)

# Intentionally not defining an env var option for a dict type
comment_prefix = Dict(
{"scala": "//", None: "#"}, config=True, help="Maps kernel language to code comment syntax"
{"scala": "//", None: "#"},
config=True,
help="Maps kernel language to code comment syntax",
)

allow_notebook_download_env = "KG_ALLOW_NOTEBOOK_DOWNLOAD"
Expand Down Expand Up @@ -71,7 +75,9 @@ def __init__(self, *args, **kwargs):
# Build the parser using the comment syntax for the notebook language
func = cell_parser_module.create_parser
try:
kernel_language = self.parent.seed_notebook["metadata"]["language_info"]["name"]
kernel_language = self.parent.seed_notebook["metadata"]["language_info"][
"name"
]
except (AttributeError, KeyError):
kernel_language = None
prefix = self.comment_prefix.get(kernel_language, "#")
Expand All @@ -85,7 +91,9 @@ def __init__(self, *args, **kwargs):
self.kernel_pool = ManagedKernelPool()

async def init_configurables(self):
await self.kernel_pool.initialize(self.parent.prespawn_count, self.parent.kernel_manager)
await self.kernel_pool.initialize(
self.parent.prespawn_count, self.parent.kernel_manager
)

def create_request_handlers(self):
"""Create handlers and redefine them off of the base_url path. Assumes
Expand All @@ -97,13 +105,17 @@ def create_request_handlers(self):
if self.allow_notebook_download:
path = url_path_join("/", self.parent.base_url, r"/_api/source")
self.log.info(f"Registering resource: {path}, methods: (GET)")
handlers.append((path, NotebookDownloadHandler, {"path": self.parent.seed_uri}))
handlers.append(
(path, NotebookDownloadHandler, {"path": self.parent.seed_uri})
)

# Register a static path handler if configuration allows
if self.static_path is not None:
path = url_path_join("/", self.parent.base_url, r"/public/(.*)")
self.log.info(f"Registering resource: {path}, methods: (GET)")
handlers.append((path, tornado.web.StaticFileHandler, {"path": self.static_path}))
handlers.append(
(path, tornado.web.StaticFileHandler, {"path": self.static_path})
)

# Discover the notebook endpoints and their implementations
endpoints = self.api_parser.endpoints(self.parent.kernel_manager.seed_source)
Expand All @@ -118,14 +130,18 @@ def create_request_handlers(self):
# Cycle through the (endpoint_path, source) tuples and register their handlers
for endpoint_path, verb_source_map in endpoints:
parameterized_path = parameterize_path(endpoint_path)
parameterized_path = url_path_join("/", self.parent.base_url, parameterized_path)
parameterized_path = url_path_join(
"/", self.parent.base_url, parameterized_path
)
self.log.info(
"Registering resource: {}, methods: ({})".format(
parameterized_path, list(verb_source_map.keys())
)
)
response_source_map = (
response_sources[endpoint_path] if endpoint_path in response_sources else {}
response_sources[endpoint_path]
if endpoint_path in response_sources
else {}
)
handler_args = {
"sources": verb_source_map,
Expand Down Expand Up @@ -159,9 +175,9 @@ def should_seed_cell(self, code):
"""Determines whether the given code cell source should be executed when
seeding a new kernel."""
# seed cells that are uninvolved with the presented API
return not self.api_parser.is_api_cell(code) and not self.api_parser.is_api_response_cell(
return not self.api_parser.is_api_cell(
code
)
) and not self.api_parser.is_api_response_cell(code)

async def shutdown(self):
"""Stop all kernels in the pool."""
Expand Down
4 changes: 3 additions & 1 deletion kernel_gateway/notebook_http/cell/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ class APICellParser(LoggingConfigurable):

def __init__(self, comment_prefix, notebook_cells=None, **kwargs):
super().__init__(**kwargs)
self.kernelspec_api_indicator = re.compile(self.api_indicator.format(comment_prefix))
self.kernelspec_api_indicator = re.compile(
self.api_indicator.format(comment_prefix)
)
self.kernelspec_api_response_indicator = re.compile(
self.api_response_indicator.format(comment_prefix)
)
Expand Down
12 changes: 9 additions & 3 deletions kernel_gateway/notebook_http/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ class NotebookAPIHandler(
are identified, parsed, and associated with HTTP verbs and paths.
"""

def initialize(self, sources, response_sources, kernel_pool, kernel_name, kernel_language=""):
def initialize(
self, sources, response_sources, kernel_pool, kernel_name, kernel_language=""
):
self.kernel_pool = kernel_pool
self.sources = sources
self.kernel_name = kernel_name
Expand Down Expand Up @@ -202,12 +204,16 @@ async def _handle_request(self):
# Run the request and source code and yield until there's a result
access_log.debug(f"Request code for notebook cell is: {request_code}")
await self.execute_code(kernel_client, kernel_id, request_code)
source_result = await self.execute_code(kernel_client, kernel_id, source_code)
source_result = await self.execute_code(
kernel_client, kernel_id, source_code
)

# If a response code cell exists, execute it
if self.request.method in self.response_sources:
response_code = self.response_sources[self.request.method]
response_future = self.execute_code(kernel_client, kernel_id, response_code)
response_future = self.execute_code(
kernel_client, kernel_id, response_code
)

# Wait for the response and parse the json value
response_result = await response_future
Expand Down
Loading

0 comments on commit ae94f01

Please sign in to comment.