UNPKG

7.67 kBPlain TextView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3
4import {
5 Clipboard,
6 ISessionContext,
7 SessionContextDialogs
8} from '@jupyterlab/apputils';
9import { Cell, CodeCellModel } from '@jupyterlab/cells';
10import { CodeEditorWrapper, IEditorServices } from '@jupyterlab/codeeditor';
11import {
12 CodeMirrorEditorFactory,
13 CodeMirrorMimeTypeService,
14 EditorExtensionRegistry,
15 EditorLanguageRegistry,
16 ybinding
17} from '@jupyterlab/codemirror';
18import { Context, DocumentRegistry } from '@jupyterlab/docregistry';
19import { INotebookContent } from '@jupyterlab/nbformat';
20import { RenderMimeRegistry } from '@jupyterlab/rendermime';
21import {
22 DEFAULT_OUTPUTS as TEST_OUTPUTS,
23 defaultRenderMime as testRenderMime
24} from '@jupyterlab/rendermime/lib/testutils';
25import { ServiceManager } from '@jupyterlab/services';
26import { ServiceManagerMock } from '@jupyterlab/services/lib/testutils';
27import { UUID } from '@lumino/coreutils';
28import * as defaultContent from './default.json';
29import { INotebookModel, NotebookModel } from './model';
30import { NotebookModelFactory } from './modelfactory';
31import { NotebookPanel } from './panel';
32import { Notebook, StaticNotebook } from './widget';
33import { NotebookHistory } from './history';
34import { NotebookWidgetFactory } from './widgetfactory';
35
36export const DEFAULT_CONTENT: INotebookContent = defaultContent;
37
38/**
39 * Create and initialize context for a notebook.
40 */
41export async function initNotebookContext(
42 options: {
43 path?: string;
44 manager?: ServiceManager.IManager;
45 startKernel?: boolean;
46 } = {}
47): Promise<Context<INotebookModel>> {
48 const factory = Private.notebookFactory;
49 const manager = options.manager || Private.getManager();
50 const path = options.path || UUID.uuid4() + '.ipynb';
51 console.debug(
52 'Initializing notebook context for',
53 path,
54 'kernel:',
55 options.startKernel
56 );
57
58 const startKernel =
59 options.startKernel === undefined ? false : options.startKernel;
60 await manager.ready;
61
62 const context = new Context({
63 sessionDialogs: new SessionContextDialogs(),
64 manager,
65 factory,
66 path,
67 kernelPreference: {
68 shouldStart: startKernel,
69 canStart: startKernel,
70 shutdownOnDispose: true,
71 name: manager.kernelspecs.specs?.default
72 }
73 });
74 await context.initialize(true);
75
76 if (startKernel) {
77 await context.sessionContext.initialize();
78 await context.sessionContext.session?.kernel?.info;
79 }
80
81 return context;
82}
83
84/**
85 * The default notebook content.
86 */
87
88export namespace NBTestUtils {
89 export const DEFAULT_OUTPUTS = TEST_OUTPUTS;
90
91 export const defaultEditorConfig = { ...StaticNotebook.defaultEditorConfig };
92
93 const editorServices: IEditorServices = (function () {
94 const languages = new EditorLanguageRegistry();
95 EditorLanguageRegistry.getDefaultLanguages()
96 .filter(lang => ['Python'].includes(lang.name))
97 .forEach(lang => {
98 languages.addLanguage(lang);
99 });
100 const extensions = new EditorExtensionRegistry();
101 EditorExtensionRegistry.getDefaultExtensions()
102 .filter(ext => ['autoClosingBrackets'].includes(ext.name))
103 .forEach(ext => {
104 extensions.addExtension(ext);
105 });
106 extensions.addExtension({
107 name: 'binding',
108 factory: ({ model }) =>
109 EditorExtensionRegistry.createImmutableExtension(
110 ybinding({ ytext: (model.sharedModel as any).ysource })
111 )
112 });
113 const factoryService = new CodeMirrorEditorFactory({
114 languages,
115 extensions
116 });
117 const mimeTypeService = new CodeMirrorMimeTypeService(languages);
118 return {
119 factoryService,
120 mimeTypeService
121 };
122 })();
123
124 export const editorFactory =
125 editorServices.factoryService.newInlineEditor.bind(
126 editorServices.factoryService
127 );
128
129 export const mimeTypeService = editorServices.mimeTypeService;
130
131 /**
132 * Get a copy of the default rendermime instance.
133 */
134 export function defaultRenderMime(): RenderMimeRegistry {
135 return testRenderMime();
136 }
137
138 export const clipboard = Clipboard.getInstance();
139
140 /**
141 * Create a base cell content factory.
142 */
143 export function createBaseCellFactory(): Cell.IContentFactory {
144 return new Cell.ContentFactory({ editorFactory });
145 }
146
147 /**
148 * Create a new code cell content factory.
149 */
150 export function createCodeCellFactory(): Cell.IContentFactory {
151 return new Cell.ContentFactory({ editorFactory });
152 }
153
154 /**
155 * Create a cell editor widget.
156 */
157 export function createCellEditor(model?: CodeCellModel): CodeEditorWrapper {
158 return new CodeEditorWrapper({
159 model: model ?? new CodeCellModel(),
160 factory: editorFactory
161 });
162 }
163
164 /**
165 * Create a default notebook content factory.
166 */
167 export function createNotebookFactory(): Notebook.IContentFactory {
168 return new Notebook.ContentFactory({ editorFactory });
169 }
170
171 /**
172 * Create a default notebook panel content factory.
173 */
174 export function createNotebookPanelFactory(): NotebookPanel.IContentFactory {
175 return new NotebookPanel.ContentFactory({ editorFactory });
176 }
177
178 /**
179 * Create a notebook widget.
180 */
181 export function createNotebook(sessionContext?: ISessionContext): Notebook {
182 let history = sessionContext
183 ? {
184 kernelHistory: new NotebookHistory({ sessionContext: sessionContext })
185 }
186 : {};
187 return new Notebook({
188 rendermime: defaultRenderMime(),
189 contentFactory: createNotebookFactory(),
190 mimeTypeService,
191 notebookConfig: {
192 ...StaticNotebook.defaultNotebookConfig,
193 windowingMode: 'none'
194 },
195 ...history
196 });
197 }
198
199 /**
200 * Create a notebook panel widget.
201 */
202 export function createNotebookPanel(
203 context: Context<INotebookModel>
204 ): NotebookPanel {
205 return new NotebookPanel({
206 content: createNotebook(context.sessionContext),
207 context
208 });
209 }
210
211 /**
212 * Populate a notebook with default content.
213 */
214 export function populateNotebook(notebook: Notebook): void {
215 const model = new NotebookModel();
216 model.fromJSON(DEFAULT_CONTENT);
217 notebook.model = model;
218 }
219
220 export function createNotebookWidgetFactory(
221 toolbarFactory?: (widget: NotebookPanel) => DocumentRegistry.IToolbarItem[]
222 ): NotebookWidgetFactory {
223 return new NotebookWidgetFactory({
224 name: 'notebook',
225 fileTypes: ['notebook'],
226 rendermime: defaultRenderMime(),
227 toolbarFactory,
228 contentFactory: createNotebookPanelFactory(),
229 mimeTypeService: mimeTypeService,
230 editorConfig: defaultEditorConfig
231 });
232 }
233
234 /**
235 * Create a context for a file.
236 */
237 export async function createMockContext(
238 startKernel = false
239 ): Promise<Context<INotebookModel>> {
240 const path = UUID.uuid4() + '.txt';
241 const manager = new ServiceManagerMock();
242 const factory = new NotebookModelFactory({});
243
244 const context = new Context({
245 sessionDialogs: new SessionContextDialogs(),
246 manager,
247 factory,
248 path,
249 kernelPreference: {
250 shouldStart: startKernel,
251 canStart: startKernel,
252 autoStartDefault: startKernel
253 }
254 });
255 await context.initialize(true);
256 await context.sessionContext.initialize();
257 return context;
258 }
259}
260
261/**
262 * A namespace for private data.
263 */
264namespace Private {
265 let manager: ServiceManager;
266
267 export const notebookFactory = new NotebookModelFactory();
268
269 /**
270 * Get or create the service manager singleton.
271 */
272 export function getManager(): ServiceManager {
273 if (!manager) {
274 manager = new ServiceManager({ standby: 'never' });
275 }
276 return manager;
277 }
278}