Show More
@@ -47,26 +47,9 b' class NotebookManager(LoggingConfigurable):' | |||||
47 | def _notary_default(self): |
|
47 | def _notary_default(self): | |
48 | return sign.NotebookNotary(parent=self) |
|
48 | return sign.NotebookNotary(parent=self) | |
49 |
|
49 | |||
50 | def check_and_sign(self, nb, path, name): |
|
50 | # NotebookManager API part 1: methods that must be | |
51 | """Check for trusted cells, and sign the notebook. |
|
51 | # implemented in subclasses. | |
52 |
|
52 | |||
53 | Called as a part of saving notebooks. |
|
|||
54 | """ |
|
|||
55 | if self.notary.check_cells(nb): |
|
|||
56 | self.notary.sign(nb) |
|
|||
57 | else: |
|
|||
58 | self.log.warn("Saving untrusted notebook %s/%s", path, name) |
|
|||
59 |
|
||||
60 | def mark_trusted_cells(self, nb, path, name): |
|
|||
61 | """Mark cells as trusted if the notebook signature matches. |
|
|||
62 |
|
||||
63 | Called as a part of loading notebooks. |
|
|||
64 | """ |
|
|||
65 | trusted = self.notary.check_signature(nb) |
|
|||
66 | if not trusted: |
|
|||
67 | self.log.warn("Notebook %s/%s is not trusted", path, name) |
|
|||
68 | self.notary.mark_cells(nb, trusted) |
|
|||
69 |
|
||||
70 | def path_exists(self, path): |
|
53 | def path_exists(self, path): | |
71 | """Does the API-style path (directory) actually exist? |
|
54 | """Does the API-style path (directory) actually exist? | |
72 |
|
55 | |||
@@ -101,47 +84,6 b' class NotebookManager(LoggingConfigurable):' | |||||
101 | """ |
|
84 | """ | |
102 | raise NotImplementedError |
|
85 | raise NotImplementedError | |
103 |
|
86 | |||
104 | def _notebook_dir_changed(self, name, old, new): |
|
|||
105 | """Do a bit of validation of the notebook dir.""" |
|
|||
106 | if not os.path.isabs(new): |
|
|||
107 | # If we receive a non-absolute path, make it absolute. |
|
|||
108 | self.notebook_dir = os.path.abspath(new) |
|
|||
109 | return |
|
|||
110 | if os.path.exists(new) and not os.path.isdir(new): |
|
|||
111 | raise TraitError("notebook dir %r is not a directory" % new) |
|
|||
112 | if not os.path.exists(new): |
|
|||
113 | self.log.info("Creating notebook dir %s", new) |
|
|||
114 | try: |
|
|||
115 | os.mkdir(new) |
|
|||
116 | except: |
|
|||
117 | raise TraitError("Couldn't create notebook dir %r" % new) |
|
|||
118 |
|
||||
119 | # Main notebook API |
|
|||
120 |
|
||||
121 | def increment_filename(self, basename, path=''): |
|
|||
122 | """Increment a notebook filename without the .ipynb to make it unique. |
|
|||
123 |
|
||||
124 | Parameters |
|
|||
125 | ---------- |
|
|||
126 | basename : unicode |
|
|||
127 | The name of a notebook without the ``.ipynb`` file extension. |
|
|||
128 | path : unicode |
|
|||
129 | The URL path of the notebooks directory |
|
|||
130 |
|
||||
131 | Returns |
|
|||
132 | ------- |
|
|||
133 | name : unicode |
|
|||
134 | A notebook name (with the .ipynb extension) that starts |
|
|||
135 | with basename and does not refer to any existing notebook. |
|
|||
136 | """ |
|
|||
137 | path = path.strip('/') |
|
|||
138 | for i in itertools.count(): |
|
|||
139 | name = u'{basename}{i}{ext}'.format(basename=basename, i=i, |
|
|||
140 | ext=self.filename_ext) |
|
|||
141 | if not self.notebook_exists(name, path): |
|
|||
142 | break |
|
|||
143 | return name |
|
|||
144 |
|
||||
145 | def notebook_exists(self, name, path=''): |
|
87 | def notebook_exists(self, name, path=''): | |
146 | """Returns a True if the notebook exists. Else, returns False. |
|
88 | """Returns a True if the notebook exists. Else, returns False. | |
147 |
|
89 | |||
@@ -207,6 +149,55 b' class NotebookManager(LoggingConfigurable):' | |||||
207 | """Delete notebook by name and path.""" |
|
149 | """Delete notebook by name and path.""" | |
208 | raise NotImplementedError('must be implemented in a subclass') |
|
150 | raise NotImplementedError('must be implemented in a subclass') | |
209 |
|
151 | |||
|
152 | def create_checkpoint(self, name, path=''): | |||
|
153 | """Create a checkpoint of the current state of a notebook | |||
|
154 | ||||
|
155 | Returns a checkpoint_id for the new checkpoint. | |||
|
156 | """ | |||
|
157 | raise NotImplementedError("must be implemented in a subclass") | |||
|
158 | ||||
|
159 | def list_checkpoints(self, name, path=''): | |||
|
160 | """Return a list of checkpoints for a given notebook""" | |||
|
161 | return [] | |||
|
162 | ||||
|
163 | def restore_checkpoint(self, checkpoint_id, name, path=''): | |||
|
164 | """Restore a notebook from one of its checkpoints""" | |||
|
165 | raise NotImplementedError("must be implemented in a subclass") | |||
|
166 | ||||
|
167 | def delete_checkpoint(self, checkpoint_id, name, path=''): | |||
|
168 | """delete a checkpoint for a notebook""" | |||
|
169 | raise NotImplementedError("must be implemented in a subclass") | |||
|
170 | ||||
|
171 | def info_string(self): | |||
|
172 | return "Serving notebooks" | |||
|
173 | ||||
|
174 | # NotebookManager API part 2: methods that have useable default | |||
|
175 | # implementations, but can be overridden in subclasses. | |||
|
176 | ||||
|
177 | def increment_filename(self, basename, path=''): | |||
|
178 | """Increment a notebook filename without the .ipynb to make it unique. | |||
|
179 | ||||
|
180 | Parameters | |||
|
181 | ---------- | |||
|
182 | basename : unicode | |||
|
183 | The name of a notebook without the ``.ipynb`` file extension. | |||
|
184 | path : unicode | |||
|
185 | The URL path of the notebooks directory | |||
|
186 | ||||
|
187 | Returns | |||
|
188 | ------- | |||
|
189 | name : unicode | |||
|
190 | A notebook name (with the .ipynb extension) that starts | |||
|
191 | with basename and does not refer to any existing notebook. | |||
|
192 | """ | |||
|
193 | path = path.strip('/') | |||
|
194 | for i in itertools.count(): | |||
|
195 | name = u'{basename}{i}{ext}'.format(basename=basename, i=i, | |||
|
196 | ext=self.filename_ext) | |||
|
197 | if not self.notebook_exists(name, path): | |||
|
198 | break | |||
|
199 | return name | |||
|
200 | ||||
210 | def create_notebook(self, model=None, path=''): |
|
201 | def create_notebook(self, model=None, path=''): | |
211 | """Create a new notebook and return its model with no content.""" |
|
202 | """Create a new notebook and return its model with no content.""" | |
212 | path = path.strip('/') |
|
203 | path = path.strip('/') | |
@@ -236,29 +227,43 b' class NotebookManager(LoggingConfigurable):' | |||||
236 | model = self.save_notebook(model, to_name, path) |
|
227 | model = self.save_notebook(model, to_name, path) | |
237 | return model |
|
228 | return model | |
238 |
|
229 | |||
239 | # Checkpoint-related |
|
230 | def log_info(self): | |
240 |
|
231 | self.log.info(self.info_string()) | ||
241 | def create_checkpoint(self, name, path=''): |
|
232 | ||
242 | """Create a checkpoint of the current state of a notebook |
|
233 | # NotebookManager methods provided for use in subclasses. | |
|
234 | ||||
|
235 | def check_and_sign(self, nb, path, name): | |||
|
236 | """Check for trusted cells, and sign the notebook. | |||
243 |
|
237 | |||
244 | Returns a checkpoint_id for the new checkpoint. |
|
238 | Called as a part of saving notebooks. | |
245 | """ |
|
239 | """ | |
246 | raise NotImplementedError("must be implemented in a subclass") |
|
240 | if self.notary.check_cells(nb): | |
|
241 | self.notary.sign(nb) | |||
|
242 | else: | |||
|
243 | self.log.warn("Saving untrusted notebook %s/%s", path, name) | |||
247 |
|
244 | |||
248 |
def |
|
245 | def mark_trusted_cells(self, nb, path, name): | |
249 | """Return a list of checkpoints for a given notebook""" |
|
246 | """Mark cells as trusted if the notebook signature matches. | |
250 |
|
|
247 | ||
|
248 | Called as a part of loading notebooks. | |||
|
249 | """ | |||
|
250 | trusted = self.notary.check_signature(nb) | |||
|
251 | if not trusted: | |||
|
252 | self.log.warn("Notebook %s/%s is not trusted", path, name) | |||
|
253 | self.notary.mark_cells(nb, trusted) | |||
251 |
|
254 | |||
252 | def restore_checkpoint(self, checkpoint_id, name, path=''): |
|
255 | def _notebook_dir_changed(self, name, old, new): | |
253 | """Restore a notebook from one of its checkpoints""" |
|
256 | """Do a bit of validation of the notebook dir.""" | |
254 | raise NotImplementedError("must be implemented in a subclass") |
|
257 | if not os.path.isabs(new): | |
|
258 | # If we receive a non-absolute path, make it absolute. | |||
|
259 | self.notebook_dir = os.path.abspath(new) | |||
|
260 | return | |||
|
261 | if os.path.exists(new) and not os.path.isdir(new): | |||
|
262 | raise TraitError("notebook dir %r is not a directory" % new) | |||
|
263 | if not os.path.exists(new): | |||
|
264 | self.log.info("Creating notebook dir %s", new) | |||
|
265 | try: | |||
|
266 | os.mkdir(new) | |||
|
267 | except: | |||
|
268 | raise TraitError("Couldn't create notebook dir %r" % new) | |||
255 |
|
269 | |||
256 | def delete_checkpoint(self, checkpoint_id, name, path=''): |
|
|||
257 | """delete a checkpoint for a notebook""" |
|
|||
258 | raise NotImplementedError("must be implemented in a subclass") |
|
|||
259 |
|
||||
260 | def log_info(self): |
|
|||
261 | self.log.info(self.info_string()) |
|
|||
262 |
|
||||
263 | def info_string(self): |
|
|||
264 | return "Serving notebooks" |
|
General Comments 0
You need to be logged in to leave comments.
Login now