mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-11 12:30:25 +08:00
Merge branch 'main' into add_upload_study_artifact_api
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
name: e2e-tests
|
||||
name: e2e-dashboard-tests
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '.github/workflows/e2e-tests.yml'
|
||||
- '.github/workflows/e2e-dashboard-tests.yml'
|
||||
- '**.py'
|
||||
- '**.ts'
|
||||
- '**.tsx'
|
||||
@@ -47,4 +47,4 @@ jobs:
|
||||
run: playwright install
|
||||
|
||||
- name: Run e2e tests
|
||||
run: pytest e2e_tests
|
||||
run: pytest e2e_tests/test_dashboard
|
||||
@@ -0,0 +1,51 @@
|
||||
name: e2e-standalone-tests
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '.github/workflows/e2e-standalone-tests.yml'
|
||||
- '**.py'
|
||||
- '**.ts'
|
||||
- '**.tsx'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- 'tsconfig.json'
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
optuna-version: ['optuna==2.10.0', 'git+https://github.com/optuna/optuna.git']
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Rust toolchains
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
- name: Setup Optuna ${{ matrix.optuna-version }}
|
||||
run: |
|
||||
python -m pip install --progress-bar off --upgrade pip setuptools
|
||||
python -m pip install --progress-bar off --upgrade ${{ matrix.optuna-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --progress-bar off .
|
||||
python -m pip install --progress-bar off pytest-playwright
|
||||
|
||||
- name: Build standalone_app
|
||||
run: make MODE="prd" standalone_app/public/bundle.js
|
||||
|
||||
- name: Install the required browsers
|
||||
run: playwright install
|
||||
|
||||
- name: Run e2e tests
|
||||
run: pytest e2e_tests/test_standalone
|
||||
@@ -6,6 +6,7 @@ on:
|
||||
paths:
|
||||
- '.github/workflows/python-tests.yml'
|
||||
- '**.py'
|
||||
- 'pyproject.toml'
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -77,6 +77,18 @@ $ docker run -it --rm -p 8080:8080 ghcr.io/optuna/optuna-dashboard postgresql+ps
|
||||
|
||||
</details>
|
||||
|
||||
## Jupyter Lab Extension (Experimental)
|
||||
|
||||
You can install the Jupyter Lab extension via [PyPI](https://pypi.org/project/jupyterlab-optuna/).
|
||||
|
||||
```
|
||||
$ pip install jupyterlab jupyterlab-optuna
|
||||
```
|
||||
|
||||
<img src="./docs/_static/jupyterlab-extension.png" style="width:600px;" alt="Jupyter Lab Extension">
|
||||
|
||||
To use, click the tile to launch the extension, and enter your Optuna’s storage URL (e.g. `sqlite:///db.sqlite3`) in the dialog.
|
||||
|
||||
## Browser-only version (Experimental)
|
||||
|
||||
<img src="./docs/_static/browser-app.gif" style="width:600px;" alt="Browser-only version">
|
||||
@@ -93,7 +105,7 @@ https://optuna.github.io/optuna-dashboard/
|
||||
|
||||
You can install the VS Code extension via [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Optuna.optuna-dashboard#overview).
|
||||
|
||||
<img src="./docs/_static/vscode-extension.png" style="width:600px;" alt="VSCode Extension">
|
||||
<img src="./docs/_static/vscode-extension.png" style="width:600px;" alt="VS Code Extension">
|
||||
|
||||
Please right-click the SQLite3 files (`*.db` or `*.sqlite3`) in the VS Code file explorer and select the "Open in Optuna Dashboard" command from the dropdown menu.
|
||||
This extension leverages the browser-only version of Optuna Dashboard, so the same limitations apply.
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 244 KiB |
@@ -178,6 +178,19 @@ or
|
||||
$ pip install uwsgi
|
||||
$ uwsgi --http :8080 --workeers 4 --wsgi-file wsgi.py
|
||||
|
||||
Jupyter Lab Extension (Experimental)
|
||||
--------------------------------
|
||||
|
||||
You can install the Jupyter Lab extension via `PyPI <https://pypi.org/project/jupyterlab-optuna/>`_.
|
||||
|
||||
.. figure:: _static/jupyterlab-extension.png
|
||||
:alt: Screenshot for the Jupyter Lab Extension
|
||||
:align: center
|
||||
:width: 800px
|
||||
|
||||
Jupyter Lab Extension
|
||||
|
||||
To use, click the tile to launch the extension, and enter your Optuna’s storage URL (e.g. ``sqlite:///db.sqlite3``) in the dialog.
|
||||
|
||||
Browser-only version (Experimental)
|
||||
-----------------------------------
|
||||
|
||||
@@ -27,7 +27,7 @@ First, ensure the necessary packages are installed by executing the following co
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install "optuna>=3.3.0" "optuna-dashboard>=0.13.0b1" pillow botorch
|
||||
$ pip install "optuna>=3.3.0" "optuna-dashboard[preferential]>=0.13.0b1" pillow
|
||||
|
||||
Next, execute the Python script, copied from `generator.py`_.
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import optuna
|
||||
from playwright.sync_api import Page
|
||||
import pytest
|
||||
|
||||
from ..test_server import make_test_server
|
||||
from ...test_server import make_test_server
|
||||
|
||||
|
||||
def make_test_storage() -> optuna.storages.InMemoryStorage:
|
||||
+1
-1
@@ -4,7 +4,7 @@ import optuna
|
||||
from playwright.sync_api import Page
|
||||
import pytest
|
||||
|
||||
from .test_server import make_test_server
|
||||
from ..test_server import make_test_server
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -1,4 +1,6 @@
|
||||
import http.server
|
||||
import socket
|
||||
import socketserver
|
||||
import threading
|
||||
from wsgiref.simple_server import make_server
|
||||
|
||||
@@ -33,3 +35,29 @@ def make_test_server(
|
||||
request.addfinalizer(stop_server)
|
||||
|
||||
return f"http://{addr}:{port}/dashboard"
|
||||
|
||||
|
||||
def make_standalone_server(request: pytest.FixtureRequest) -> str:
|
||||
addr = "127.0.0.1"
|
||||
port = get_free_port()
|
||||
directory = "./standalone_app/"
|
||||
|
||||
Handler = http.server.SimpleHTTPRequestHandler
|
||||
httpd = socketserver.TCPServer(
|
||||
("", port), lambda *args, **kwargs: Handler(*args, directory=directory, **kwargs)
|
||||
)
|
||||
|
||||
def serve_httpd():
|
||||
httpd.serve_forever()
|
||||
|
||||
thread = threading.Thread(target=serve_httpd)
|
||||
thread.start()
|
||||
|
||||
def stop_server() -> None:
|
||||
httpd.shutdown()
|
||||
httpd.server_close()
|
||||
thread.join()
|
||||
|
||||
request.addfinalizer(stop_server)
|
||||
|
||||
return f"http://{addr}:{port}"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
from playwright.sync_api import Page
|
||||
import pytest
|
||||
|
||||
from ..test_server import make_standalone_server
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def server_url(request: pytest.FixtureRequest) -> str:
|
||||
return make_standalone_server(request)
|
||||
|
||||
|
||||
def test_home(
|
||||
page: Page,
|
||||
server_url: str,
|
||||
) -> None:
|
||||
url = f"{server_url}"
|
||||
page.goto(url)
|
||||
element = page.get_by_role("heading")
|
||||
assert element is not None
|
||||
title = element.text_content()
|
||||
assert title is not None
|
||||
assert title == "Optuna Dashboard (Wasm ver.)"
|
||||
@@ -17,4 +17,4 @@ from ._note import save_note # noqa
|
||||
from ._preference_setting import register_preference_feedback_component # noqa
|
||||
|
||||
|
||||
__version__ = "0.13.0b1"
|
||||
__version__ = "0.13.0"
|
||||
|
||||
@@ -7,9 +7,9 @@ from typing import Iterable
|
||||
|
||||
import optuna
|
||||
from optuna import logging
|
||||
from optuna._imports import try_import
|
||||
from optuna.distributions import BaseDistribution
|
||||
from optuna.samplers import BaseSampler
|
||||
from optuna.samplers import RandomSampler
|
||||
from optuna.trial import FrozenTrial
|
||||
from optuna.trial import TrialState
|
||||
from optuna_dashboard.preferential._system_attrs import get_n_generate
|
||||
@@ -20,6 +20,10 @@ from optuna_dashboard.preferential._system_attrs import report_preferences
|
||||
from optuna_dashboard.preferential._system_attrs import set_n_generate
|
||||
|
||||
|
||||
with try_import() as _imports:
|
||||
from optuna_dashboard.preferential.samplers.gp import PreferentialGPSampler
|
||||
|
||||
|
||||
_logger = logging.get_logger(__name__)
|
||||
_SYSTEM_ATTR_PREFERENTIAL_STUDY = "preference:is_preferential"
|
||||
|
||||
@@ -344,11 +348,10 @@ def create_study(
|
||||
|
||||
sampler:
|
||||
A sampler object that implements background algorithm for value suggestion.
|
||||
If :obj:`None` is specified, `RandomSampler`_ is used. Please note that
|
||||
most Optuna samplers does not work efficiently for preferential optimization.
|
||||
|
||||
.. _RandomSampler: https://optuna.readthedocs.io/en/stable/reference/\
|
||||
samplers/generated/optuna.samplers.RandomSampler.html
|
||||
If :obj:`None` is specified,
|
||||
:class:`~optuna_dashboard.preferential.samplers.gp.PreferentialGPSampler` is used.
|
||||
Please note that most Optuna samplers does not work efficiently for preferential
|
||||
optimization.
|
||||
|
||||
study_name:
|
||||
Study's name. If this argument is set to None, a unique name is generated
|
||||
@@ -369,9 +372,13 @@ def create_study(
|
||||
The interface may change in newer versions without prior notice.
|
||||
"""
|
||||
try:
|
||||
if sampler is None:
|
||||
_imports.check() # If BoTorch is not installed, raise ImportError.
|
||||
sampler = PreferentialGPSampler()
|
||||
|
||||
study = optuna.create_study(
|
||||
storage=storage,
|
||||
sampler=sampler or RandomSampler(),
|
||||
sampler=sampler,
|
||||
study_name=study_name,
|
||||
)
|
||||
study._storage.set_study_system_attr(
|
||||
@@ -441,11 +448,10 @@ def load_study(
|
||||
:func:`~optuna.study.create_study` for further details.
|
||||
sampler:
|
||||
A sampler object that implements background algorithm for value suggestion.
|
||||
If :obj:`None` is specified, `RandomSampler`_ is used. Please note that
|
||||
most Optuna samplers does not work efficiently for preferential optimization.
|
||||
|
||||
.. _RandomSampler: https://optuna.readthedocs.io/en/stable/reference/samplers/\
|
||||
generated/optuna.samplers.RandomSampler.html
|
||||
If :obj:`None` is specified,
|
||||
:class:`~optuna_dashboard.preferential.samplers.gp.PreferentialGPSampler` is used.
|
||||
Please note that most Optuna samplers does not work efficiently for preferential
|
||||
optimization.
|
||||
|
||||
Returns:
|
||||
A :class:`~optuna_dashboard.preferential.PreferentialStudy` object.
|
||||
@@ -454,9 +460,11 @@ def load_study(
|
||||
Preferential optimization is an experimental feature (introduced in v0.13.0).
|
||||
The interface may change in newer versions without prior notice.
|
||||
"""
|
||||
study = optuna.load_study(
|
||||
study_name=study_name, storage=storage, sampler=sampler or RandomSampler()
|
||||
)
|
||||
if sampler is None:
|
||||
_imports.check() # If BoTorch is not installed, raise ImportError.
|
||||
sampler = PreferentialGPSampler()
|
||||
|
||||
study = optuna.load_study(study_name=study_name, storage=storage, sampler=sampler)
|
||||
system_attrs = study._storage.get_study_system_attrs(study._study_id)
|
||||
if not system_attrs.get(_SYSTEM_ATTR_PREFERENTIAL_STUDY):
|
||||
raise ValueError("The study is not a PreferentialStudy.")
|
||||
|
||||
@@ -147,6 +147,16 @@ const CandidateTrial: FC<{
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: theme.spacing(2),
|
||||
right: theme.spacing(2),
|
||||
}}
|
||||
onClick={() => setDetailShown(false)}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
<TrialListDetail
|
||||
trial={trial}
|
||||
isBestTrial={() => false}
|
||||
|
||||
@@ -64,8 +64,7 @@ export const StudyList: FC<{
|
||||
return useMemo(() => new URLSearchParams(search), [search])
|
||||
}
|
||||
const query = useQuery()
|
||||
const initialSortBy =
|
||||
query.get("studies_order_by") === "desc" ? "desc" : "asc"
|
||||
const initialSortBy = query.get("studies_order_by") === "asc" ? "asc" : "desc"
|
||||
const [sortBy, setSortBy] = useState<"asc" | "desc">(initialSortBy)
|
||||
|
||||
let filteredStudies = studies.filter((s) => !studyFilter(s))
|
||||
|
||||
@@ -5,7 +5,9 @@ import { GizmoHelper, GizmoViewport, OrbitControls } from "@react-three/drei"
|
||||
import { STLLoader } from "three/examples/jsm/loaders/STLLoader"
|
||||
import { Rhino3dmLoader } from "three/examples/jsm/loaders/3DMLoader"
|
||||
import { PerspectiveCamera } from "three"
|
||||
import { Modal, Box } from "@mui/material"
|
||||
import { Modal, Box, useTheme } from "@mui/material"
|
||||
import ClearIcon from "@mui/icons-material/Clear"
|
||||
import IconButton from "@mui/material/IconButton"
|
||||
|
||||
export const isThreejsArtifact = (artifact: Artifact): boolean => {
|
||||
return (
|
||||
@@ -32,7 +34,7 @@ const CustomGizmoHelper: React.FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const calculateBoundingBox = (geometries: THREE.BufferGeometry[]) => {
|
||||
const computeBoundingBox = (geometries: THREE.BufferGeometry[]) => {
|
||||
const boundingBox = new THREE.Box3()
|
||||
geometries.forEach((geometry) => {
|
||||
const mesh = new THREE.Mesh(geometry)
|
||||
@@ -45,8 +47,11 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
|
||||
props
|
||||
) => {
|
||||
const [geometry, setGeometry] = useState<THREE.BufferGeometry[]>([])
|
||||
const [modelSize, setModelSize] = useState<THREE.Vector3>(
|
||||
new THREE.Vector3(10, 10, 10)
|
||||
const [boundingBox, setBoundingBox] = useState<THREE.Box3>(
|
||||
new THREE.Box3(
|
||||
new THREE.Vector3(-10, -10, -10),
|
||||
new THREE.Vector3(10, 10, 10)
|
||||
)
|
||||
)
|
||||
const [cameraSettings, setCameraSettings] = useState<PerspectiveCamera>(
|
||||
new THREE.PerspectiveCamera()
|
||||
@@ -54,11 +59,11 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
|
||||
|
||||
const handleLoadedGeometries = (geometries: THREE.BufferGeometry[]) => {
|
||||
setGeometry(geometries)
|
||||
const boundingBox = calculateBoundingBox(geometries)
|
||||
const boundingBox = computeBoundingBox(geometries)
|
||||
if (boundingBox !== null) {
|
||||
const size = boundingBox.getSize(new THREE.Vector3())
|
||||
setModelSize(size)
|
||||
setBoundingBox(boundingBox)
|
||||
}
|
||||
return boundingBox
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -81,20 +86,30 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
|
||||
}
|
||||
})
|
||||
}
|
||||
const maxModelSize = Math.max(modelSize.x, modelSize.y, modelSize.z)
|
||||
const cameraSet = new THREE.PerspectiveCamera(
|
||||
modelSize
|
||||
? Math.min(
|
||||
45,
|
||||
Math.atan(modelSize.y / modelSize.z) * (180 / Math.PI) * 2
|
||||
)
|
||||
: 45,
|
||||
window.innerWidth / window.innerHeight
|
||||
)
|
||||
cameraSet.position.set(maxModelSize * 2, maxModelSize * 2, maxModelSize * 2)
|
||||
setCameraSettings(cameraSet)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const cameraSet = new THREE.PerspectiveCamera(
|
||||
50,
|
||||
window.innerWidth / window.innerHeight,
|
||||
0.1,
|
||||
boundingBox.getSize(new THREE.Vector3()).length() * 100
|
||||
)
|
||||
const maxPosition = Math.max(
|
||||
boundingBox.max.x,
|
||||
boundingBox.max.y,
|
||||
boundingBox.max.z
|
||||
)
|
||||
cameraSet.position.set(
|
||||
maxPosition * 1.5,
|
||||
maxPosition * 1.5,
|
||||
maxPosition * 1.5
|
||||
)
|
||||
const center = boundingBox.getCenter(new THREE.Vector3())
|
||||
cameraSet.lookAt(center.x, center.y, center.z)
|
||||
setCameraSettings(cameraSet)
|
||||
}, [boundingBox])
|
||||
|
||||
return (
|
||||
<Canvas
|
||||
camera={cameraSettings}
|
||||
@@ -102,7 +117,7 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
|
||||
>
|
||||
<ambientLight />
|
||||
<OrbitControls />
|
||||
<gridHelper args={[Math.max(modelSize?.x, modelSize?.y) * 5]} />
|
||||
<gridHelper args={[Math.max(boundingBox.max.x, boundingBox.max.y) * 5]} />
|
||||
{props.hasGizmo && <CustomGizmoHelper />}
|
||||
<axesHelper />
|
||||
{geometry.length > 0 &&
|
||||
@@ -121,6 +136,7 @@ export const useThreejsArtifactModal = (): [
|
||||
] => {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [target, setTarget] = useState<[string, Artifact | null]>(["", null])
|
||||
const theme = useTheme()
|
||||
|
||||
const openModal = (artifactUrlPath: string, artifact: Artifact) => {
|
||||
setTarget([artifactUrlPath, artifact])
|
||||
@@ -146,6 +162,19 @@ export const useThreejsArtifactModal = (): [
|
||||
borderRadius: "15px",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: theme.spacing(2),
|
||||
right: theme.spacing(2),
|
||||
}}
|
||||
onClick={() => {
|
||||
setOpen(false)
|
||||
setTarget(["", null])
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
<ThreejsArtifactViewer
|
||||
src={target[0]}
|
||||
width={`${innerWidth * 0.8}px`}
|
||||
|
||||
Generated
+124
-120
@@ -75,11 +75,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
|
||||
"integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.18.6"
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"chalk": "^2.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -125,13 +126,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
|
||||
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.20.5",
|
||||
"@babel/types": "^7.23.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -250,9 +252,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-environment-visitor": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
|
||||
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
|
||||
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -271,25 +273,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-function-name": {
|
||||
"version": "7.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
|
||||
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.18.10",
|
||||
"@babel/types": "^7.19.0"
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/types": "^7.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-hoist-variables": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
|
||||
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
|
||||
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.18.6"
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -417,29 +419,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-split-export-declaration": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
|
||||
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.18.6"
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.19.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
|
||||
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
|
||||
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@@ -483,12 +485,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
|
||||
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
|
||||
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.18.6",
|
||||
"chalk": "^2.0.0",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"chalk": "^2.4.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -496,9 +498,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
|
||||
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -1657,33 +1659,33 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.18.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
||||
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
"@babel/parser": "^7.18.10",
|
||||
"@babel/types": "^7.18.10"
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
|
||||
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
"@babel/generator": "^7.20.5",
|
||||
"@babel/helper-environment-visitor": "^7.18.9",
|
||||
"@babel/helper-function-name": "^7.19.0",
|
||||
"@babel/helper-hoist-variables": "^7.18.6",
|
||||
"@babel/helper-split-export-declaration": "^7.18.6",
|
||||
"@babel/parser": "^7.20.5",
|
||||
"@babel/types": "^7.20.5",
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
@@ -1692,12 +1694,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
|
||||
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.19.4",
|
||||
"@babel/helper-validator-identifier": "^7.19.1",
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -15313,11 +15315,12 @@
|
||||
}
|
||||
},
|
||||
"@babel/code-frame": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
|
||||
"integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.18.6"
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"chalk": "^2.4.2"
|
||||
}
|
||||
},
|
||||
"@babel/compat-data": {
|
||||
@@ -15350,13 +15353,14 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
|
||||
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.20.5",
|
||||
"@babel/types": "^7.23.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -15444,9 +15448,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-environment-visitor": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
|
||||
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
|
||||
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/helper-explode-assignable-expression": {
|
||||
@@ -15459,22 +15463,22 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
|
||||
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/template": "^7.18.10",
|
||||
"@babel/types": "^7.19.0"
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/types": "^7.23.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-hoist-variables": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
|
||||
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
|
||||
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.18.6"
|
||||
"@babel/types": "^7.22.5"
|
||||
}
|
||||
},
|
||||
"@babel/helper-member-expression-to-functions": {
|
||||
@@ -15569,23 +15573,23 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-split-export-declaration": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
|
||||
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.18.6"
|
||||
"@babel/types": "^7.22.5"
|
||||
}
|
||||
},
|
||||
"@babel/helper-string-parser": {
|
||||
"version": "7.19.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
|
||||
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
|
||||
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
|
||||
},
|
||||
"@babel/helper-validator-option": {
|
||||
"version": "7.18.6",
|
||||
@@ -15617,19 +15621,19 @@
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
|
||||
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
|
||||
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
|
||||
"requires": {
|
||||
"@babel/helper-validator-identifier": "^7.18.6",
|
||||
"chalk": "^2.0.0",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"chalk": "^2.4.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
|
||||
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
|
||||
@@ -16401,41 +16405,41 @@
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.18.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
||||
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
"@babel/parser": "^7.18.10",
|
||||
"@babel/types": "^7.18.10"
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
|
||||
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
"@babel/generator": "^7.20.5",
|
||||
"@babel/helper-environment-visitor": "^7.18.9",
|
||||
"@babel/helper-function-name": "^7.19.0",
|
||||
"@babel/helper-hoist-variables": "^7.18.6",
|
||||
"@babel/helper-split-export-declaration": "^7.18.6",
|
||||
"@babel/parser": "^7.20.5",
|
||||
"@babel/types": "^7.20.5",
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
|
||||
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"requires": {
|
||||
"@babel/helper-string-parser": "^7.19.4",
|
||||
"@babel/helper-validator-identifier": "^7.19.1",
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
|
||||
+4
-1
@@ -52,9 +52,12 @@ test = [
|
||||
optional = [
|
||||
"streamlit",
|
||||
"boto3",
|
||||
"botorch",
|
||||
"botorch>=0.8.1; python_version>='3.8'",
|
||||
]
|
||||
|
||||
preferential = [
|
||||
"botorch>=0.8.1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
optuna-dashboard = "optuna_dashboard._cli:main"
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import copy
|
||||
import multiprocessing
|
||||
import pickle
|
||||
import sys
|
||||
from typing import Callable
|
||||
from unittest.mock import patch
|
||||
import uuid
|
||||
@@ -22,6 +23,10 @@ from ..storage_supplier import parametrize_storages
|
||||
from ..storage_supplier import StorageSupplier
|
||||
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
pytest.skip("BoTorch dropped Python3.7 support", allow_module_level=True)
|
||||
|
||||
|
||||
@parametrize_storages
|
||||
def test_study_set_and_get_user_attrs(storage_supplier: Callable[[], StorageSupplier]) -> None:
|
||||
with storage_supplier() as storage:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from unittest import TestCase
|
||||
|
||||
import optuna
|
||||
@@ -14,6 +15,7 @@ from optuna_dashboard._preferential_history import remove_history
|
||||
from optuna_dashboard._preferential_history import report_history
|
||||
from optuna_dashboard._serializer import serialize_preference_history
|
||||
from optuna_dashboard.preferential import create_study
|
||||
import pytest
|
||||
|
||||
from .wsgi_client import send_request
|
||||
|
||||
@@ -105,6 +107,7 @@ class APITestCase(TestCase):
|
||||
)
|
||||
self.assertEqual(status, 400)
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_get_best_trials_of_preferential_study(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(n_generate=4, storage=storage)
|
||||
@@ -128,6 +131,7 @@ class APITestCase(TestCase):
|
||||
assert len(best_trials) == 1
|
||||
assert best_trials[0]["number"] == 0
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_report_preference(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(n_generate=4, storage=storage)
|
||||
@@ -161,6 +165,7 @@ class APITestCase(TestCase):
|
||||
assert better.number == 2
|
||||
assert worse.number == 1
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_report_preference_when_typo_mode(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(storage=storage, n_generate=3)
|
||||
@@ -184,6 +189,7 @@ class APITestCase(TestCase):
|
||||
)
|
||||
self.assertEqual(status, 400)
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_change_component(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(storage=storage, n_generate=3)
|
||||
@@ -214,6 +220,7 @@ class APITestCase(TestCase):
|
||||
assert study_detail["feedback_component_type"]["output_type"] == "artifact"
|
||||
assert study_detail["feedback_component_type"]["artifact_key"] == "image"
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_skip_trial(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(n_generate=4, storage=storage)
|
||||
@@ -238,6 +245,7 @@ class APITestCase(TestCase):
|
||||
assert len(best_trials) == 1
|
||||
assert best_trials[0].number == 2
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_remove_history(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(storage=storage, n_generate=3)
|
||||
@@ -271,6 +279,7 @@ class APITestCase(TestCase):
|
||||
assert histories[0]["is_removed"]
|
||||
assert len(study.get_preferences()) == 0
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_restore_history(self) -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(storage=storage, n_generate=3)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from typing import Callable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
@@ -13,6 +14,7 @@ from optuna_dashboard._preferential_history import restore_history
|
||||
from optuna_dashboard._serializer import serialize_preference_history
|
||||
from optuna_dashboard.preferential import create_study
|
||||
from optuna_dashboard.preferential._system_attrs import _SYSTEM_ATTR_PREFIX_PREFERENCE
|
||||
import pytest
|
||||
|
||||
from .storage_supplier import parametrize_storages
|
||||
from .storage_supplier import StorageSupplier
|
||||
@@ -22,6 +24,10 @@ if TYPE_CHECKING:
|
||||
from optuna_dashboard._preferential_history import History
|
||||
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
pytest.skip("BoTorch dropped Python3.7 support", allow_module_level=True)
|
||||
|
||||
|
||||
@parametrize_storages
|
||||
def test_report_and_get_choices(storage_supplier: Callable[[], StorageSupplier]) -> None:
|
||||
with storage_supplier() as storage:
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import optuna
|
||||
from optuna_dashboard._serializer import serialize_attrs
|
||||
from optuna_dashboard._serializer import serialize_study_detail
|
||||
from optuna_dashboard._serializer import serialize_study_summary
|
||||
from optuna_dashboard._storage import get_study_summaries
|
||||
from optuna_dashboard.preferential import create_study
|
||||
import pytest
|
||||
|
||||
|
||||
def test_serialize_bytes() -> None:
|
||||
@@ -22,6 +25,7 @@ def test_serialize_dict() -> None:
|
||||
assert len(serialized) <= 1
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_get_study_detail_is_preferential() -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
study = create_study(n_generate=4, storage=storage)
|
||||
@@ -48,6 +52,7 @@ def test_get_study_detail_is_not_preferential() -> None:
|
||||
assert not study_detail["is_preferential"]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
|
||||
def test_get_study_summary_is_preferential() -> None:
|
||||
storage = optuna.storages.InMemoryStorage()
|
||||
create_study(n_generate=4, storage=storage)
|
||||
|
||||
+13
-8
@@ -1,16 +1,20 @@
|
||||
use fanova::{FanovaOptions, RandomForestOptions};
|
||||
use js_sys::Array;
|
||||
use serde_wasm_bindgen::from_value;
|
||||
use fanova::{FanovaOptions, RandomForestOptions};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Vec<f64> {
|
||||
// TODO(c-bata): Fix error handling
|
||||
pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Result<Vec<f64>, JsError> {
|
||||
let features_vec: Vec<Vec<f64>> = features
|
||||
.iter()
|
||||
.map(|x| from_value::<Vec<f64>>(x).unwrap())
|
||||
.collect();
|
||||
let targets_vec: Vec<f64> = targets.iter().map(|x| x.as_f64().unwrap()).collect();
|
||||
.map(|x| from_value::<Vec<f64>>(x))
|
||||
.collect::<Result<_, _>>()
|
||||
.map_err(|_| JsError::new("features must be of type number[][]"))?;
|
||||
let targets_vec: Vec<f64> = targets
|
||||
.iter()
|
||||
.map(|x| x.as_f64())
|
||||
.collect::<Option<_>>()
|
||||
.ok_or(JsError::new("targets must be of type number[]"))?;
|
||||
|
||||
let mut fanova = FanovaOptions::new()
|
||||
.random_forest(RandomForestOptions::new().seed(0))
|
||||
@@ -18,9 +22,10 @@ pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Vec<f64> {
|
||||
features_vec.iter().map(|x| x.as_slice()).collect(),
|
||||
&targets_vec,
|
||||
)
|
||||
.unwrap();
|
||||
.map_err(|e| JsError::new(&format!("failed to build fANOVA model: {}", e)))?;
|
||||
let importances = (0..features_vec.len())
|
||||
.map(|i| fanova.quantify_importance(&[i]).mean)
|
||||
.collect::<Vec<_>>();
|
||||
return importances;
|
||||
|
||||
Ok(importances)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export const PlotImportance: FC<{ study: Study }> = ({ study }) => {
|
||||
const values = filteredTrials.map(
|
||||
(t) => t.values?.[objectiveId] as number
|
||||
)
|
||||
// TODO: handle errors thrown by wasm_fanova_calculate
|
||||
const importance = wasm_fanova_calculate(features, values)
|
||||
return study.intersection_search_space.map((s, i) => ({
|
||||
name: s.name,
|
||||
|
||||
@@ -14,6 +14,10 @@ Nothing to configure.
|
||||
|
||||
## Release Notes
|
||||
|
||||
### 0.1.0
|
||||
|
||||
Added older database schemas support (Optuna 2.6.0 or later)
|
||||
|
||||
### 0.0.1
|
||||
|
||||
Initial Release
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"displayName": "Optuna Dashboard",
|
||||
"description": "Web Dashboard for Optuna",
|
||||
"publisher": "Optuna",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"icon": "images/optuna-logo.png",
|
||||
"engines": {
|
||||
|
||||
Reference in New Issue
Block a user