Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom env variables #2

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
be85760
Add custom env form
AnastasiaSliusar Jul 10, 2024
f57183e
Add link from jupyterlab to jupyterserver for passing custom env vari…
AnastasiaSliusar Jul 11, 2024
3226375
Update the dialog
AnastasiaSliusar Jul 18, 2024
775cd68
Fix a dialog
AnastasiaSliusar Jul 19, 2024
9a5339c
Update a dialog, add css styles, saving user selection into kernelpre…
AnastasiaSliusar Jul 23, 2024
3b070bf
Add context menu on Laucher
AnastasiaSliusar Jul 24, 2024
de1702e
Merge branch 'jupyterlab:main' into custom-env-variables
AnastasiaSliusar Jul 24, 2024
91fc3a0
Automatic application of license header
github-actions[bot] Jul 24, 2024
00009c7
Fix context menu on each kernel icon on Launcher
AnastasiaSliusar Jul 24, 2024
802924b
Merge branch 'custom-env-variables' of https://github.com/AnastasiaSl…
AnastasiaSliusar Jul 24, 2024
e8c6a88
Fixing context menu on Launcher
AnastasiaSliusar Jul 25, 2024
d63760d
Fix running a kernel with custom env variables
AnastasiaSliusar Jul 26, 2024
b21f63c
Resolving merge conflicts
AnastasiaSliusar Jul 29, 2024
2e88b88
Fix a kernel selection dialog
AnastasiaSliusar Jul 30, 2024
774dabd
Fix showing checkbox
AnastasiaSliusar Jul 31, 2024
feb48de
Add support of calling a dialog for custom env variables for console …
AnastasiaSliusar Jul 31, 2024
d9f7ec6
Format code
AnastasiaSliusar Aug 1, 2024
55e31e5
Fix condition of showing a part of dialog for setuping custom env var…
AnastasiaSliusar Aug 1, 2024
765a2c4
Change name of the flag
AnastasiaSliusar Aug 6, 2024
7b18f44
Add tests
AnastasiaSliusar Aug 9, 2024
651732d
Fix lint and a test
AnastasiaSliusar Aug 15, 2024
56c53b6
Resolve conflicts
AnastasiaSliusar Aug 16, 2024
d959874
Fix tests
AnastasiaSliusar Aug 19, 2024
ed2fed8
Fix tests and eslint
AnastasiaSliusar Aug 20, 2024
7c11957
Update Playwright Snapshots
github-actions[bot] Aug 20, 2024
d45d3d4
Merge remote-tracking branch 'upstream/main' into custom-env-variables
AnastasiaSliusar Aug 20, 2024
a9e9a0e
Merge branch 'custom-env-variables' of https://github.com/AnastasiaSl…
AnastasiaSliusar Aug 20, 2024
f991f2b
Rename parameter
AnastasiaSliusar Aug 29, 2024
05fa30b
resolve conflicts
AnastasiaSliusar Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,12 @@
"Enter"
]
},
{
"id": "console:setup-custom-env",
"label": "Launch kernel with custom env vars...",
"caption": "Launch kernel with custom env vars...",
"shortcuts": []
},
{
"id": "console:shutdown",
"label": "Shut Down",
Expand Down Expand Up @@ -980,6 +986,12 @@
"caption": "",
"shortcuts": []
},
{
"id": "filebrowser:toggle-single-click-navigation",
"label": "Enable Single Click Navigation",
"caption": "",
"shortcuts": []
},
{
"id": "filebrowser:toggle-sort-notebooks-first",
"label": "Sort Notebooks Above Files",
Expand Down Expand Up @@ -2031,6 +2043,12 @@
"caption": "",
"shortcuts": []
},
{
"id": "notebook:setup-custom-env",
"label": "Launch kernel with custom env vars...",
"caption": "Launch kernel with custom env vars...",
"shortcuts": []
},
{
"id": "notebook:show-all-cell-code",
"label": "Expand All Code",
Expand Down Expand Up @@ -2211,6 +2229,12 @@
"caption": "",
"shortcuts": []
},
{
"id": "running:kernel-shut-down-unused",
"label": "Shut Down Unused",
"caption": "",
"shortcuts": []
},
{
"id": "running:show-modal",
"label": "Search Tabs and Running Sessions",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 126 additions & 11 deletions packages/apputils/src/sessioncontext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import { IChangedArgs, PathExt } from '@jupyterlab/coreutils';
import { IChangedArgs, PageConfig, PathExt } from '@jupyterlab/coreutils';
import {
Kernel,
KernelMessage,
Expand All @@ -16,12 +16,18 @@ import {
TranslationBundle
} from '@jupyterlab/translation';
import { find } from '@lumino/algorithm';
import { JSONExt, PromiseDelegate, UUID } from '@lumino/coreutils';
import {
JSONExt,
PartialJSONObject,
PromiseDelegate,
UUID
} from '@lumino/coreutils';
import { IDisposable, IObservableDisposable } from '@lumino/disposable';
import { ISignal, Signal } from '@lumino/signaling';
import { Widget } from '@lumino/widgets';
import * as React from 'react';
import { Dialog, showDialog } from './dialog';
import { CustomEnvWidget } from '@jupyterlab/ui-components';

/**
* A context object to manage a widget's kernel session connection.
Expand Down Expand Up @@ -301,6 +307,11 @@ export namespace ISessionContext {
* Skip showing the kernel restart dialog if checked (default `false`).
*/
readonly skipKernelRestartDialog?: boolean;

/**
* Custom kernel variables
*/
customEnvVars?: undefined | PartialJSONObject;
}

export type KernelDisplayStatus =
Expand Down Expand Up @@ -710,6 +721,9 @@ export class SessionContext implements ISessionContext {
});
if (name) {
options = { name };
if (preference.customEnvVars) {
options.env = preference.customEnvVars;
}
}
}

Expand Down Expand Up @@ -767,7 +781,10 @@ export class SessionContext implements ISessionContext {
// and start its kernel first to ensure consistent
// ordering.
await this._initStarted.promise;
return this._changeKernel(options);
const test = this._changeKernel(options);
console.log('test');
console.dir(test);
return test;
}

/**
Expand Down Expand Up @@ -1407,14 +1424,23 @@ export class SessionContextDialogs implements ISessionContext.IDialogs {
return;
}

const model = result.value as Kernel.IModel;

if (model && sessionContext.kernelPreference?.customEnvVars) {
sessionContext.kernelPreference.customEnvVars = undefined;
}

if (model.env) {
sessionContext.kernelPreference.customEnvVars = model.env;
}

if (hasCheckbox && result.isChecked !== null) {
sessionContext.kernelPreference = {
...sessionContext.kernelPreference,
autoStartDefault: result.isChecked
};
}

const model = result.value;
if (model === null && !sessionContext.hasNoKernel) {
return sessionContext.shutdown();
}
Expand Down Expand Up @@ -1812,21 +1838,55 @@ namespace Private {
export const createKernelSelector = (
sessionContext: ISessionContext,
translator?: ITranslator
) =>
new KernelSelector({
node: createSelectorNode(sessionContext, translator)
});
) => new KernelSelector(sessionContext, translator);

/**
* A widget that provides a kernel selection.
*/
class KernelSelector extends Widget {
export class KernelSelector extends Widget {
sessionContext: ISessionContext;
translator: ITranslator | undefined;

constructor(sessionContext: ISessionContext, translator?: ITranslator) {
super({ node: createSelectorNode(sessionContext, translator) });
this.sessionContext = sessionContext;
this.translator = translator;
}
/**
* Get the value of the kernel selector widget.
*/
getValue(): Kernel.IModel {
const selector = this.node.querySelector('select') as HTMLSelectElement;
return JSON.parse(selector.value) as Kernel.IModel;
let kernelData = JSON.parse(selector.value) as Kernel.IModel;
let tmp = {} as PartialJSONObject;
const envVarsBlock = this.node.querySelector(
'div.jp-custom-env-vars-block'
);

if (envVarsBlock) {
let customEnvParameters = envVarsBlock.getAttribute(
'data-custom-env-vars'
);
if (customEnvParameters) {
let envParameters = JSON.parse(
customEnvParameters
) as PartialJSONObject;

for (let index in envParameters) {
let env = envParameters[index] as PartialJSONObject;
let envName: string =
env && typeof env.name === 'string' ? env.name : '';
let envValue: string =
env && typeof env.value === 'string' ? env.value : ('' as string);
if (envName && envValue) {
tmp[envName] = envValue;
}
}

kernelData['env'] = tmp;
}
}
return kernelData;
}
}

Expand All @@ -1853,25 +1913,80 @@ namespace Private {
sessionContext,
translator
);

const acceptKernelEnvVar =
PageConfig.getOption('accept_kernel_env_var') === 'true'
? true
: false;
const envVarsDiv = document.createElement('div');
envVarsDiv.setAttribute('class', 'jp-custom-env-vars-block');
envVarsDiv.setAttribute('data-custom-env-vars', '');

if (options.disabled) select.disabled = true;
for (const group of options.groups) {
const { label, options } = group;
const optgroup = document.createElement('optgroup');
optgroup.label = label;
for (const { selected, text, title, value } of options) {
const option = document.createElement('option');
if (selected) option.selected = true;
if (selected) {
option.selected = true;
let val = JSON.parse(value);
let id = val && val.id ? val.id : '';
if (acceptKernelEnvVar && !id) {
let defaultEnvValue = {};
envVarsDiv.innerHTML = '';
addEnvBlock(envVarsDiv, defaultEnvValue, translator);
}
}

if (title) option.title = title;
option.text = text;
option.value = value;
optgroup.appendChild(option);
}
select.appendChild(optgroup);
}

select.onchange = () => {
let kernelData = JSON.parse(select.value) as Kernel.IModel;
envVarsDiv.innerHTML = '';
body.setAttribute('data-custom-env-vars', '');
if (acceptKernelEnvVar && !kernelData.id) {
let defaultEnvValue = {};
addEnvBlock(envVarsDiv, defaultEnvValue, translator);
}
};
body.appendChild(select);
body.appendChild(envVarsDiv);
return body;
}

function addEnvBlock(
body: HTMLDivElement,
defaultEnvValues: PartialJSONObject,
translator?: ITranslator
) {
let envConfiguration: PartialJSONObject = {};
body.setAttribute('data-custom-env-vars', '');

let customEnvBlock = new CustomEnvWidget(
envConfiguration,
defaultEnvValues,
formData => {
envConfiguration = formData as PartialJSONObject;
body.setAttribute(
'data-custom-env-vars',
JSON.stringify(envConfiguration)
);
},
false,
translator
);

Widget.attach(customEnvBlock, body);
}

/**
* Get the default kernel name given select options.
*/
Expand Down
16 changes: 16 additions & 0 deletions packages/apputils/style/dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ button.jp-Dialog-close-button {
min-height: unset;
}

button.jp-Dialog-button.jp-mod-styled.js-custom-env {
margin-left: 5px;
margin-top: 5px;
}

.jp-Dialog-header {
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -151,3 +156,14 @@ button.jp-Dialog-close-button {
.jp-Dialog-button.jp-mod-styled:not(:last-child) {
margin-right: 12px;
}

.jp-Dialog-body .js-Dialog-form-custom-env span {
display: inline-block;
width: 40px;
margin-right: 10px;
}

.jp-Dialog-body .js-Dialog-form-custom-env input {
margin-top: 10px;
margin-bottom: 10px;
}
31 changes: 31 additions & 0 deletions packages/apputils/test/sessioncontext.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ describe('@jupyterlab/apputils', () => {
// eslint-disable-next-line camelcase
allow_external_kernels: true,
// eslint-disable-next-line camelcase
accept_kernel_env_var: true,
// eslint-disable-next-line camelcase
external_connection_dir: external
}
}
Expand Down Expand Up @@ -165,6 +167,25 @@ describe('@jupyterlab/apputils', () => {
});
});

describe('#kernelChanged with custom env variables', () => {
it('should be emitted when the kernel changes', async () => {
let called = false;
sessionContext.kernelChanged.connect(
(sender, { oldValue, newValue }) => {
if (oldValue !== null) {
return;
}
expect(sender).toBe(sessionContext);
expect(oldValue).toBeNull();
expect(newValue).toBe(sessionContext.session?.kernel || null);
called = true;
}
);
await sessionContext.initialize();
expect(called).toBe(true);
});
});

describe('#sessionChanged', () => {
it('should be emitted when the session changes', async () => {
let called = false;
Expand Down Expand Up @@ -477,6 +498,16 @@ describe('@jupyterlab/apputils', () => {
expect(kernel.name).toBe(name);
});

it('should change the current kernel and have custom_env_vars', async () => {
await sessionContext.initialize();

const name = sessionContext.session?.kernel?.name;
const id = sessionContext.session?.kernel?.id;
const env = { TEST_ENV_NAME: 'test_env_value' };
const kernel = (await sessionContext.changeKernel({ name, env }))!;
expect(kernel.id).not.toBe(id);
});

it('should still work if called before fully initialized', async () => {
const initPromise = sessionContext.initialize(); // Start but don't finish init.
const name = 'echo';
Expand Down
Loading
Loading