This commit is contained in:
liuzhe-lz 2021-07-23 11:32:12 +08:00 коммит произвёл GitHub
Родитель 9270f9b807
Коммит f27b874190
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 3240 добавлений и 1 удалений

1
dependencies/develop.txt поставляемый
Просмотреть файл

@ -10,3 +10,4 @@ pytest-cov
pytest-azurepipelines
coverage
ipython
jupyterlab

Просмотреть файл

@ -0,0 +1,4 @@
from . import proxy
load_jupyter_server_extension = proxy.setup
_load_jupyter_server_extension = proxy.setup

Просмотреть файл

@ -0,0 +1,30 @@
import json
from pathlib import Path
import shutil
from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
import nni_node
_backend_config_file = Path(jupyter_config_dir(), 'jupyter_server_config.d', 'nni.json')
_backend_config_content = {
'ServerApp': {
'jpserver_extensions': {
'nni.tools.jupyter_extension': True
}
}
}
_frontend_src = Path(nni_node.__path__[0], 'jupyter-extension')
_frontend_dst = Path(jupyter_data_dir(), 'labextensions', 'nni-jupyter-extension')
def install():
_backend_config_file.parent.mkdir(parents=True, exist_ok=True)
_backend_config_file.write_text(json.dumps(_backend_config_content))
_frontend_dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copytree(_frontend_src, _frontend_dst)
def uninstall():
_backend_config_file.unlink()
shutil.rmtree(_frontend_dst)

Просмотреть файл

@ -0,0 +1,43 @@
import json
from pathlib import Path
import requests
from tornado.web import RequestHandler
def setup(server):
base_url = server.web_app.settings['base_url']
url_pattern = base_url.rstrip('/') + '/nni/(.*)'
server.web_app.add_handlers('.*$', [(url_pattern, NniProxyHandler)])
class NniProxyHandler(RequestHandler):
def get(self, path):
ports = _get_experiment_ports()
if not ports:
self.set_status(404)
return
if path == 'index':
if len(ports) > 1: # if there is more than one running experiments, show experiment list
self.redirect('experiment')
else: # if there is only one running experiment, show that experiment
self.redirect('oview')
return
r = requests.get(f'http://localhost:{ports[0]}/{path}')
self.set_status(r.status_code)
for key, value in r.headers.items():
self.add_header(key, value)
self.finish(r.content)
# TODO: post, put, etc
def set_default_headers(self):
self.clear_header('Content-Type')
self.clear_header('Date')
def _get_experiment_ports():
experiment_list_path = Path.home() / 'nni-experiments/.experiment'
if not experiment_list_path.exists():
return None
experiments = json.load(open(experiment_list_path))
return [exp['port'] for exp in experiments.values() if exp['status'] != 'STOPPED']

Просмотреть файл

@ -6,6 +6,7 @@ import logging
import os
import pkg_resources
from colorama import init
import nni.tools.jupyter_extension.management as jupyter_management
from .common_utils import print_error
from .launcher import create_experiment, resume_experiment, view_experiment
from .updater import update_searchspace, update_concurrency, update_duration, update_trialnum, import_data
@ -278,6 +279,14 @@ def parse_args():
'the unit is second')
parser_top.set_defaults(func=monitor_experiment)
# jupyter-extension command
jupyter_parser = subparsers.add_parser('jupyter-extension', help='install or uninstall JupyterLab extension (internal preview)')
jupyter_subparsers = jupyter_parser.add_subparsers()
jupyter_install_parser = jupyter_subparsers.add_parser('install', help='install JupyterLab extension')
jupyter_install_parser.set_defaults(func=lambda _args: jupyter_management.install()) # TODO: prompt message
jupyter_uninstall_parser = jupyter_subparsers.add_parser('uninstall', help='uninstall JupyterLab extension')
jupyter_uninstall_parser.set_defaults(func=lambda _args: jupyter_management.uninstall())
args = parser.parse_args()
args.func(args)

Просмотреть файл

@ -47,4 +47,4 @@ ignore-patterns=test*
# List of members which are set dynamically and missed by pylint inference
generated-members=numpy.*,torch.*,tensorflow.*,pycuda.*,tensorrt.*
ignored-modules=tensorflow,_winapi,msvcrt,tensorrt,pycuda
ignored-modules=tensorflow,_winapi,msvcrt,tensorrt,pycuda,nni_node

Просмотреть файл

@ -153,6 +153,10 @@ def compile_ts():
_yarn('ts/nasui')
_yarn('ts/nasui', 'build')
_print('Building JupyterLab extension')
_yarn('ts/jupyter_extension')
_yarn('ts/jupyter_extension', 'build')
def symlink_nni_node():
"""
@ -172,6 +176,8 @@ def symlink_nni_node():
_symlink('ts/nasui/build', 'nni_node/nasui/build')
_symlink('ts/nasui/server.js', 'nni_node/nasui/server.js')
_symlink('ts/jupyter_extension/dist', 'nni_node/jupyter-extension')
def copy_nni_node(version):
"""
@ -205,6 +211,8 @@ def copy_nni_node(version):
shutil.copytree('ts/nasui/build', 'nni_node/nasui/build')
shutil.copyfile('ts/nasui/server.js', 'nni_node/nasui/server.js')
shutil.copytree('ts/jupyter_extension/dist', 'nni_node/jupyter-extension')
_yarn_env = dict(os.environ)
# `Path('nni_node').resolve()` does not work on Windows if the directory not exists

2
ts/jupyter_extension/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
/build
/nni

Просмотреть файл

@ -0,0 +1,20 @@
{
"name": "nni-jupyter-extension",
"version": "999.0.0-developing",
"license": "MIT",
"scripts": {
"build": "tsc && jupyter labextension build ."
},
"dependencies": {
"@jupyterlab/application": "^3.0.11",
"@jupyterlab/launcher": "^3.0.9"
},
"devDependencies": {
"@jupyterlab/builder": "^3.0.9"
},
"jupyterlab": {
"extension": true,
"outputDir": "dist"
},
"main": "build/index.js"
}

Просмотреть файл

@ -0,0 +1,55 @@
import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application';
import { ICommandPalette, IFrame } from '@jupyterlab/apputils';
import { PageConfig } from '@jupyterlab/coreutils';
import { ILauncher } from '@jupyterlab/launcher';
class NniWidget extends IFrame {
constructor() {
super({
sandbox: [
'allow-same-origin',
'allow-scripts',
]
});
this.url = PageConfig.getBaseUrl() + 'nni/index';
this.id = 'nni';
this.title.label = 'NNI';
this.title.closable = true;
}
}
async function activate(app: JupyterFrontEnd, palette: ICommandPalette, launcher: ILauncher | null) {
console.log('nni extension is activated');
const { commands, shell } = app;
const command = 'nni';
const category = 'Other';
commands.addCommand(command, {
label: 'NNI',
caption: 'NNI',
iconClass: (args) => (args.isPalette ? null : 'jp-Launcher-kernelIcon'),
execute: () => {
shell.add(new NniWidget(), 'main');
}
});
palette.addItem({ command, category });
if (launcher) {
launcher.add({
command,
category,
kernelIconUrl: '/nni/icon.png' // FIXME: this field only works for "Notebook" category
});
}
}
const extension: JupyterFrontEndPlugin<void> = {
id: 'nni',
autoStart: true,
optional: [ILauncher],
requires: [ICommandPalette],
activate,
};
export default extension;

Просмотреть файл

@ -0,0 +1,14 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"outDir": "build",
"rootDir": "src",
"target": "es2017"
},
"include": [
"src/*"
]
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу