Skip to content

Commit 383655d

Browse files
committed
Address missing local-provisioner scenario
1 parent 7b5a95c commit 383655d

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

jupyter_client/provisioning/factory.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"""Kernel Provisioner Classes"""
22
# Copyright (c) Jupyter Development Team.
33
# Distributed under the terms of the Modified BSD License.
4-
import os
4+
import glob
5+
from os import getenv
6+
from os import path
57
from typing import Any
68
from typing import Dict
79
from typing import List
@@ -44,7 +46,7 @@ class KernelProvisionerFactory(SingletonConfigurable):
4446

4547
@default('default_provisioner_name')
4648
def default_provisioner_name_default(self):
47-
return os.getenv(self.default_provisioner_name_env, "local-provisioner")
49+
return getenv(self.default_provisioner_name_env, "local-provisioner")
4850

4951
def __init__(self, **kwargs) -> None:
5052
super().__init__(**kwargs)
@@ -115,7 +117,7 @@ def _check_availability(self, provisioner_name: str) -> bool:
115117
is_available = True
116118
if provisioner_name not in self.provisioners:
117119
try:
118-
ep = KernelProvisionerFactory._get_provisioner(provisioner_name)
120+
ep = self._get_provisioner(provisioner_name)
119121
self.provisioners[provisioner_name] = ep # Update cache
120122
except NoSuchEntryPoint:
121123
is_available = False
@@ -167,7 +169,33 @@ def _get_all_provisioners() -> List[EntryPoint]:
167169
"""Wrapper around entrypoints.get_group_all() - primarily to facilitate testing."""
168170
return get_group_all(KernelProvisionerFactory.GROUP_NAME)
169171

170-
@staticmethod
171-
def _get_provisioner(name: str) -> EntryPoint:
172+
def _get_provisioner(self, name: str) -> EntryPoint:
172173
"""Wrapper around entrypoints.get_single() - primarily to facilitate testing."""
173-
return get_single(KernelProvisionerFactory.GROUP_NAME, name)
174+
try:
175+
ep = get_single(KernelProvisionerFactory.GROUP_NAME, name)
176+
except NoSuchEntryPoint:
177+
# Check if the entrypoint name is 'local-provisioner'. Although this should never
178+
# happen, we have seen cases where the previous distribution of jupyter_client has
179+
# remained which doesn't include kernel-provisioner entrypoints (so 'local-provisioner'
180+
# is deemed not found even though its definition is in THIS package). In such cass,
181+
# the entrypoints package uses what it first finds - which is the older distribution
182+
# resulting in a violation of a supposed invariant condition. To address this scenario,
183+
# we will log a warning message indicating this situation, then build the entrypoint
184+
# instance ourselves - since we have that information.
185+
if name == 'local-provisioner':
186+
distros = glob.glob(f"{path.dirname(path.dirname(__file__))}-*")
187+
self.log.warn(
188+
f"Kernel Provisioning: The 'local-provisioner' is not found. This is likely "
189+
f"due to the presence of multiple jupyter_client distributions and a previous "
190+
f"distribution is being used as the source for entrypoints - which does not "
191+
f"include 'local-provisioner'. That distribution should be removed such that "
192+
f"only the version-appropriate distribution remains (version >= 7). Until "
193+
f"then, a 'local-provisioner' entrypoint will be automatically constructed "
194+
f"and used.\nThe candidate distribution locations are: {distros}"
195+
)
196+
ep = EntryPoint(
197+
'local-provisioner', 'jupyter_client.provisioning', 'LocalProvisioner'
198+
)
199+
else:
200+
raise
201+
return ep

jupyter_client/tests/test_provisioning.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def mock_get_all_provisioners() -> List[EntryPoint]:
210210
return result
211211

212212

213-
def mock_get_provisioner(name) -> EntryPoint:
213+
def mock_get_provisioner(factory, name) -> EntryPoint:
214214
if name == 'new-test-provisioner':
215215
return EntryPoint(
216216
'new-test-provisioner', 'jupyter_client.tests.test_provisioning', 'NewTestProvisioner'

0 commit comments

Comments
 (0)