Skip to content

Commit 569d305

Browse files
Backport PR #935: avoid creating asyncio.Lock at import time (#936)
Co-authored-by: Min RK <[email protected]>
1 parent 7f72f1c commit 569d305

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

jupyter_server/services/nbconvert/handlers.py

+23-18
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@
1111
AUTH_RESOURCE = "nbconvert"
1212

1313

14-
LOCK = asyncio.Lock()
15-
16-
1714
class NbconvertRootHandler(APIHandler):
1815
auth_resource = AUTH_RESOURCE
16+
_exporter_lock: asyncio.Lock
17+
18+
def initialize(self, **kwargs):
19+
super().initialize(**kwargs)
20+
# share lock across instances of this handler class
21+
if not hasattr(self.__class__, "_exporter_lock"):
22+
self.__class__._exporter_lock = asyncio.Lock()
23+
self._exporter_lock = self.__class__._exporter_lock
1924

2025
@web.authenticated
2126
@authorized
@@ -28,22 +33,22 @@ async def get(self):
2833
# Some exporters use the filesystem when instantiating, delegate that
2934
# to a thread so we don't block the event loop for it.
3035
exporters = await run_sync(base.get_export_names)
31-
for exporter_name in exporters:
32-
try:
33-
async with LOCK:
36+
async with self._exporter_lock:
37+
for exporter_name in exporters:
38+
try:
3439
exporter_class = await run_sync(base.get_exporter, exporter_name)
35-
except ValueError:
36-
# I think the only way this will happen is if the entrypoint
37-
# is uninstalled while this method is running
38-
continue
39-
# XXX: According to the docs, it looks like this should be set to None
40-
# if the exporter shouldn't be exposed to the front-end and a friendly
41-
# name if it should. However, none of the built-in exports have it defined.
42-
# if not exporter_class.export_from_notebook:
43-
# continue
44-
res[exporter_name] = {
45-
"output_mimetype": exporter_class.output_mimetype,
46-
}
40+
except ValueError:
41+
# I think the only way this will happen is if the entrypoint
42+
# is uninstalled while this method is running
43+
continue
44+
# XXX: According to the docs, it looks like this should be set to None
45+
# if the exporter shouldn't be exposed to the front-end and a friendly
46+
# name if it should. However, none of the built-in exports have it defined.
47+
# if not exporter_class.export_from_notebook:
48+
# continue
49+
res[exporter_name] = {
50+
"output_mimetype": exporter_class.output_mimetype,
51+
}
4752

4853
self.finish(json.dumps(res))
4954

0 commit comments

Comments
 (0)