Skip to content

Commit 544fdb2

Browse files
committed
Make ipykernel work without debugpy
debugpy is an optional dependency because only frontends with debugging support (Jupyter lab) can really use its features. Fixes: #712
1 parent 3c6037f commit 544fdb2

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,44 @@ jobs:
110110
- name: Check Docstrings
111111
run: |
112112
velin . --check --compact
113+
test_without_debugpy:
114+
runs-on: ${{ matrix.os }}-latest
115+
strategy:
116+
fail-fast: false
117+
matrix:
118+
os: [ubuntu]
119+
python-version: [ '3.9' ]
120+
steps:
121+
- name: Checkout
122+
uses: actions/checkout@v1
123+
- name: Install Python ${{ matrix.python-version }}
124+
uses: actions/setup-python@v1
125+
with:
126+
python-version: ${{ matrix.python-version }}
127+
architecture: 'x64'
128+
- name: Upgrade packaging dependencies
129+
run: |
130+
pip install --upgrade pip setuptools wheel --user
131+
- name: Get pip cache dir
132+
id: pip-cache
133+
run: |
134+
echo "::set-output name=dir::$(pip cache dir)"
135+
- name: Cache pip
136+
uses: actions/cache@v1
137+
with:
138+
path: ${{ steps.pip-cache.outputs.dir }}
139+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('setup.py') }}
140+
restore-keys: |
141+
${{ runner.os }}-pip-${{ matrix.python-version }}-
142+
${{ runner.os }}-pip-
143+
- name: Install the Python dependencies without debugpy
144+
run: |
145+
pip install --pre --upgrade --upgrade-strategy=eager .[test]
146+
pip uninstall --yes debugpy
147+
- name: List installed packages
148+
run: |
149+
pip freeze
150+
- name: Run the tests
151+
timeout-minutes: 10
152+
run: |
153+
pytest ipykernel -vv -s --durations 10

ipykernel/ipkernel.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from .kernelbase import Kernel as KernelBase
1818
from .zmqshell import ZMQInteractiveShell
1919
from .eventloops import _use_appnope
20-
from .debugger import Debugger
2120
from .compiler import XCachingCompiler
2221

2322
try:
@@ -34,6 +33,13 @@
3433
except ImportError:
3534
_use_experimental_60_completion = False
3635

36+
try:
37+
import debugpy
38+
from .debugger import Debugger
39+
_is_debugpy_available = True
40+
except ImportError:
41+
_is_debugpy_available = False
42+
3743
_EXPERIMENTAL_KEY_NAME = '_jupyter_types_experimental'
3844

3945

@@ -46,7 +52,7 @@ class IPythonKernel(KernelBase):
4652
help="Set this flag to False to deactivate the use of experimental IPython completion APIs.",
4753
).tag(config=True)
4854

49-
debugpy_stream = Instance(ZMQStream, allow_none=True)
55+
debugpy_stream = Instance(ZMQStream, allow_none=True) if _is_debugpy_available else None
5056

5157
user_module = Any()
5258
@observe('user_module')
@@ -72,11 +78,12 @@ def __init__(self, **kwargs):
7278
super(IPythonKernel, self).__init__(**kwargs)
7379

7480
# Initialize the Debugger
75-
self.debugger = Debugger(self.log,
76-
self.debugpy_stream,
77-
self._publish_debug_event,
78-
self.debug_shell_socket,
79-
self.session)
81+
if _is_debugpy_available:
82+
self.debugger = Debugger(self.log,
83+
self.debugpy_stream,
84+
self._publish_debug_event,
85+
self.debug_shell_socket,
86+
self.session)
8087

8188
# Initialize the InteractiveShell subclass
8289
self.shell = self.shell_class.instance(parent=self,
@@ -152,10 +159,11 @@ def __init__(self, **kwargs):
152159
}
153160

154161
def dispatch_debugpy(self, msg):
155-
# The first frame is the socket id, we can drop it
156-
frame = msg[1].bytes.decode('utf-8')
157-
self.log.debug("Debugpy received: %s", frame)
158-
self.debugger.tcp_client.receive_dap_frame(frame)
162+
if _is_debugpy_available:
163+
# The first frame is the socket id, we can drop it
164+
frame = msg[1].bytes.decode('utf-8')
165+
self.log.debug("Debugpy received: %s", frame)
166+
self.debugger.tcp_client.receive_dap_frame(frame)
159167

160168
@property
161169
def banner(self):
@@ -414,7 +422,8 @@ def do_complete(self, code, cursor_pos):
414422
'status' : 'ok'}
415423

416424
async def do_debug_request(self, msg):
417-
return await self.debugger.process_request(msg)
425+
if _is_debugpy_available:
426+
return await self.debugger.process_request(msg)
418427

419428
def _experimental_do_complete(self, code, cursor_pos):
420429
"""

ipykernel/kernelspec.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
from jupyter_client.kernelspec import KernelSpecManager
1515

16+
from .ipkernel import _is_debugpy_available
17+
1618
pjoin = os.path.join
1719

1820
KERNEL_NAME = 'python%i' % sys.version_info[0]
@@ -52,7 +54,7 @@ def get_kernel_dict(extra_arguments=None):
5254
'argv': make_ipkernel_cmd(extra_arguments=extra_arguments),
5355
'display_name': 'Python %i (ipykernel)' % sys.version_info[0],
5456
'language': 'python',
55-
'metadata': { 'debugger': True}
57+
'metadata': { 'debugger': _is_debugpy_available}
5658
}
5759

5860

0 commit comments

Comments
 (0)