1
- # # Building a Notebook client
2
- #
3
- # We want to test our bookstore endpoints, but it's no fun having to do this in an insecure fashion. Better would be to have some security in place.
4
- #
5
- #
6
- # ## Example notebook config
7
- #
8
- #
9
- # ```
10
- # [{'base_url': '/',
11
- # 'hostname ': 'localhost ',
12
- # 'notebook_dir ': '/Users/mpacer/jupyter/eg_notebooks ',
13
- # 'password ': False ,
14
- # 'pid ': 96033 ,
15
- # 'port ': 8888 ,
16
- # 'secure ': False ,
17
- # 'token ': '' ,
18
- # 'url ': 'http://localhost:8888/'}]
19
- # ```
20
-
1
+ """Client to test bookstore endpoints from within a notebook.
2
+
3
+
4
+ TODO: (Clarify) We want to test our bookstore endpoints, but it's no fun having
5
+ to do this in an insecure fashion. Better would be to have some security in
6
+ place.
7
+
8
+ Example
9
+ -------
10
+
11
+ [{'base_url ': '/ ',
12
+ 'hostname ': 'localhost ',
13
+ 'notebook_dir ': '/Users/mpacer/jupyter/eg_notebooks' ,
14
+ 'password ': False ,
15
+ 'pid ': 96033 ,
16
+ 'port ': 8888 ,
17
+ 'secure ': False ,
18
+ 'token ': '',
19
+ 'url': 'http://localhost:8888/'}]
20
+ """
21
21
import os
22
-
23
- import requests
24
-
22
+ import re
23
+ import json
25
24
from copy import deepcopy
26
25
from typing import NamedTuple
27
26
28
-
27
+ import requests
28
+ from IPython import get_ipython
29
29
from notebook .notebookapp import list_running_servers
30
30
31
31
32
32
def extract_kernel_id (connection_file ):
33
- return os .path .basename (connection_file ).lstrip ('kernel-' ).rstrip ('.json' )
33
+ connection_filename = os .path .basename (connection_file )
34
+ kernel_id = re .sub (r"kernel-(.*)\.json" , r"\1" , connection_filename )
35
+ return kernel_id
34
36
35
37
36
38
class LiveNotebookRecord (NamedTuple ):
@@ -58,30 +60,52 @@ class KernelInfo:
58
60
# execution_state: str #'idle',
59
61
# connections: int # 0
60
62
def __init__ (self , * args , id , name , last_activity , execution_state , connections ):
63
+ self .model = {
64
+ "id" : id ,
65
+ "name" : name ,
66
+ "last_activity" : last_activity ,
67
+ "execution_state" : execution_state ,
68
+ "connections" : connections ,
69
+ }
61
70
self .id = id
62
71
self .name = name
63
72
self .last_activity = last_activity
64
73
self .execution_state = execution_state
65
74
self .connections = connections
66
75
76
+ def __repr__ (self ):
77
+ return json .dumps (self .model , indent = 2 )
78
+
67
79
68
80
class NotebookSession : # (NamedTuple):
69
81
# id: str #'68d9c58f-c57d-4133-8b41-5ec2731b268d',
70
82
# path: str #'Untitled38.ipynb',
71
83
# name: str #'',
72
84
# type: str #'notebook',
73
85
# kernel: KernelInfo
74
- # notebook: dict # {'path': 'Untitled38.ipynb', 'name': ''}}}
86
+ # notebook: dict # deprecated API {'path': 'Untitled38.ipynb', 'name': ''}}}
75
87
76
88
def __init__ (self , * args , path , name , type , kernel , notebook , ** kwargs ):
89
+ self .model = {
90
+ "path" : path ,
91
+ "name" : name ,
92
+ "type" : type ,
93
+ "kernel" : kernel ,
94
+ "notebook" : notebook ,
95
+ }
77
96
self .path = path
78
97
self .name = name
79
98
self .type = type
80
99
self .kernel = KernelInfo (** kernel )
81
100
self .notebook = notebook
82
101
102
+ def __repr__ (self ):
103
+ return json .dumps (self .model , indent = 2 )
104
+
83
105
84
106
class NotebookClient :
107
+ """Client used to interact with bookstore from within a running notebook UI"""
108
+
85
109
def __init__ (self , nb_config ):
86
110
self .nb_config = nb_config
87
111
self .nb_record = LiveNotebookRecord (** self .nb_config )
@@ -110,7 +134,9 @@ def setup_request_sessions(self):
110
134
def sessions (self ):
111
135
"""Current notebook sessions. Reissues request on each call.
112
136
"""
113
- return {session ['kernel' ]['id' ]: session for session in self .get_sessions ()}
137
+ return {
138
+ session ['kernel' ]['id' ]: NotebookSession (** session ) for session in self .get_sessions ()
139
+ }
114
140
115
141
@property
116
142
def headers (self ):
@@ -139,10 +165,14 @@ def kernels_endpoint(self):
139
165
return f"{ self .url } { api_endpoint } "
140
166
141
167
def get_kernels (self ):
142
- target_url = f"{ self .sessions_endpoint } "
168
+ target_url = f"{ self .kernels_endpoint } "
143
169
resp = self .req_session .get (target_url )
144
170
return resp .json ()
145
171
172
+ @property
173
+ def kernels (self ):
174
+ return self .get_kernels ()
175
+
146
176
@property
147
177
def contents_endpoint (self ):
148
178
api_endpoint = "/api/contents/"
@@ -154,40 +184,38 @@ def get_contents(self, path):
154
184
return resp .json ()
155
185
156
186
157
- def python_compat_session (session ):
158
- deepcopy (session )
159
-
160
-
161
187
class NotebookClientCollection :
188
+ """Representation of a collection of notebook clients"""
189
+
190
+ # TODO: refactor from lambda to a def
162
191
nb_client_gen = lambda : (NotebookClient (x ) for x in list_running_servers ())
163
192
sessions = {x .url : x .sessions for x in nb_client_gen ()}
164
193
165
194
@classmethod
166
195
def current_server (cls ):
196
+ """class method for current notebook server"""
197
+
198
+ current_kernel_id = extract_kernel_id (get_ipython ().parent .parent .connection_file )
167
199
for server_url , session_dict in cls .sessions .items ():
168
200
for session_id , session in session_dict .items ():
169
- python_compat_session (session )
170
- if NotebookSession (** session ).kernel .id == extract_kernel_id (
171
- get_ipython ().parent .parent .connection_file
172
- ):
173
- # if session['kernel']['id'] == extract_kernel_id(get_ipython().parent.parent.connection_file):
174
-
201
+ if session .kernel .id == current_kernel_id :
175
202
return next (
176
203
client for client in cls .nb_client_gen () if client .url == server_url
177
204
)
178
205
179
206
180
207
class CurrentNotebookClient (NotebookClient ):
208
+ """Represents the currently active notebook client"""
209
+
181
210
def __init__ (self ):
182
211
self .nb_client = NotebookClientCollection .current_server ()
183
212
super ().__init__ (self .nb_client .nb_config )
184
213
self .session = self .sessions [self .kernel_id ]
185
- self .notebook = NotebookSession (** self .session ).notebook
186
214
187
215
@property
188
216
def connection_file (self ):
189
217
return get_ipython ().parent .parent .connection_file
190
218
191
219
@property
192
220
def kernel_id (self ):
193
- return os . path . basename (self .connection_file ). lstrip ( 'kernel-' ). rstrip ( '.json' )
221
+ return extract_kernel_id (self .connection_file )
0 commit comments