diff --git a/.github/workflows/pip-compile.yml b/.github/workflows/pip-compile.yml index f14cd121d..03da8b6b9 100644 --- a/.github/workflows/pip-compile.yml +++ b/.github/workflows/pip-compile.yml @@ -91,7 +91,7 @@ jobs: run: | python3 -m tox run -e py311-linux-${{ matrix.architecture }}-${{ matrix.requirements }} - - name: run tox (MacOS, Python 3.11) + - name: run tox (macOS, Python 3.11) if: ${{ (matrix.os == 'macos-13' || matrix.os == 'macos-latest') && matrix.python-version == '3.11' }} run: | python3 -m tox run -e py311-macos-${{ matrix.architecture }}-${{ matrix.requirements }} diff --git a/.gitignore b/.gitignore index 859ea84c4..73c06ab91 100644 --- a/.gitignore +++ b/.gitignore @@ -398,7 +398,6 @@ vignettes/*.pdf # Javascript node_modules/ -package-lock.json # --------------------------- # BEGIN Whitelisted Files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbe322faa..0e7bae323 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,7 @@ See the [Dioptra Commit Style Guide](./COMMIT_STYLE_GUIDE.md). #### Squashing -All final commits will be squashed, therefore when squashing your branch, it’s important to make sure you update the commit message. If you’re using Github’s UI it will by default create a new commit message which is a combination of all commits and **does not follow the commit guidelines**. +All final commits will be squashed, therefore when squashing your branch, it’s important to make sure you update the commit message. If you’re using GitHub’s UI it will by default create a new commit message which is a combination of all commits and **does not follow the commit guidelines**. If you’re working locally, it often can be useful to `--amend` a commit, or utilize `rebase -i` to reorder, squash, and reword your commits. diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f2fde6018..a9019bd11 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -18,3 +18,4 @@ lbarbMITRE cminiter pscemama-mitre alexb1200 +jsoref diff --git a/DEVELOPER.md b/DEVELOPER.md index 23acd1b54..24913853d 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -2,7 +2,7 @@ If you have not already, please review [CONTRIBUTING.md](CONTRIBUTING.md) for more complete information on expectations for contributions. -## Developer quickstart +## Developer Set-up ### Setting up the Python virtual environment @@ -17,12 +17,12 @@ Ensure that you have Python 3.11 installed and that it is available in your PATH | linux-arm64-py3.11-requirements-dev.txt | Linux | arm64 | ❌ | ❌ | | linux-arm64-py3.11-requirements-dev-tensorflow.txt | Linux | arm64 | ✅ | ❌ | | linux-arm64-py3.11-requirements-dev-pytorch.txt | Linux | arm64 | ❌ | ✅ | -| macos-amd64-py3.11-requirements-dev.txt | MacOS | x86-64 | ❌ | ❌ | -| macos-amd64-py3.11-requirements-dev-tensorflow.txt | MacOS | x86-64 | ✅ | ❌ | -| macos-amd64-py3.11-requirements-dev-pytorch.txt | MacOS | x86-64 | ❌ | ✅ | -| macos-arm64-py3.11-requirements-dev.txt | MacOS | arm64 | ❌ | ❌ | -| macos-arm64-py3.11-requirements-dev-tensorflow.txt | MacOS | arm64 | ✅ | ❌ | -| macos-arm64-py3.11-requirements-dev-pytorch.txt | MacOS | arm64 | ❌ | ✅ | +| macos-amd64-py3.11-requirements-dev.txt | macOS | x86-64 | ❌ | ❌ | +| macos-amd64-py3.11-requirements-dev-tensorflow.txt | macOS | x86-64 | ✅ | ❌ | +| macos-amd64-py3.11-requirements-dev-pytorch.txt | macOS | x86-64 | ❌ | ✅ | +| macos-arm64-py3.11-requirements-dev.txt | macOS | arm64 | ❌ | ❌ | +| macos-arm64-py3.11-requirements-dev-tensorflow.txt | macOS | arm64 | ✅ | ❌ | +| macos-arm64-py3.11-requirements-dev-pytorch.txt | macOS | arm64 | ❌ | ✅ | | win-amd64-py3.11-requirements-dev.txt | Windows | x86-64 | ❌ | ❌ | | win-amd64-py3.11-requirements-dev-tensorflow.txt | Windows | x86-64 | ✅ | ❌ | | win-amd64-py3.11-requirements-dev-pytorch.txt | Windows | x86-64 | ❌ | ✅ | @@ -34,7 +34,7 @@ python -m venv .venv ``` Activate the virtual environment after creating it. -To activate it on MacOS/Linux: +To activate it on macOS/Linux: ```sh source .venv/bin/activate @@ -53,7 +53,7 @@ python -m pip install --upgrade pip pip-tools ``` Finally, use `pip-sync` to install the dependencies in your chosen requirements file and install `dioptra` in development mode. -On MacOS/Linux: +On macOS/Linux: ```sh # Replace "linux-amd64-py3.11-requirements-dev.txt" with your chosen file @@ -70,9 +70,69 @@ pip-sync requirements\win-amd64-py3.11-requirements-dev.txt If the requirements file you used is updated, or if you want to switch to another requirements file (you need access to the Tensorflow library, for example), just run `pip-sync` again using the appropriate filename. It will install, upgrade, and uninstall all packages accordingly and ensure that you have a consistent environment. -### Frontend development setup - -For instructions on how to prepare the frontend development environment, [see the src/frontend/README.md file](src/frontend/README.md) +### Local Development setup (without containers) +- Clone the repository at https://github.com/usnistgov/dioptra: + ``` + git clone git@github.com:usnistgov/dioptra.git ~/dioptra/dev + ``` + or + ``` + git clone https://github.com/usnistgov/dioptra.git ~/dioptra/dev + ``` +- `cd ~dioptra/dev` +- `git checkout dev` +- [Install redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) +- Create a work directory for files `mkdir -p ~/dioptra/deployments/dev` +- [Create a python virtual environment](#setting-up-the-python-virtual-environment) + +- The following describes commands to execute in four different terminal windows: + 1. Flask Terminal + - Environment variables that must be set for flask: + ``` + DIOPTRA_RESTAPI_DEV_DATABASE_URI="sqlite:////home//dioptra/deployments/dev/dioptra-dev.db" + DIOPTRA_RESTAPI_ENV=dev + DIOPTRA_RESTAPI_VERSION=v1 + ``` + N.B.: replace with your username. On some systems the home path may also be different. Verify the expansion of '~' with the `pwd` command while in the appropriate directory. + + - Activate the python environment set-up in prior steps + - `dioptra-db autoupgrade` + - `flask run` + + 2. Frontend UI Terminal + - Commands to get a Frontend running: + ```bash + cd src/fronted + npm install + npm run dev + ``` + + 3. Redis Terminal + - `redis-server` + + 4. Dioptra Worker + - Starting a Dioptra Worker requires the following environment variables: + ``` + DIOPTRA_WORKER_USERNAME="dioptra-worker" # This must be a registered user in the Dioptra app + DIOPTRA_WORKER_PASSWORD="password" # Must match the username's password + DIOPTRA_API="http://localhost:5000" # This is the default API location when you run `flask run` + RQ_REDIS_URI="redis://localhost:6379/0" # This is the default URI when you run `redis-server` + MLFLOW_S3_ENDPOINT_URL="http://localhost:35000" # If you're running a MLflow Tracking server, update this to point at it. Otherwise, this is a placeholder. + OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES # Macs only, needed to make the RQ worker (i.e. the Dioptra Worker) work + ``` + - Activate the python environment set-up in prior steps (e.g. `source .venv/bin/activate`) + - With the prior environment variables set then execute the following commands: + ```bash + mkdir -p ~/dioptra/deployments/dev/workdir/ + cd ~/dioptra/deployments/dev/workdir/ + dioptra-worker-v1 'Tensorflow CPU' # Assumes 'Tensorflow CPU' is a registered Queue name + ``` +- Frontend app is available by default at http://localhost:5173 (the frontend terminal windows should also indicate the URL to use) +- Create Dioptra worker in the Frontend UI or through API. curl command for interacting with API (assuming you have the environment variables in Step iv set) is: + ``` + curl http://localhost:5000/api/v1/users/ -X POST --data-raw "{\"username\": \"$DIOPTRA_WORKER_USERNAME\", \"email\": \"dioptra-worker@localhost\", \"password\": \"$DIOPTRA_WORKER_PASSWORD\", \"confirmPassword\": \"$DIOPTRA_WORKER_PASSWORD\"}" + ``` +- Create 'Tensorflow CPU' Queue -- this needs to agree with the queue name used in Step iv. ### Building the documentation @@ -133,7 +193,7 @@ make code-check This project has a [commit style guide](./COMMIT_STYLE_GUIDE.md) that is enforced using the `gitlint` tool. Developers are expected to run `gitlint` and validate their commit message before opening a Pull Request. -After commiting your contribution, activate your virtual environment if you haven't already and run: +After committing your contribution, activate your virtual environment if you haven't already and run: ```sh python -m tox run -e gitlint diff --git a/Makefile b/Makefile index 11521c1c3..1b94a2d27 100644 --- a/Makefile +++ b/Makefile @@ -537,7 +537,7 @@ endif $(call save_sentinel_file,$@) ################################################################################# -# AUTO-GENERATED PROJECT BUILD RECEIPES # +# AUTO-GENERATED PROJECT BUILD RECIPES # ################################################################################# $(call generate_full_docker_image_recipe,MLFLOW_TRACKING,CONTAINER_IMAGE_TAG) diff --git a/README.md b/README.md index c2d02b6c3..3090ffe1c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Details are available in the project documentation available at `_ on your host machine (must meet all :ref:`quickstart-system-requirements`). - `Anaconda for Windows `_ - - `Anaconda for MacOS `_ + - `Anaconda for macOS `_ - `Anaconda for Linux `_ If your host machine does not meet the :ref:`quickstart-system-requirements`, then go to the `Anaconda Installation Documents `_ for more help. @@ -67,7 +67,7 @@ There are two install options to start using `Conda Environments `_ on your host machine (must meet all :ref:`quickstart-system-requirements`). - `Miniconda for Windows `_ - - `Miniconda for MacOS `_ + - `Miniconda for macOS `_ - `Miniconda for Linux `_ If your host machine does not meet the :ref:`quickstart-system-requirements`, then go to the `Miniconda Installation Documents `_ for more help. @@ -82,9 +82,9 @@ The minimum requirements for test-driving the Testbed architecture locally on yo - CPU: Intel or AMD-based x86-64 processor with 4+ physical cores at 1.90GHz or higher (recommended) - RAM: 16GB or higher (recommended) -- Operating System: Windows 10, MacOS 10.14 or newer, Linux (Ubuntu 20.04 LTS recommended) +- Operating System: Windows 10, macOS 10.14 or newer, Linux (Ubuntu 20.04 LTS recommended) - GNU/Linux-compatible environment, see :ref:`quickstart-gnu-linux-environment` -- Docker Desktop 3.1.0 or later (Windows/MacOS) +- Docker Desktop 3.1.0 or later (Windows/macOS) .. _quickstart-gnu-linux-environment: @@ -94,14 +94,14 @@ GNU/Linux Environments A host device that uses a GNU/Linux environment can be the following: - Most Linux distributions -- MacOS/OS X with Homebrew_ +- macOS/OS X with Homebrew_ - Windows with the `Windows Subsystem for Linux`_ - A virtual machine running a Linux distribution .. note:: Dioptra was developed for use with native GNU/Linux environments. - When using MacOS/OS X or Windows there is a chance you will encounter errors that are specific to your system's setup that are not covered in this documentation. + When using macOS/OS X or Windows there is a chance you will encounter errors that are specific to your system's setup that are not covered in this documentation. To resolve such issues, first look at the external documentation linked (i.e. Homebrew_ and `Windows Subsystem for Linux`_) before submitting a bug report. Also, when using a virtual machine it is likely the performance can be throttled because of the CPU and Memory allocations set at the time the virtual machine was configured. If performance becomes an issue when using a virtual machine, consider increasing the CPU and Memory resources allocated to the machine. @@ -121,7 +121,7 @@ To clone the repository, open a new **Terminal** session for your operating syst Use the keyboard shortcut :kbd:`ctrl` + :kbd:`alt` + :kbd:`t` to open the **Terminal**. - .. tab-item:: MacOS + .. tab-item:: macOS Use the keyboard shortcut :kbd:`command` + :kbd:`space` to open the **Spotlight Search**, type ``Terminal`` into the search bar, and click the *Terminal* application under *Top Hit* at the top of your results. @@ -138,10 +138,10 @@ Next, navigate to the directory where you will clone the repository, .. attention:: - Windows Subsystem for Linux (WSL) and MacOS users may encounter performance and file permission issues depending on the directory where the repository is cloned. + Windows Subsystem for Linux (WSL) and macOS users may encounter performance and file permission issues depending on the directory where the repository is cloned. This problem is due to the way that Docker is implemented on these operating systems. - For WSL users, these issues may occur if you clone the repository within any folder on the Windows filesystem under ``/mnt/c``, while for MacOS users it may occur if the repository is cloned within the ``Downloads`` or ``Documents`` directory. - For this reason, WSL and MacOS users are both encouraged to create and clone the repository into a projects directory in their home directory, + For WSL users, these issues may occur if you clone the repository within any folder on the Windows filesystem under ``/mnt/c``, while for macOS users it may occur if the repository is cloned within the ``Downloads`` or ``Documents`` directory. + For this reason, WSL and macOS users are both encouraged to create and clone the repository into a projects directory in their home directory, .. code-block:: sh diff --git a/docs/source/getting-started/running-dioptra.rst b/docs/source/getting-started/running-dioptra.rst index 5ba0ff438..5e252c950 100644 --- a/docs/source/getting-started/running-dioptra.rst +++ b/docs/source/getting-started/running-dioptra.rst @@ -66,7 +66,7 @@ Cruft will now run and prompt you to configure the deployment. See the :ref:`App We recommend identifying a location to store datasets you will want to use with Dioptra at this point and setting the ``datasets_directory`` variable accordingly. See the :ref:`Downloading the datasets ` section for more details. -Once you have configured your deployment, continue following the instructions for initialzing and starting your deployment below. +Once you have configured your deployment, continue following the instructions for initializing and starting your deployment below. .. code:: sh @@ -337,7 +337,7 @@ The following subsections explain how to: - Assign GPUs to specific worker containers - Integrate custom containers in the Dioptra deployment -In addition to the above, you may want to further customize the the Docker Compose configuration via the ``docker-compose.override.yml`` file to suit your needs, such as allocating explicit CPUs you want each container to use. +In addition to the above, you may want to further customize the Docker Compose configuration via the ``docker-compose.override.yml`` file to suit your needs, such as allocating explicit CPUs you want each container to use. An example template file (``docker-compose.override.yml.template``) is provided as part of the deployment as a starting point. This can be copied to ``docker-compose.override.yml`` and modified. See the `Compose specification documentation `__ for the full list of available options. diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst index 700c8f862..c335675c2 100644 --- a/docs/source/glossary.rst +++ b/docs/source/glossary.rst @@ -46,7 +46,7 @@ Glossary A copy of the paper is available on the arXiv at https://arxiv.org/abs/1511.07528. JSON - An acronym for the term *Javascript Object Notation*. + An acronym for the term *JavaScript Object Notation*. JSON is a lightweight data-interchange format that is completely language independent despite being based on a subset of the JavaScript Programming Language Standard ECMA-262 3rd Edition - December 1999. For more information, see https://www.json.org. diff --git a/docs/source/overview/executive-summary.rst b/docs/source/overview/executive-summary.rst index 06d8b7bb7..9e511aab7 100644 --- a/docs/source/overview/executive-summary.rst +++ b/docs/source/overview/executive-summary.rst @@ -171,7 +171,7 @@ The architecture is built entirely from open-source resources making it easy for Assumptions / System Requirements --------------------------------- -Most of the built-in demonstrations in the testbed assume the testbed is deployed on Unix-based operating systems (e.g., Linux, MacOS). +Most of the built-in demonstrations in the testbed assume the testbed is deployed on Unix-based operating systems (e.g., Linux, macOS). Those familiar with the Windows Subsystem for Linux (WSL) should be able to deploy it on Windows, but this mode is not explicitly supported at this time. Most included demos perform computationally intensive calculations requiring access to significant computational resources such as Graphics Processing Units (GPUs). The architecture has been tested on a :term:`NVIDIA DGX` server with 4 GPUs. diff --git a/docs/source/user-guide/custom-task-plugins.rst b/docs/source/user-guide/custom-task-plugins.rst index 48af670f2..d96547d1d 100644 --- a/docs/source/user-guide/custom-task-plugins.rst +++ b/docs/source/user-guide/custom-task-plugins.rst @@ -140,7 +140,7 @@ For local tasks we will use a different notation for both creating and invoking Creating a Local Task --------------------- -In general the major difference besides location of local task plugins is that the the `@task` decorator now replaces the `@pyplugs.register` decorator. +In general the major difference besides location of local task plugins is that the `@task` decorator now replaces the `@pyplugs.register` decorator. The task decorator is imported from the prefect library: .. code-block:: python diff --git a/docs/source/user-guide/entry-points.rst b/docs/source/user-guide/entry-points.rst index 0e6026d9b..8b7d1c8c4 100644 --- a/docs/source/user-guide/entry-points.rst +++ b/docs/source/user-guide/entry-points.rst @@ -143,7 +143,7 @@ uri Executable Script ----------------- -The entry point script, in principle, is just an executable Python script that accepts command-line options, so Testbed users can get started quickly by using their pre-existing Python scripts. +The entry point script, in principle, is just an executable Python script that accepts command-line options, so Testbed users can get started quickly by using their preexisting Python scripts. However, if users wish to make use of the Testbed's powerful job tracking and task plugin capabilities, they will need to adopt the Testbed's standard for writing entry point scripts outlined in this section. .. attention:: diff --git a/examples/DEPRECATED-tensorflow-imagenet-resnet50/src/gaussian_augmentation.py b/examples/DEPRECATED-tensorflow-imagenet-resnet50/src/gaussian_augmentation.py index 09865dd7b..48aa1e036 100644 --- a/examples/DEPRECATED-tensorflow-imagenet-resnet50/src/gaussian_augmentation.py +++ b/examples/DEPRECATED-tensorflow-imagenet-resnet50/src/gaussian_augmentation.py @@ -81,7 +81,7 @@ def _coerce_int_to_bool(ctx, param, value): @click.option( "--def-tar-name", type=click.STRING, - default="guassian_augmentation_dataset.tar.gz", + default="gaussian_augmentation_dataset.tar.gz", help="Name to give to tarfile artifact containing preprocessed images", ) @click.option( @@ -150,7 +150,7 @@ def _coerce_int_to_bool(ctx, param, value): help="Set the entry point rng seed", default=-1, ) -def guassian_augmentation( +def gaussian_augmentation( image_size, def_tar_name, def_data_dir, @@ -167,7 +167,7 @@ def guassian_augmentation( ): LOGGER.info( "Execute MLFlow entry point", - entry_point="guassian_augmentation", + entry_point="gaussian_augmentation", image_size=image_size, def_tar_name=def_tar_name, def_data_dir=def_data_dir, @@ -184,7 +184,7 @@ def guassian_augmentation( ) with mlflow.start_run() as active_run: # noqa: F841 - flow: Flow = init_guassian_augmentation_flow() + flow: Flow = init_gaussian_augmentation_flow() state = flow.run( parameters=dict( image_size=image_size, @@ -207,7 +207,7 @@ def guassian_augmentation( return state -def init_guassian_augmentation_flow() -> Flow: +def init_gaussian_augmentation_flow() -> Flow: with Flow("Fast Gradient Method") as flow: ( image_size, @@ -341,4 +341,4 @@ def init_guassian_augmentation_flow() -> Flow: configure_structlog() with plugin_dirs(), StdoutLogStream(as_json), StderrLogStream(as_json): - _ = guassian_augmentation() + _ = gaussian_augmentation() diff --git a/examples/scripts/venvs/examples-setup-requirements.txt b/examples/scripts/venvs/examples-setup-requirements.txt index 731844ff9..ad71fe5d1 100644 --- a/examples/scripts/venvs/examples-setup-requirements.txt +++ b/examples/scripts/venvs/examples-setup-requirements.txt @@ -6,9 +6,9 @@ ipython>=8.12.0,<=8.24.0 jupyter>=1.0.0 jupyterlab>=3.6.0,<=4.1.8 kaggle>=1.5.0,<=1.6.12 -mlflow-skinny<2,<=2.12.1 +mlflow-skinny>=2,<=2.12.1 numpy>=1.22.0,<2 Pillow>=9.2.0 requests>=2.25,<3 -rich>=13.3.0,13.7.1 -universal_pathlib>=0.0.23,0.2.2 +rich>=13.3.0,<=13.7.1 +universal_pathlib>=0.0.23,<=0.2.5 diff --git a/examples/task-plugins/dioptra_custom/feature_squeezing/cw_inf_plugin.py b/examples/task-plugins/dioptra_custom/feature_squeezing/cw_inf_plugin.py index 923d10355..5697aa722 100644 --- a/examples/task-plugins/dioptra_custom/feature_squeezing/cw_inf_plugin.py +++ b/examples/task-plugins/dioptra_custom/feature_squeezing/cw_inf_plugin.py @@ -97,7 +97,7 @@ def create_adversarial_cw_inf_dataset( color_mode=color_mode, class_mode=label_mode, batch_size=batch_size, - shuffle=True, # alse, + shuffle=True, # false, ) num_images = data_flow.n img_filenames = [Path(x) for x in data_flow.filenames] diff --git a/examples/task-plugins/dioptra_custom/feature_squeezing/cw_l2_plugin.py b/examples/task-plugins/dioptra_custom/feature_squeezing/cw_l2_plugin.py index d8a2d9a3a..a8986d439 100644 --- a/examples/task-plugins/dioptra_custom/feature_squeezing/cw_l2_plugin.py +++ b/examples/task-plugins/dioptra_custom/feature_squeezing/cw_l2_plugin.py @@ -102,7 +102,7 @@ def create_adversarial_cw_l2_dataset( color_mode=color_mode, class_mode=label_mode, batch_size=batch_size, - shuffle=True, # alse, + shuffle=True, # false, ) num_images = data_flow.n img_filenames = [Path(x) for x in data_flow.filenames] diff --git a/examples/task-plugins/dioptra_custom/feature_squeezing/jsma_plugin.py b/examples/task-plugins/dioptra_custom/feature_squeezing/jsma_plugin.py index bd8ab8709..bf9940943 100644 --- a/examples/task-plugins/dioptra_custom/feature_squeezing/jsma_plugin.py +++ b/examples/task-plugins/dioptra_custom/feature_squeezing/jsma_plugin.py @@ -93,7 +93,7 @@ def create_adversarial_jsma_dataset( color_mode=color_mode, class_mode=label_mode, batch_size=batch_size, - shuffle=True, # alse, + shuffle=True, # false, ) num_images = data_flow.n img_filenames = [Path(x) for x in data_flow.filenames] diff --git a/examples/task-plugins/dioptra_custom/feature_squeezing/squeeze_plugin.py b/examples/task-plugins/dioptra_custom/feature_squeezing/squeeze_plugin.py index 1b0b11536..f14e83b68 100644 --- a/examples/task-plugins/dioptra_custom/feature_squeezing/squeeze_plugin.py +++ b/examples/task-plugins/dioptra_custom/feature_squeezing/squeeze_plugin.py @@ -84,7 +84,7 @@ def feature_squeeze( run_id=run_id, ) - batch_size = 32 # There is currently a bug preventing batch size from getting passsed in correctly + batch_size = 32 # There is currently a bug preventing batch size from getting passed in correctly tensorflow_global_seed: int = rng.integers(low=0, high=2**31 - 1) dataset_seed: int = rng.integers(low=0, high=2**31 - 1) diff --git a/pyproject.toml b/pyproject.toml index 2f96f0c72..90b242f7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ build-backend = "setuptools.build_meta" [project] name = "dioptra" -version = "1.0.0" +version = "1.0.1" authors = [ { name="James Glasbrenner", email="jglasbrenner@mitre.org" }, { name="Harold Booth", email="harold.booth@nist.gov" }, @@ -193,7 +193,7 @@ exclude = ''' ''' [tool.bumpver] -current_version = "1.0.0" +current_version = "1.0.1" version_pattern = "MAJOR.MINOR.PATCH[-TAG]" commit_message = "release {old_version} → {new_version}" commit = true @@ -229,7 +229,7 @@ push = false [tool.commitizen] name = "cz_conventional_commits" -version = "1.0.0" +version = "1.0.1" changelog_file = "CHANGELOG.md" style = [ ["qmark", "fg:#ff9d00 bold"], diff --git a/requirements/linux-amd64-py3.11-requirements-dev-pytorch.txt b/requirements/linux-amd64-py3.11-requirements-dev-pytorch.txt index a8ff1ab3f..9c38a7245 100644 --- a/requirements/linux-amd64-py3.11-requirements-dev-pytorch.txt +++ b/requirements/linux-amd64-py3.11-requirements-dev-pytorch.txt @@ -10,25 +10,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -46,7 +46,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -56,7 +56,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -72,39 +72,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -114,15 +115,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -130,21 +131,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -154,9 +157,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -168,26 +171,25 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # torch # tox # triton # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -199,11 +201,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -225,17 +227,17 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # torch @@ -243,35 +245,37 @@ fsspec==2024.6.1 gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -279,12 +283,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -300,14 +304,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -348,17 +351,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -371,7 +373,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -385,9 +386,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -395,11 +397,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -409,21 +411,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -432,12 +434,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -449,15 +450,17 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) +mlflow-skinny==2.17.1 + # via mlflow mpmath==1.3.0 # via sympy -msgpack==1.0.8 +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -481,17 +484,17 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via # scikit-image # torch -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -507,9 +510,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -546,7 +547,7 @@ nvidia-cusparse-cu12==12.1.0.106 # torch nvidia-nccl-cu12==2.19.3 # via torch -nvidia-nvjitlink-cu12==12.5.82 +nvidia-nvjitlink-cu12==12.6.77 # via # nvidia-cusolver-cu12 # nvidia-cusparse-cu12 @@ -556,16 +557,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -582,17 +581,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -611,7 +609,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -623,7 +621,7 @@ pillow==10.4.0 # torchvision pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -635,21 +633,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -657,17 +657,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -685,23 +689,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -718,6 +721,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -736,16 +740,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -753,22 +754,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -781,12 +775,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -798,42 +793,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -843,7 +839,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -885,25 +880,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -911,20 +906,20 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) -sympy==1.13.1 +sympy==1.13.3 # via torch tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -936,17 +931,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -969,9 +964,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -992,29 +987,30 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole triton==2.2.0 # via torch -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy # torch -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1022,11 +1018,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1034,7 +1030,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1043,19 +1039,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/linux-amd64-py3.11-requirements-dev-tensorflow.txt b/requirements/linux-amd64-py3.11-requirements-dev-tensorflow.txt index 25ac59d0b..54d6e0650 100644 --- a/requirements/linux-amd64-py3.11-requirements-dev-tensorflow.txt +++ b/requirements/linux-amd64-py3.11-requirements-dev-tensorflow.txt @@ -11,25 +11,25 @@ absl-py==2.1.0 # keras # tensorboard # tensorflow -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -49,7 +49,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -59,7 +59,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -75,39 +75,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -117,15 +118,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -133,21 +134,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -157,9 +160,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -171,24 +174,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -200,11 +202,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -228,17 +230,17 @@ flask-sqlalchemy==3.1.1 # flask-migrate flatbuffers==24.3.25 # via tensorflow -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib @@ -247,43 +249,45 @@ gast==0.6.0 gitdb==4.0.11 # via gitpython gitpython==3.1.43 - # via mlflow + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk google-pasta==0.2.0 # via tensorflow -graphene==3.3 +graphene==3.4.1 # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via # tensorboard # tensorflow -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -h5py==3.11.0 +h5py==3.12.1 # via # keras # tensorflow -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -291,12 +295,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -312,14 +316,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -359,17 +362,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -382,7 +384,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -396,9 +397,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -406,13 +408,13 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -keras==3.4.1 +keras==3.6.0 # via tensorflow -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -424,21 +426,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -447,12 +449,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -468,13 +469,15 @@ ml-dtypes==0.3.2 # via # keras # tensorflow -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -500,15 +503,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -525,12 +528,9 @@ numpy==1.26.4 # mlflow # nrtk # opencv-python - # opt-einsum # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -546,20 +546,18 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk -opt-einsum==3.3.0 +opt-einsum==3.4.0 # via tensorflow -optree==0.12.1 +optree==0.13.0 # via keras overrides==7.7.0 # via jupyter-server @@ -577,18 +575,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx # tensorflow # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -607,7 +603,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -618,7 +614,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -630,22 +626,24 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==4.25.5 # via - # mlflow + # mlflow-skinny # tensorboard # tensorflow -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -653,17 +651,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -681,23 +683,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -714,6 +715,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -732,16 +734,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -749,22 +748,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -777,12 +769,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -795,44 +788,45 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via # dioptra (pyproject.toml) # keras -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -844,7 +838,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard # tensorflow @@ -887,25 +880,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -913,7 +906,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -934,7 +927,7 @@ tensorflow==2.16.1 # via -r requirements-dev-tensorflow.in tensorflow-io-gcs-filesystem==0.37.1 # via tensorflow -termcolor==2.4.0 +termcolor==2.5.0 # via tensorflow terminado==0.18.1 # via @@ -944,17 +937,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -968,9 +961,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -991,28 +984,29 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # optree # sqlalchemy # tensorflow -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1020,11 +1014,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1032,7 +1026,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1041,22 +1035,22 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # astunparse # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via # deprecated # tensorflow -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/linux-amd64-py3.11-requirements-dev.txt b/requirements/linux-amd64-py3.11-requirements-dev.txt index 9c695a7f5..3ebda4e3a 100644 --- a/requirements/linux-amd64-py3.11-requirements-dev.txt +++ b/requirements/linux-amd64-py3.11-requirements-dev.txt @@ -8,25 +8,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -44,7 +44,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -54,7 +54,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -70,39 +70,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -112,15 +113,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -128,21 +129,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -152,9 +155,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -166,24 +169,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -195,11 +197,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -221,52 +223,54 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -274,12 +278,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -295,14 +299,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -342,17 +345,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -365,7 +367,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -379,9 +380,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -389,11 +391,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -403,21 +405,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -426,12 +428,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -443,13 +444,15 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -473,15 +476,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -497,9 +500,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -514,16 +515,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -540,17 +539,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -569,7 +567,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -580,7 +578,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -592,21 +590,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -614,17 +614,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -642,23 +646,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -675,6 +678,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -693,16 +697,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -710,22 +711,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -738,12 +732,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -755,42 +750,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -800,7 +796,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -842,25 +837,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -868,7 +863,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -879,7 +874,7 @@ tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -891,17 +886,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -915,9 +910,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -938,26 +933,27 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -965,11 +961,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -977,7 +973,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -986,19 +982,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/linux-arm64-py3.11-requirements-dev-pytorch.txt b/requirements/linux-arm64-py3.11-requirements-dev-pytorch.txt index 7acf963fe..b81cf49e5 100644 --- a/requirements/linux-arm64-py3.11-requirements-dev-pytorch.txt +++ b/requirements/linux-arm64-py3.11-requirements-dev-pytorch.txt @@ -10,25 +10,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -46,7 +46,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -56,7 +56,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -72,39 +72,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.139 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.139 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.3.3 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -114,15 +115,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -130,31 +131,35 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==2.0.5 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.6.2 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 # via nbconvert deprecated==1.2.14 - # via opentelemetry-api -distlib==0.3.8 + # via + # opentelemetry-api + # opentelemetry-semantic-conventions +distlib==0.3.9 # via virtualenv -distributed==2024.6.2 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -166,25 +171,24 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # torch # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -196,11 +200,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -222,17 +226,17 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # torch @@ -240,35 +244,37 @@ fsspec==2024.6.1 gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.64.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -276,18 +282,18 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.1.0 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect iniconfig==2.0.0 # via pytest -injector==0.21.0 +injector==0.22.0 # via # dioptra # dioptra (pyproject.toml) @@ -297,14 +303,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -337,7 +342,7 @@ json5==0.9.25 # via jupyterlab-server jsonpointer==3.0.0 # via jsonschema -jsonschema[format-nongpl]==4.22.0 +jsonschema[format-nongpl]==4.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -345,17 +350,16 @@ jsonschema[format-nongpl]==4.22.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -368,12 +372,11 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab -jupyter-server==2.14.1 +jupyter-server==2.14.2 # via # jupyter-lsp # jupyterlab @@ -382,21 +385,22 @@ jupyter-server==2.14.1 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.3 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert -jupyterlab-server==2.27.2 +jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets -kaggle==1.6.14 +kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -406,21 +410,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -429,12 +433,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -446,15 +449,17 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.2 +mlflow==2.17.1 # via dioptra (pyproject.toml) +mlflow-skinny==2.17.1 + # via mlflow mpmath==1.3.0 # via sympy -msgpack==1.0.8 +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -478,17 +483,17 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via # scikit-image # torch -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.8.1 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -504,9 +509,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -522,16 +525,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.25.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.25.0 - # via mlflow -opentelemetry-semantic-conventions==0.46b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -548,17 +549,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -577,7 +577,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -589,7 +589,7 @@ pillow==10.4.0 # torchvision pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -601,39 +601,45 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.3 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via # pexpect # terminado -pure-eval==0.2.2 +pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -651,23 +657,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.2.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -684,6 +689,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -702,16 +708,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -719,22 +722,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -747,12 +743,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -764,42 +761,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.18.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.4 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -809,7 +807,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -851,46 +848,46 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra # dioptra (pyproject.toml) # flask-sqlalchemy # mlflow -sqlparse==0.5.0 - # via mlflow +sqlparse==0.5.1 + # via mlflow-skinny stack-data==0.6.3 # via ipython -structlog==24.2.0 +structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) -sympy==1.12.1 +sympy==1.13.3 # via torch tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -902,17 +899,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.2 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -935,9 +932,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -958,27 +955,28 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy # torch -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -986,11 +984,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -998,7 +996,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1007,19 +1005,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/linux-arm64-py3.11-requirements-dev-tensorflow.txt b/requirements/linux-arm64-py3.11-requirements-dev-tensorflow.txt index 0f7629c9f..d54c1295f 100644 --- a/requirements/linux-arm64-py3.11-requirements-dev-tensorflow.txt +++ b/requirements/linux-arm64-py3.11-requirements-dev-tensorflow.txt @@ -11,25 +11,25 @@ absl-py==2.1.0 # keras # tensorboard # tensorflow -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -49,7 +49,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -59,7 +59,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -75,39 +75,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.139 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.139 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.3.3 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -117,15 +118,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -133,31 +134,35 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==2.0.5 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.6.2 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 # via nbconvert deprecated==1.2.14 - # via opentelemetry-api -distlib==0.3.8 + # via + # opentelemetry-api + # opentelemetry-semantic-conventions +distlib==0.3.9 # via virtualenv -distributed==2024.6.2 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -169,24 +174,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -198,11 +202,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -226,17 +230,17 @@ flask-sqlalchemy==3.1.1 # flask-migrate flatbuffers==24.3.25 # via tensorflow -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib @@ -245,43 +249,45 @@ gast==0.6.0 gitdb==4.0.11 # via gitpython gitpython==3.1.43 - # via mlflow + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk google-pasta==0.2.0 # via tensorflow -graphene==3.3 +graphene==3.4.1 # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.64.1 +grpcio==1.67.0 # via # tensorboard # tensorflow -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -h5py==3.11.0 +h5py==3.12.1 # via # keras # tensorflow -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -289,18 +295,18 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.1.0 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect iniconfig==2.0.0 # via pytest -injector==0.21.0 +injector==0.22.0 # via # dioptra # dioptra (pyproject.toml) @@ -310,14 +316,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -349,7 +354,7 @@ json5==0.9.25 # via jupyterlab-server jsonpointer==3.0.0 # via jsonschema -jsonschema[format-nongpl]==4.22.0 +jsonschema[format-nongpl]==4.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -357,17 +362,16 @@ jsonschema[format-nongpl]==4.22.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -380,12 +384,11 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab -jupyter-server==2.14.1 +jupyter-server==2.14.2 # via # jupyter-lsp # jupyterlab @@ -394,23 +397,24 @@ jupyter-server==2.14.1 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.3 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert -jupyterlab-server==2.27.2 +jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets -kaggle==1.6.14 +kaggle==1.6.17 # via dioptra (pyproject.toml) -keras==3.4.1 +keras==3.6.0 # via tensorflow -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -422,21 +426,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -445,12 +449,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -466,13 +469,15 @@ ml-dtypes==0.3.2 # via # keras # tensorflow -mlflow==2.14.2 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -498,15 +503,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.8.1 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -523,12 +528,9 @@ numpy==1.26.4 # mlflow # nrtk # opencv-python - # opt-einsum # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -544,20 +546,18 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.25.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.25.0 - # via mlflow -opentelemetry-semantic-conventions==0.46b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk -opt-einsum==3.3.0 +opt-einsum==3.4.0 # via tensorflow -optree==0.12.0 +optree==0.13.0 # via keras overrides==7.7.0 # via jupyter-server @@ -575,18 +575,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx # tensorflow # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -605,7 +603,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -616,7 +614,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -628,40 +626,46 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.3 +propcache==0.2.0 + # via yarl +protobuf==4.25.5 # via - # mlflow + # mlflow-skinny # tensorboard # tensorflow -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via # pexpect # terminado -pure-eval==0.2.2 +pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -679,23 +683,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.2.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -712,6 +715,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -730,16 +734,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -747,22 +748,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -775,12 +769,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -793,44 +788,45 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via # dioptra (pyproject.toml) # keras -rpds-py==0.18.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.4 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -842,7 +838,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard # tensorflow @@ -885,36 +880,36 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra # dioptra (pyproject.toml) # flask-sqlalchemy # mlflow -sqlparse==0.5.0 - # via mlflow +sqlparse==0.5.1 + # via mlflow-skinny stack-data==0.6.3 # via ipython -structlog==24.2.0 +structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) @@ -932,7 +927,7 @@ tensorflow==2.16.1 # via -r requirements-dev-tensorflow.in tensorflow-io-gcs-filesystem==0.37.1 # via tensorflow -termcolor==2.4.0 +termcolor==2.5.0 # via tensorflow terminado==0.18.1 # via @@ -942,17 +937,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.2 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -966,9 +961,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -989,28 +984,29 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # optree # sqlalchemy # tensorflow -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1018,11 +1014,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1030,7 +1026,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1039,22 +1035,22 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # astunparse # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via # deprecated # tensorflow -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/linux-arm64-py3.11-requirements-dev.txt b/requirements/linux-arm64-py3.11-requirements-dev.txt index 916a96416..21f53a9ee 100644 --- a/requirements/linux-arm64-py3.11-requirements-dev.txt +++ b/requirements/linux-arm64-py3.11-requirements-dev.txt @@ -8,25 +8,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -44,7 +44,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -54,7 +54,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -70,39 +70,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.139 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.139 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.3.3 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -112,15 +113,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -128,31 +129,35 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==2.0.5 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.6.2 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 # via nbconvert deprecated==1.2.14 - # via opentelemetry-api -distlib==0.3.8 + # via + # opentelemetry-api + # opentelemetry-semantic-conventions +distlib==0.3.9 # via virtualenv -distributed==2024.6.2 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -164,24 +169,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -193,11 +197,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -219,52 +223,54 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.64.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -272,18 +278,18 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.1.0 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect iniconfig==2.0.0 # via pytest -injector==0.21.0 +injector==0.22.0 # via # dioptra # dioptra (pyproject.toml) @@ -293,14 +299,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -332,7 +337,7 @@ json5==0.9.25 # via jupyterlab-server jsonpointer==3.0.0 # via jsonschema -jsonschema[format-nongpl]==4.22.0 +jsonschema[format-nongpl]==4.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -340,17 +345,16 @@ jsonschema[format-nongpl]==4.22.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -363,12 +367,11 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab -jupyter-server==2.14.1 +jupyter-server==2.14.2 # via # jupyter-lsp # jupyterlab @@ -377,21 +380,22 @@ jupyter-server==2.14.1 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.3 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert -jupyterlab-server==2.27.2 +jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets -kaggle==1.6.14 +kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -401,21 +405,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -424,12 +428,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -441,13 +444,15 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.2 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -471,15 +476,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.8.1 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -495,9 +500,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -512,16 +515,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.25.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.25.0 - # via mlflow -opentelemetry-semantic-conventions==0.46b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -538,17 +539,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -567,7 +567,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -578,7 +578,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -590,39 +590,45 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.3 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via # pexpect # terminado -pure-eval==0.2.2 +pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -640,23 +646,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.2.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -673,6 +678,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -691,16 +697,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -708,22 +711,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -736,12 +732,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -753,42 +750,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.18.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.4 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -798,7 +796,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -840,36 +837,36 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra # dioptra (pyproject.toml) # flask-sqlalchemy # mlflow -sqlparse==0.5.0 - # via mlflow +sqlparse==0.5.1 + # via mlflow-skinny stack-data==0.6.3 # via ipython -structlog==24.2.0 +structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) @@ -877,7 +874,7 @@ tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -889,17 +886,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.2 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -913,9 +910,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -936,26 +933,27 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -963,11 +961,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -975,7 +973,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -984,19 +982,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-amd64-py3.11-requirements-dev-pytorch.txt b/requirements/macos-amd64-py3.11-requirements-dev-pytorch.txt index fd38faa33..9094657ff 100644 --- a/requirements/macos-amd64-py3.11-requirements-dev-pytorch.txt +++ b/requirements/macos-amd64-py3.11-requirements-dev-pytorch.txt @@ -10,25 +10,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -48,7 +48,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -58,7 +58,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -74,39 +74,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -116,15 +117,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -132,21 +133,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -156,9 +159,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -170,25 +173,24 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # torch # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -200,11 +202,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -226,17 +228,17 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # torch @@ -244,35 +246,37 @@ fsspec==2024.6.1 gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -280,12 +284,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -301,14 +305,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -349,17 +352,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -372,7 +374,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -386,9 +387,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -396,11 +398,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -410,21 +412,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -433,12 +435,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -450,15 +451,17 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) +mlflow-skinny==2.17.1 + # via mlflow mpmath==1.3.0 # via sympy -msgpack==1.0.8 +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -482,17 +485,17 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via # scikit-image # torch -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -508,9 +511,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -526,16 +527,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -552,17 +551,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -581,7 +579,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -593,7 +591,7 @@ pillow==10.4.0 # torchvision pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -605,21 +603,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -627,17 +627,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -655,23 +659,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -688,6 +691,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -706,16 +710,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -723,22 +724,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -751,12 +745,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -768,42 +763,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -813,7 +809,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -855,25 +850,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -881,20 +876,20 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) -sympy==1.13.1 +sympy==1.13.3 # via torch tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -906,17 +901,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -939,9 +934,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -962,27 +957,28 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy # torch -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -990,11 +986,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1002,7 +998,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1011,19 +1007,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-amd64-py3.11-requirements-dev-tensorflow.txt b/requirements/macos-amd64-py3.11-requirements-dev-tensorflow.txt index 3a9033379..ef49a6506 100644 --- a/requirements/macos-amd64-py3.11-requirements-dev-tensorflow.txt +++ b/requirements/macos-amd64-py3.11-requirements-dev-tensorflow.txt @@ -11,25 +11,25 @@ absl-py==2.1.0 # keras # tensorboard # tensorflow -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -51,7 +51,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -61,7 +61,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -77,39 +77,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -119,15 +120,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -135,21 +136,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -159,9 +162,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -173,24 +176,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -202,11 +204,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -230,17 +232,17 @@ flask-sqlalchemy==3.1.1 # flask-migrate flatbuffers==24.3.25 # via tensorflow -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib @@ -249,43 +251,45 @@ gast==0.6.0 gitdb==4.0.11 # via gitpython gitpython==3.1.43 - # via mlflow + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk google-pasta==0.2.0 # via tensorflow -graphene==3.3 +graphene==3.4.1 # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via # tensorboard # tensorflow -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -h5py==3.11.0 +h5py==3.12.1 # via # keras # tensorflow -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -293,12 +297,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -314,14 +318,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -361,17 +364,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -384,7 +386,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -398,9 +399,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -408,13 +410,13 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -keras==3.4.1 +keras==3.6.0 # via tensorflow -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -426,21 +428,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -449,12 +451,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -470,13 +471,15 @@ ml-dtypes==0.3.2 # via # keras # tensorflow -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -502,15 +505,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -527,12 +530,9 @@ numpy==1.26.4 # mlflow # nrtk # opencv-python - # opt-einsum # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -548,20 +548,18 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk -opt-einsum==3.3.0 +opt-einsum==3.4.0 # via tensorflow -optree==0.12.1 +optree==0.13.0 # via keras overrides==7.7.0 # via jupyter-server @@ -579,18 +577,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx # tensorflow # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -609,7 +605,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -620,7 +616,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -632,22 +628,24 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==4.25.5 # via - # mlflow + # mlflow-skinny # tensorboard # tensorflow -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -655,17 +653,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -683,23 +685,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -716,6 +717,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -734,16 +736,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -751,22 +750,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -779,12 +771,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -797,44 +790,45 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via # dioptra (pyproject.toml) # keras -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -846,7 +840,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard # tensorflow @@ -889,25 +882,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -915,7 +908,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -936,7 +929,7 @@ tensorflow==2.16.1 # via -r requirements-dev-tensorflow.in tensorflow-io-gcs-filesystem==0.37.1 # via tensorflow -termcolor==2.4.0 +termcolor==2.5.0 # via tensorflow terminado==0.18.1 # via @@ -946,17 +939,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -970,9 +963,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -993,28 +986,29 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # optree # sqlalchemy # tensorflow -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1022,11 +1016,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1034,7 +1028,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1043,22 +1037,22 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # astunparse # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via # deprecated # tensorflow -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-amd64-py3.11-requirements-dev.txt b/requirements/macos-amd64-py3.11-requirements-dev.txt index f571e7951..c976e4fc2 100644 --- a/requirements/macos-amd64-py3.11-requirements-dev.txt +++ b/requirements/macos-amd64-py3.11-requirements-dev.txt @@ -8,25 +8,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -46,7 +46,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -56,7 +56,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -72,39 +72,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -114,15 +115,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -130,21 +131,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -154,9 +157,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -168,24 +171,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -197,11 +199,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -223,52 +225,54 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -276,12 +280,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -297,14 +301,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -344,17 +347,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -367,7 +369,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -381,9 +382,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -391,11 +393,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -405,21 +407,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -428,12 +430,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -445,13 +446,15 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -475,15 +478,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -499,9 +502,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -516,16 +517,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -542,17 +541,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -571,7 +569,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -582,7 +580,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -594,21 +592,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -616,17 +616,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -644,23 +648,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -677,6 +680,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -695,16 +699,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -712,22 +713,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -740,12 +734,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -757,42 +752,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -802,7 +798,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -844,25 +839,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -870,7 +865,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -881,7 +876,7 @@ tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -893,17 +888,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -917,9 +912,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -940,26 +935,27 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -967,11 +963,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -979,7 +975,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -988,19 +984,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-arm64-py3.11-requirements-dev-pytorch.txt b/requirements/macos-arm64-py3.11-requirements-dev-pytorch.txt index 0ec708349..97c32ab11 100644 --- a/requirements/macos-arm64-py3.11-requirements-dev-pytorch.txt +++ b/requirements/macos-arm64-py3.11-requirements-dev-pytorch.txt @@ -10,25 +10,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -48,7 +48,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -58,7 +58,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -74,39 +74,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -116,15 +117,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -132,21 +133,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -156,9 +159,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -170,25 +173,24 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # torch # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -200,11 +202,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -226,17 +228,17 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # torch @@ -244,33 +246,35 @@ fsspec==2024.6.1 gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -278,12 +282,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -299,14 +303,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -347,17 +350,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -370,7 +372,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -384,9 +385,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -394,11 +396,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -408,21 +410,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -431,12 +433,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -448,15 +449,17 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) +mlflow-skinny==2.17.1 + # via mlflow mpmath==1.3.0 # via sympy -msgpack==1.0.8 +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -480,17 +483,17 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via # scikit-image # torch -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -506,9 +509,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -524,16 +525,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -550,17 +549,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -579,7 +577,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -591,7 +589,7 @@ pillow==10.4.0 # torchvision pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -603,21 +601,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -625,17 +625,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -653,23 +657,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -686,6 +689,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -704,16 +708,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -721,22 +722,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -749,12 +743,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -766,42 +761,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -811,7 +807,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -853,25 +848,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -879,20 +874,20 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) -sympy==1.13.1 +sympy==1.13.3 # via torch tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -904,17 +899,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -937,9 +932,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -960,27 +955,28 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy # torch -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -988,11 +984,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1000,7 +996,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1009,19 +1005,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-arm64-py3.11-requirements-dev-tensorflow.txt b/requirements/macos-arm64-py3.11-requirements-dev-tensorflow.txt index 5e26cf194..98d182808 100644 --- a/requirements/macos-arm64-py3.11-requirements-dev-tensorflow.txt +++ b/requirements/macos-arm64-py3.11-requirements-dev-tensorflow.txt @@ -11,25 +11,25 @@ absl-py==2.1.0 # keras # tensorboard # tensorflow -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -51,7 +51,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -61,7 +61,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -77,39 +77,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -119,15 +120,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -135,21 +136,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -159,9 +162,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -173,24 +176,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -202,11 +204,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -230,17 +232,17 @@ flask-sqlalchemy==3.1.1 # flask-migrate flatbuffers==24.3.25 # via tensorflow -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib @@ -249,41 +251,43 @@ gast==0.6.0 gitdb==4.0.11 # via gitpython gitpython==3.1.43 - # via mlflow + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk google-pasta==0.2.0 # via tensorflow -graphene==3.3 +graphene==3.4.1 # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -grpcio==1.65.1 +grpcio==1.67.0 # via # tensorboard # tensorflow -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -h5py==3.11.0 +h5py==3.12.1 # via # keras # tensorflow -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -291,12 +295,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -312,14 +316,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -359,17 +362,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -382,7 +384,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -396,9 +397,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -406,13 +408,13 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -keras==3.4.1 +keras==3.6.0 # via tensorflow -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -424,21 +426,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -447,12 +449,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -468,13 +469,15 @@ ml-dtypes==0.3.2 # via # keras # tensorflow -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -500,15 +503,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -525,12 +528,9 @@ numpy==1.26.4 # mlflow # nrtk # opencv-python - # opt-einsum # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -546,20 +546,18 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk -opt-einsum==3.3.0 +opt-einsum==3.4.0 # via tensorflow -optree==0.12.1 +optree==0.13.0 # via keras overrides==7.7.0 # via jupyter-server @@ -577,18 +575,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx # tensorflow # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -607,7 +603,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -618,7 +614,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -630,22 +626,24 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==4.25.5 # via - # mlflow + # mlflow-skinny # tensorboard # tensorflow -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -653,17 +651,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -681,23 +683,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -714,6 +715,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -732,16 +734,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -749,22 +748,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -777,12 +769,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -795,44 +788,45 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via # dioptra (pyproject.toml) # keras -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -844,7 +838,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard # tensorflow @@ -888,25 +881,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -914,7 +907,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -937,7 +930,7 @@ tensorflow-io-gcs-filesystem==0.37.1 # via tensorflow tensorflow-metal==1.1.0 ; sys_platform == "darwin" and (platform_machine == "aarch64" or platform_machine == "arm64") # via -r requirements-dev-tensorflow.in -termcolor==2.4.0 +termcolor==2.5.0 # via tensorflow terminado==0.18.1 # via @@ -947,17 +940,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -971,9 +964,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -994,28 +987,29 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # optree # sqlalchemy # tensorflow -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1023,11 +1017,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1035,7 +1029,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1044,23 +1038,23 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # astunparse # dioptra (pyproject.toml) # pip-tools # tensorflow-metal -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via # deprecated # tensorflow -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/macos-arm64-py3.11-requirements-dev.txt b/requirements/macos-arm64-py3.11-requirements-dev.txt index 901a9a48a..bd7b2752d 100644 --- a/requirements/macos-arm64-py3.11-requirements-dev.txt +++ b/requirements/macos-arm64-py3.11-requirements-dev.txt @@ -8,25 +8,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -46,7 +46,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -56,7 +56,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -72,39 +72,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -114,15 +115,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via tox @@ -130,21 +131,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -154,9 +157,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -168,24 +171,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -197,11 +199,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -223,50 +225,52 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard -gunicorn==22.0.0 +gunicorn==23.0.0 # via mlflow h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -274,12 +278,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -295,14 +299,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -342,17 +345,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -365,7 +367,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -379,9 +380,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -389,11 +391,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -403,21 +405,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -426,12 +428,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -443,13 +444,15 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -473,15 +476,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -497,9 +500,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -514,16 +515,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -540,17 +539,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -569,7 +567,7 @@ pendulum==3.0.0 # via prefect pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -580,7 +578,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -592,21 +590,23 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) ptyprocess==0.7.0 # via @@ -614,17 +614,21 @@ ptyprocess==0.7.0 # terminado pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -642,23 +646,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -675,6 +678,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -693,16 +697,13 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -710,22 +711,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -738,12 +732,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -755,42 +750,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -800,7 +796,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -842,25 +837,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -868,7 +863,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -879,7 +874,7 @@ tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -891,17 +886,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -915,9 +910,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -938,26 +933,27 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -965,11 +961,11 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -977,7 +973,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -986,19 +982,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/win-amd64-py3.11-requirements-dev-pytorch.txt b/requirements/win-amd64-py3.11-requirements-dev-pytorch.txt index 57742732f..2bb40e05f 100644 --- a/requirements/win-amd64-py3.11-requirements-dev-pytorch.txt +++ b/requirements/win-amd64-py3.11-requirements-dev-pytorch.txt @@ -10,25 +10,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -46,7 +46,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -56,7 +56,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -72,39 +72,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -114,15 +115,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via @@ -137,21 +138,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -161,9 +164,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -175,25 +178,24 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # torch # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -205,11 +207,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -231,17 +233,17 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # torch @@ -249,33 +251,35 @@ fsspec==2024.6.1 gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -283,12 +287,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -304,14 +308,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -352,17 +355,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -375,7 +377,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -389,9 +390,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -399,11 +401,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -413,21 +415,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -436,12 +438,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -453,15 +454,17 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) +mlflow-skinny==2.17.1 + # via mlflow mpmath==1.3.0 # via sympy -msgpack==1.0.8 +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -485,17 +488,17 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via # scikit-image # torch -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -511,9 +514,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -529,16 +530,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -554,17 +553,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -581,7 +579,7 @@ passlib==1.7.4 # dioptra (pyproject.toml) pendulum==3.0.0 # via prefect -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -593,7 +591,7 @@ pillow==10.4.0 # torchvision pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -605,35 +603,41 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -651,23 +655,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -684,6 +687,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -702,25 +706,22 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pywin32==306 +pywin32==308 # via # docker # jupyter-core -pywinpty==2.0.13 +pywinpty==2.0.14 # via # jupyter-server # jupyter-server-terminals # terminado -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -728,22 +729,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -756,12 +750,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -773,42 +768,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -818,7 +814,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -860,25 +855,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -886,20 +881,20 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 # via # dioptra # dioptra (pyproject.toml) -sympy==1.13.1 +sympy==1.13.3 # via torch tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -911,17 +906,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -944,9 +939,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -967,27 +962,28 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy # torch -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -995,13 +991,13 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox waitress==3.0.0 # via mlflow wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1009,7 +1005,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1018,19 +1014,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/win-amd64-py3.11-requirements-dev-tensorflow.txt b/requirements/win-amd64-py3.11-requirements-dev-tensorflow.txt index a535aad64..a72a85c6e 100644 --- a/requirements/win-amd64-py3.11-requirements-dev-tensorflow.txt +++ b/requirements/win-amd64-py3.11-requirements-dev-tensorflow.txt @@ -11,25 +11,25 @@ absl-py==2.1.0 # keras # tensorboard # tensorflow-intel -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -49,7 +49,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -59,7 +59,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -75,39 +75,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -117,15 +118,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via @@ -140,21 +141,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -164,9 +167,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -178,24 +181,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -207,11 +209,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -235,17 +237,17 @@ flask-sqlalchemy==3.1.1 # flask-migrate flatbuffers==24.3.25 # via tensorflow-intel -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib @@ -254,41 +256,43 @@ gast==0.6.0 gitdb==4.0.11 # via gitpython gitpython==3.1.43 - # via mlflow + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk google-pasta==0.2.0 # via tensorflow-intel -graphene==3.3 +graphene==3.4.1 # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via # tensorboard # tensorflow-intel h11==0.14.0 # via httpcore -h5py==3.11.0 +h5py==3.12.1 # via # keras # tensorflow-intel -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -296,12 +300,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -317,14 +321,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -364,17 +367,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -387,7 +389,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -401,9 +402,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -411,13 +413,13 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -keras==3.4.1 +keras==3.6.0 # via tensorflow-intel -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -429,21 +431,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -452,12 +454,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -473,13 +474,15 @@ ml-dtypes==0.3.2 # via # keras # tensorflow-intel -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -505,15 +508,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -530,12 +533,9 @@ numpy==1.26.4 # mlflow # nrtk # opencv-python - # opt-einsum # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -551,20 +551,18 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk -opt-einsum==3.3.0 +opt-einsum==3.4.0 # via tensorflow-intel -optree==0.12.1 +optree==0.13.0 # via keras overrides==7.7.0 # via jupyter-server @@ -581,18 +579,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx # tensorflow-intel # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -609,7 +605,7 @@ passlib==1.7.4 # dioptra (pyproject.toml) pendulum==3.0.0 # via prefect -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -620,7 +616,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -632,36 +628,42 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==4.25.5 # via - # mlflow + # mlflow-skinny # tensorboard # tensorflow-intel -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -679,23 +681,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -712,6 +713,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -730,25 +732,22 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pywin32==306 +pywin32==308 # via # docker # jupyter-core -pywinpty==2.0.13 +pywinpty==2.0.14 # via # jupyter-server # jupyter-server-terminals # terminado -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -756,22 +755,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -784,12 +776,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -802,44 +795,45 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via # dioptra (pyproject.toml) # keras -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -851,7 +845,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard # tensorflow-intel @@ -894,25 +887,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -920,7 +913,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -943,7 +936,7 @@ tensorflow-intel==2.16.1 # via tensorflow tensorflow-io-gcs-filesystem==0.31.0 # via tensorflow-intel -termcolor==2.4.0 +termcolor==2.5.0 # via tensorflow-intel terminado==0.18.1 # via @@ -953,17 +946,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -977,9 +970,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -1000,28 +993,29 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # optree # sqlalchemy # tensorflow-intel -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -1029,13 +1023,13 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox waitress==3.0.0 # via mlflow wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -1043,7 +1037,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -1052,22 +1046,22 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # astunparse # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via # deprecated # tensorflow-intel -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/win-amd64-py3.11-requirements-dev.txt b/requirements/win-amd64-py3.11-requirements-dev.txt index 825c29e04..372cad976 100644 --- a/requirements/win-amd64-py3.11-requirements-dev.txt +++ b/requirements/win-amd64-py3.11-requirements-dev.txt @@ -8,25 +8,25 @@ # via -r requirements-dev.in absl-py==2.1.0 # via tensorboard -adversarial-robustness-toolbox==1.18.1 +adversarial-robustness-toolbox==1.18.2 # via dioptra (pyproject.toml) -aiohttp==3.9.5 +aiohappyeyeballs==2.4.3 + # via aiohttp +aiohttp==3.10.10 # via dioptra (pyproject.toml) aiosignal==1.3.1 # via aiohttp alabaster==0.7.16 # via sphinx -alembic==1.13.2 +alembic==1.13.3 # via # dioptra # dioptra (pyproject.toml) # flask-migrate # mlflow aniso8601==9.0.1 - # via - # flask-restx - # graphene -anyio==4.4.0 + # via flask-restx +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -44,7 +44,7 @@ async-lru==2.0.4 # via jupyterlab async-timeout==4.0.3 # via dioptra (pyproject.toml) -attrs==23.2.0 +attrs==24.2.0 # via # aiohttp # cattrs @@ -54,7 +54,7 @@ attrs==23.2.0 # referencing autopep8==2.3.1 # via dioptra (pyproject.toml) -babel==2.15.0 +babel==2.16.0 # via # jupyterlab-server # sphinx @@ -70,39 +70,40 @@ bleach==6.1.0 # nbconvert blinker==1.8.2 # via flask -boto3==1.34.149 +boto3==1.35.50 # via # dioptra # dioptra (pyproject.toml) -botocore==1.34.149 +botocore==1.35.50 # via # boto3 # s3transfer -build==1.2.1 +build==1.2.2.post1 # via # dioptra (pyproject.toml) # pip-tools -cachetools==5.4.0 +cachetools==5.5.0 # via - # mlflow + # google-auth + # mlflow-skinny # tox -cattrs==23.2.3 +cattrs==24.1.2 # via # lsprotocol # pygls -certifi==2024.7.4 +certifi==2024.8.30 # via # httpcore # httpx # kaggle # requests -cffi==1.16.0 +cffi==1.17.1 # via argon2-cffi-bindings chardet==5.2.0 # via # binaryornot # tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests click==8.1.7 # via @@ -112,15 +113,15 @@ click==8.1.7 # dioptra (pyproject.toml) # distributed # flask - # mlflow + # mlflow-skinny # pip-tools # prefect # rq -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via # dask # distributed - # mlflow + # mlflow-skinny # prefect colorama==0.4.6 # via @@ -135,21 +136,23 @@ comm==0.2.2 # via # ipykernel # ipywidgets -contourpy==1.2.1 +contourpy==1.3.0 # via matplotlib cookiecutter==2.1.1 # via # dioptra (pyproject.toml) # pytest-cookies -croniter==3.0.1 +croniter==4.0.0 # via prefect cycler==0.12.1 # via matplotlib -dask==2024.7.1 +dask==2024.10.0 # via # distributed # prefect -debugpy==1.8.2 +databricks-sdk==0.36.0 + # via mlflow-skinny +debugpy==1.8.7 # via ipykernel decorator==5.1.1 # via ipython @@ -159,9 +162,9 @@ deprecated==1.2.14 # via # opentelemetry-api # opentelemetry-semantic-conventions -distlib==0.3.8 +distlib==0.3.9 # via virtualenv -distributed==2024.7.1 +distributed==2024.10.0 # via prefect docker==7.1.0 # via @@ -173,24 +176,23 @@ entrypoints==0.4 # via # dioptra # dioptra (pyproject.toml) - # mlflow -esbonio==0.16.4 +esbonio==0.16.5 # via dioptra (pyproject.toml) -executing==2.0.1 +executing==2.1.0 # via stack-data -faker==26.0.0 +faker==30.8.1 # via dioptra (pyproject.toml) fastjsonschema==2.20.0 # via nbformat -filelock==3.15.4 +filelock==3.16.1 # via # tox # virtualenv -flake8==7.1.0 +flake8==7.1.1 # via # dioptra (pyproject.toml) # flake8-bugbear -flake8-bugbear==24.4.26 +flake8-bugbear==24.8.19 # via dioptra (pyproject.toml) flask==3.0.3 # via @@ -202,11 +204,11 @@ flask==3.0.3 # flask-restx # flask-sqlalchemy # mlflow -flask-accepts==0.18.4 +flask-accepts==1.0.1 # via # dioptra # dioptra (pyproject.toml) -flask-cors==4.0.1 +flask-cors==5.0.0 # via # dioptra # dioptra (pyproject.toml) @@ -228,50 +230,52 @@ flask-sqlalchemy==3.1.1 # dioptra # dioptra (pyproject.toml) # flask-migrate -fonttools==4.53.1 +fonttools==4.54.1 # via matplotlib fqdn==1.5.1 # via jsonschema freezegun==1.5.1 # via dioptra (pyproject.toml) -frozenlist==1.4.1 +frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.6.1 +fsspec==2024.10.0 # via # dask # universal-pathlib gitdb==4.0.11 # via gitpython gitpython==3.1.43 + # via mlflow-skinny +google-auth==2.35.0 + # via databricks-sdk +graphene==3.4.1 # via mlflow -graphene==3.3 - # via mlflow -graphql-core==3.2.3 +graphql-core==3.2.5 # via # graphene # graphql-relay graphql-relay==3.2.0 # via graphene -greenlet==3.0.3 +greenlet==3.1.1 # via sqlalchemy -grpcio==1.65.1 +grpcio==1.67.0 # via tensorboard h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx -httpx==0.27.0 +httpx==0.27.2 # via jupyterlab -idna==3.7 +idna==3.10 # via # anyio # httpx # jsonschema # requests # yarl -imageio==2.34.2 +imageio==2.36.0 # via # imgaug # scikit-image @@ -279,12 +283,12 @@ imagesize==1.4.1 # via sphinx imgaug==0.4.0 # via dioptra (pyproject.toml) -importlib-metadata==7.2.1 +importlib-metadata==8.4.0 # via # dask - # mlflow + # mlflow-skinny # opentelemetry-api -importlib-resources==6.4.0 +importlib-resources==6.4.5 # via # flask-restx # prefect @@ -300,14 +304,13 @@ ipykernel==6.29.5 # jupyter # jupyter-console # jupyterlab - # qtconsole -ipython==8.26.0 +ipython==8.29.0 # via # dioptra (pyproject.toml) # ipykernel # ipywidgets # jupyter-console -ipywidgets==8.1.3 +ipywidgets==8.1.5 # via jupyter isoduration==20.11.0 # via jsonschema @@ -347,17 +350,16 @@ jsonschema[format-nongpl]==4.23.0 # jupyter-events # jupyterlab-server # nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema -jupyter==1.0.0 +jupyter==1.1.1 # via dioptra (pyproject.toml) -jupyter-client==8.6.2 +jupyter-client==8.6.3 # via # ipykernel # jupyter-console # jupyter-server # nbclient - # qtconsole jupyter-console==6.6.3 # via jupyter jupyter-core==5.7.2 @@ -370,7 +372,6 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat - # qtconsole jupyter-events==0.10.0 # via jupyter-server jupyter-lsp==2.2.5 @@ -384,9 +385,10 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.2.4 +jupyterlab==4.2.5 # via # dioptra (pyproject.toml) + # jupyter # notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -394,11 +396,11 @@ jupyterlab-server==2.27.3 # via # jupyterlab # notebook -jupyterlab-widgets==3.0.11 +jupyterlab-widgets==3.0.13 # via ipywidgets kaggle==1.6.17 # via dioptra (pyproject.toml) -kiwisolver==1.4.5 +kiwisolver==1.4.7 # via matplotlib lazy-loader==0.4 # via scikit-image @@ -408,21 +410,21 @@ locket==1.0.0 # partd lsprotocol==2023.0.1 # via pygls -mako==1.3.5 +mako==1.3.6 # via alembic -markdown==3.6 +markdown==3.7 # via # mlflow # tensorboard markdown-it-py==3.0.0 # via rich -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # mako # nbconvert # werkzeug -marshmallow==3.21.3 +marshmallow==3.23.0 # via # dioptra # dioptra (pyproject.toml) @@ -431,12 +433,11 @@ marshmallow==3.21.3 # prefect marshmallow-oneofschema==3.1.1 # via prefect -matplotlib==3.9.1 +matplotlib==3.9.2 # via # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # pycocotools matplotlib-inline==0.1.7 # via @@ -448,13 +449,15 @@ mdurl==0.1.2 # via markdown-it-py mistune==3.0.2 # via nbconvert -mlflow==2.14.3 +mlflow==2.17.1 # via dioptra (pyproject.toml) -msgpack==1.0.8 +mlflow-skinny==2.17.1 + # via mlflow +msgpack==1.1.0 # via # distributed # prefect -multidict==6.0.5 +multidict==6.1.0 # via # aiohttp # yarl @@ -478,15 +481,15 @@ nbformat==5.10.4 # nbconvert nest-asyncio==1.6.0 # via ipykernel -networkx==3.3 +networkx==3.4.2 # via scikit-image -notebook==7.2.1 +notebook==7.2.2 # via jupyter notebook-shim==0.2.4 # via # jupyterlab # notebook -nrtk==0.10.0 +nrtk==0.15.1 # via dioptra (pyproject.toml) numpy==1.26.4 # via @@ -502,9 +505,7 @@ numpy==1.26.4 # opencv-python # pandas # pyarrow - # pybsm # pycocotools - # pywavelets # scikit-image # scikit-learn # scipy @@ -519,16 +520,14 @@ opencv-python==4.10.0.84 # via # dioptra (pyproject.toml) # imgaug - # nrtk - # pybsm -opentelemetry-api==1.26.0 +opentelemetry-api==1.27.0 # via - # mlflow + # mlflow-skinny # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-sdk==1.26.0 - # via mlflow -opentelemetry-semantic-conventions==0.47b0 +opentelemetry-sdk==1.27.0 + # via mlflow-skinny +opentelemetry-semantic-conventions==0.48b0 # via opentelemetry-sdk overrides==7.7.0 # via jupyter-server @@ -544,17 +543,16 @@ packaging==24.1 # lazy-loader # marshmallow # matplotlib - # mlflow + # mlflow-skinny # nbconvert # prefect # pyproject-api # pytest - # qtconsole - # qtpy # scikit-image # sphinx + # tensorboard # tox -pandas==2.2.2 +pandas==2.2.3 # via # dioptra # dioptra (pyproject.toml) @@ -571,7 +569,7 @@ passlib==1.7.4 # dioptra (pyproject.toml) pendulum==3.0.0 # via prefect -pillow==10.4.0 +pillow==11.0.0 # via # dioptra (pyproject.toml) # imageio @@ -582,7 +580,7 @@ pillow==10.4.0 # smqtk-image-io pip-tools==7.4.1 # via dioptra (pyproject.toml) -platformdirs==4.2.2 +platformdirs==4.3.6 # via # esbonio # jupyter-core @@ -594,35 +592,41 @@ pluggy==1.5.0 # tox prefect==1.4.1 # via dioptra (pyproject.toml) -prometheus-client==0.20.0 +prometheus-client==0.21.0 # via jupyter-server -prompt-toolkit==3.0.47 +prompt-toolkit==3.0.48 # via # ipython # jupyter-console -protobuf==4.25.4 +propcache==0.2.0 + # via yarl +protobuf==5.28.3 # via - # mlflow + # mlflow-skinny # tensorboard -psutil==6.0.0 +psutil==6.1.0 # via # distributed # ipykernel -psycopg2-binary==2.9.9 +psycopg2-binary==2.9.10 # via dioptra (pyproject.toml) pure-eval==0.2.3 # via stack-data -pyarrow==15.0.2 +pyarrow==17.0.0 # via # dioptra (pyproject.toml) # mlflow -pybsm==0.5.1 - # via nrtk +pyasn1==0.6.1 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.4.1 + # via google-auth pycocotools==2.0.8 # via # dioptra (pyproject.toml) # nrtk -pycodestyle==2.12.0 +pycodestyle==2.12.1 # via # autopep8 # dioptra (pyproject.toml) @@ -640,23 +644,22 @@ pygments==2.18.0 # ipython # jupyter-console # nbconvert - # qtconsole # rich # sphinx -pyparsing==3.1.2 +pyparsing==3.2.0 # via # dioptra # dioptra (pyproject.toml) # matplotlib -pyproject-api==1.7.1 +pyproject-api==1.8.0 # via tox -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via # build # pip-tools pyspellchecker==0.8.1 # via esbonio -pytest==8.3.2 +pytest==8.3.3 # via # dioptra (pyproject.toml) # pytest-cookies @@ -673,6 +676,7 @@ python-dateutil==2.9.0.post0 # dioptra (pyproject.toml) # faker # freezegun + # graphene # jupyter-client # kaggle # matplotlib @@ -691,25 +695,22 @@ python-slugify==8.0.4 # prefect pytoml==0.1.21 # via dioptra (pyproject.toml) -pytz==2024.1 +pytz==2024.2 # via # croniter # flask-restx - # mlflow # pandas # prefect -pywavelets==1.6.0 - # via scikit-image -pywin32==306 +pywin32==308 # via # docker # jupyter-core -pywinpty==2.0.13 +pywinpty==2.0.14 # via # jupyter-server # jupyter-server-terminals # terminado -pyyaml==6.0.1 +pyyaml==6.0.2 # via # cookiecutter # dask @@ -717,22 +718,15 @@ pyyaml==6.0.1 # dioptra (pyproject.toml) # distributed # jupyter-events - # mlflow + # mlflow-skinny # prefect -pyzmq==26.0.3 +pyzmq==26.2.0 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # qtconsole -qtconsole==5.5.2 - # via jupyter -qtpy==2.4.1 - # via qtconsole -querystring-parser==1.2.4 - # via mlflow -redis==5.0.7 +redis==5.2.0 # via # dioptra # dioptra (pyproject.toml) @@ -745,12 +739,13 @@ referencing==0.35.1 requests==2.32.3 # via # cookiecutter + # databricks-sdk # dioptra # dioptra (pyproject.toml) # docker # jupyterlab-server # kaggle - # mlflow + # mlflow-skinny # prefect # smqtk-dataprovider # sphinx @@ -762,42 +757,43 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rich==13.7.1 +rich==13.9.3 # via dioptra (pyproject.toml) -rpds-py==0.19.1 +rpds-py==0.20.0 # via # jsonschema # referencing -rq==1.16.2 +rq==2.0.0 # via # dioptra # dioptra (pyproject.toml) -s3transfer==0.10.2 +rsa==4.9 + # via google-auth +s3transfer==0.10.3 # via boto3 -scikit-image==0.21.0 +scikit-image==0.24.0 # via # imgaug # nrtk -scikit-learn==1.5.1 +scikit-learn==1.5.2 # via # adversarial-robustness-toolbox # dioptra (pyproject.toml) # mlflow -scipy==1.13.1 +scipy==1.14.1 # via # adversarial-robustness-toolbox # dioptra # dioptra (pyproject.toml) # imgaug # mlflow - # pybsm # scikit-image # scikit-learn send2trash==1.8.3 # via jupyter-server -shapely==2.0.5 +shapely==2.0.6 # via imgaug -simplejson==3.19.2 +simplejson==3.19.3 # via dioptra (pyproject.toml) six==1.16.0 # via @@ -807,7 +803,6 @@ six==1.16.0 # imgaug # kaggle # python-dateutil - # querystring-parser # rfc3339-validator # tensorboard smmap==5.0.1 @@ -849,25 +844,25 @@ snowballstemmer==2.2.0 # sphinx sortedcontainers==2.4.0 # via distributed -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==4.5.0 # via # dioptra (pyproject.toml) # esbonio -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy==2.0.31 +sqlalchemy==2.0.36 # via # alembic # dioptra @@ -875,7 +870,7 @@ sqlalchemy==2.0.31 # flask-sqlalchemy # mlflow sqlparse==0.5.1 - # via mlflow + # via mlflow-skinny stack-data==0.6.3 # via ipython structlog==24.4.0 @@ -886,7 +881,7 @@ tabulate==0.9.0 # via prefect tblib==3.0.0 # via distributed -tensorboard==2.17.0 +tensorboard==2.18.0 # via dioptra (pyproject.toml) tensorboard-data-server==0.7.2 # via tensorboard @@ -898,17 +893,17 @@ text-unidecode==1.3 # via python-slugify threadpoolctl==3.5.0 # via scikit-learn -tifffile==2024.7.24 +tifffile==2024.9.20 # via scikit-image -time-machine==2.14.2 +time-machine==2.16.0 # via pendulum -tinycss2==1.3.0 +tinycss2==1.4.0 # via nbconvert toml==0.10.2 # via prefect -tomli==2.0.1 +tomli==2.0.2 # via dioptra (pyproject.toml) -toolz==0.12.1 +toolz==1.0.0 # via # dask # distributed @@ -922,9 +917,9 @@ tornado==6.4.1 # jupyterlab # notebook # terminado -tox==4.16.0 +tox==4.23.2 # via dioptra (pyproject.toml) -tqdm==4.66.4 +tqdm==4.66.6 # via # adversarial-robustness-toolbox # kaggle @@ -945,26 +940,27 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat - # qtconsole -types-python-dateutil==2.9.0.20240316 +types-python-dateutil==2.9.0.20241003 # via arrow typing-extensions==4.12.2 # via # alembic # dioptra # dioptra (pyproject.toml) + # faker + # graphene # ipython # opentelemetry-sdk # sqlalchemy -tzdata==2024.1 +tzdata==2024.2 # via # pandas # pendulum -universal-pathlib==0.2.2 +universal-pathlib==0.2.5 # via dioptra (pyproject.toml) uri-template==1.3.0 # via jsonschema -urllib3==2.2.2 +urllib3==2.2.3 # via # botocore # distributed @@ -972,13 +968,13 @@ urllib3==2.2.2 # kaggle # prefect # requests -virtualenv==20.26.3 +virtualenv==20.27.1 # via tox waitress==3.0.0 # via mlflow wcwidth==0.2.13 # via prompt-toolkit -webcolors==24.6.0 +webcolors==24.8.0 # via jsonschema webencodings==0.5.1 # via @@ -986,7 +982,7 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server -werkzeug==3.0.3 +werkzeug==3.0.6 # via # dioptra # dioptra (pyproject.toml) @@ -995,19 +991,19 @@ werkzeug==3.0.3 # flask-login # flask-restx # tensorboard -wheel==0.43.0 +wheel==0.44.0 # via # dioptra (pyproject.toml) # pip-tools -widgetsnbextension==4.0.11 +widgetsnbextension==4.0.13 # via ipywidgets wrapt==1.16.0 # via deprecated -yarl==1.9.4 +yarl==1.16.0 # via aiohttp zict==3.0.0 # via distributed -zipp==3.19.2 +zipp==3.20.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/src/dioptra/client/__version__.py b/src/dioptra/client/__version__.py index 694c5ce36..ccdd03af1 100644 --- a/src/dioptra/client/__version__.py +++ b/src/dioptra/client/__version__.py @@ -14,4 +14,4 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -__version__ = "1.0.0" +__version__ = "1.0.1" diff --git a/src/dioptra/client/_client.py b/src/dioptra/client/_client.py index a4094a64b..176ea3ae9 100644 --- a/src/dioptra/client/_client.py +++ b/src/dioptra/client/_client.py @@ -704,7 +704,7 @@ def upload_custom_plugin_package( """Registers a new task plugin uploaded via the task plugin upload form. Args: - custom_plugin_name: Plugin name for for the upload form. + custom_plugin_name: Plugin name for the upload form. custom_plugin_file: Path to custom plugin. collection: Collection to upload the plugin to. Defaults to "dioptra_custom". diff --git a/src/dioptra/pyplugs/__version__.py b/src/dioptra/pyplugs/__version__.py index 694c5ce36..ccdd03af1 100644 --- a/src/dioptra/pyplugs/__version__.py +++ b/src/dioptra/pyplugs/__version__.py @@ -14,4 +14,4 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -__version__ = "1.0.0" +__version__ = "1.0.1" diff --git a/src/dioptra/restapi/__version__.py b/src/dioptra/restapi/__version__.py index 694c5ce36..ccdd03af1 100644 --- a/src/dioptra/restapi/__version__.py +++ b/src/dioptra/restapi/__version__.py @@ -14,4 +14,4 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -__version__ = "1.0.0" +__version__ = "1.0.1" diff --git a/src/dioptra/restapi/db/alembic/versions/5b80d059cbb4_fix_primary_key_and_unique_index_on_.py b/src/dioptra/restapi/db/alembic/versions/5b80d059cbb4_fix_primary_key_and_unique_index_on_.py index b9d5a86a0..509a3f1c4 100644 --- a/src/dioptra/restapi/db/alembic/versions/5b80d059cbb4_fix_primary_key_and_unique_index_on_.py +++ b/src/dioptra/restapi/db/alembic/versions/5b80d059cbb4_fix_primary_key_and_unique_index_on_.py @@ -55,7 +55,7 @@ def upgrade(): with op.batch_alter_table("plugin_task_input_parameters", schema=None) as batch_op: batch_op.add_column(sa.Column("required", sa.Boolean(), nullable=True)) - # Set the new required field on any pre-existing input_parameters to True. + # Set the new required field on any preexisting input_parameters to True. with Session() as session: for param in session.scalars(sa.select(PluginTaskInputParameterUpgrade)): param.required = True diff --git a/src/dioptra/restapi/db/alembic/versions/6a75ede23821_update_entry_point_parameter_types_list.py b/src/dioptra/restapi/db/alembic/versions/6a75ede23821_update_entry_point_parameter_types_list.py new file mode 100644 index 000000000..21e385fdc --- /dev/null +++ b/src/dioptra/restapi/db/alembic/versions/6a75ede23821_update_entry_point_parameter_types_list.py @@ -0,0 +1,125 @@ +"""Update entry point parameter types list + +Revision ID: 6a75ede23821 +Revises: 4b2d781f8bb4 +Create Date: 2024-09-10 16:32:40.707231 + +""" + +from typing import Annotated, Optional + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.orm import ( + DeclarativeBase, + Mapped, + MappedAsDataclass, + mapped_column, + sessionmaker, +) + +# revision identifiers, used by Alembic. +revision = "6a75ede23821" +down_revision = "4b2d781f8bb4" +branch_labels = None +depends_on = None + + +# Upgrade and downgrade inserts and deletes +UPGRADE_INSERTS = ["boolean", "integer", "list", "mapping"] +UPGRADE_DELETES = ["path", "uri"] +DOWNGRADE_INSERTS = ["path", "uri"] + + +# Migration data models +intpk = Annotated[ + int, + mapped_column(sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True), +] +text_ = Annotated[str, mapped_column(sa.Text())] +bool_ = Annotated[bool, mapped_column(sa.Boolean())] +optionalstr = Annotated[Optional[str], mapped_column(sa.Text(), nullable=True)] + + +class UpgradeBase(DeclarativeBase, MappedAsDataclass): + pass + + +class DowngradeBase(DeclarativeBase, MappedAsDataclass): + pass + + +class EntryPointParameterTypeUpgrade(UpgradeBase): + __tablename__ = "entry_point_parameter_types" + + parameter_type: Mapped[text_] = mapped_column(primary_key=True) + + +class EntryPointParameterUpgrade(UpgradeBase): + __tablename__ = "entry_point_parameters" + + entry_point_resource_snapshot_id: Mapped[intpk] = mapped_column(init=False) + parameter_number: Mapped[intpk] + parameter_type: Mapped[text_] = mapped_column(nullable=False) + name: Mapped[text_] = mapped_column(nullable=False) + default_value: Mapped[optionalstr] + + +class EntryPointParameterTypeDowngrade(DowngradeBase): + __tablename__ = "entry_point_parameter_types" + + parameter_type: Mapped[text_] = mapped_column(primary_key=True) + + +def upgrade(): + bind = op.get_bind() + Session = sessionmaker(bind=bind) + + with Session() as session: + for parameter_type in UPGRADE_INSERTS: + stmt = sa.select(EntryPointParameterTypeUpgrade).where( + EntryPointParameterTypeUpgrade.parameter_type == parameter_type + ) + + if session.scalar(stmt) is None: + session.add( + EntryPointParameterTypeUpgrade(parameter_type=parameter_type) + ) + + # Search for any parameters that are of type "path" or "uri" and convert them to + # "string" + to_string_params_stmt = sa.select(EntryPointParameterUpgrade).where( + EntryPointParameterUpgrade.parameter_type.in_(["path", "uri"]) + ) + + for entry_point_parameter in session.execute(to_string_params_stmt): + entry_point_parameter.parameter_type = "string" + + for parameter_type in UPGRADE_DELETES: + stmt = sa.select(EntryPointParameterTypeUpgrade).where( + EntryPointParameterTypeUpgrade.parameter_type == parameter_type + ) + entry_point_parameter_type = session.scalar(stmt) + + if entry_point_parameter_type is not None: + session.delete(entry_point_parameter_type) + + session.commit() + + +def downgrade(): + bind = op.get_bind() + Session = sessionmaker(bind=bind) + + with Session() as session: + for parameter_type in DOWNGRADE_INSERTS: + stmt = sa.select(EntryPointParameterTypeDowngrade).where( + EntryPointParameterTypeDowngrade.parameter_type == parameter_type + ) + + if session.scalar(stmt) is None: + session.add( + EntryPointParameterTypeDowngrade(parameter_type=parameter_type) + ) + + session.commit() diff --git a/src/dioptra/restapi/db/alembic/versions/d2bae5f6d991_add_readonly_resource_locks_to_pre_.py b/src/dioptra/restapi/db/alembic/versions/d2bae5f6d991_add_readonly_resource_locks_to_pre_.py index 3b4071e06..c21592086 100644 --- a/src/dioptra/restapi/db/alembic/versions/d2bae5f6d991_add_readonly_resource_locks_to_pre_.py +++ b/src/dioptra/restapi/db/alembic/versions/d2bae5f6d991_add_readonly_resource_locks_to_pre_.py @@ -1,4 +1,4 @@ -"""Add 'readonly' resource locks to pre-existing built-in parameter types +"""Add 'readonly' resource locks to preexisting built-in parameter types Revision ID: d2bae5f6d991 Revises: 10f9e72e72aa diff --git a/src/dioptra/restapi/errors.py b/src/dioptra/restapi/errors.py index ba72c03a5..58fea2a30 100644 --- a/src/dioptra/restapi/errors.py +++ b/src/dioptra/restapi/errors.py @@ -20,87 +20,418 @@ """ from __future__ import annotations +import http +import typing + +import structlog +from flask import request from flask_restx import Api +from structlog.stdlib import BoundLogger + +LOGGER: BoundLogger = structlog.stdlib.get_logger() + + +def add_attribute_values(**kwargs: typing.Any) -> list[str]: + """ + Helper function to add attribute name/value pairs to a list for use in an error + message. + + Args: + buffer: The StringIO instance into which the attribute name/value pairs are to + be added. + attributes: the list of attribute value pairs to add to the buffer. + """ + length = len(kwargs) + def sep(index: int) -> str: + if index == 0: + return " with" + + if index == length - 1: + return ", and" + + return "," + + return [ + f"{sep(index)} {key} having value ({value})" + for index, (key, value) in enumerate(kwargs.items()) + ] + + +class DioptraError(Exception): + """ + Generic Dioptra Error. + Args: + message: An error specific message to display that provide context for why the + error was raised. + """ -class BackendDatabaseError(Exception): + def __init__(self, message: str): + self.message: str = message + + def to_message(self) -> str: + if self.__cause__ is None: + return self.message + + if isinstance(self.__cause__, DioptraError): + return f"{self.message} Cause: {self.__cause__.to_message()}" + + return f"{self.message} Cause: {self.__cause__}" + + +class EntityDoesNotExistError(DioptraError): + """ + The requested entity does not exist. + Args: + entity_type: the entity type name (e.g. "group" or "queue") + kwargs: the attribute value pairs used to request the entity + """ + + def __init__(self, entity_type: str | None = None, **kwargs: typing.Any): + super().__init__( + "".join( + [ + "Failed to locate ", + "an entity" if entity_type is None else entity_type, + *add_attribute_values(**kwargs), + ".", + ] + ) + ) + self.entity_type = "unknown" if entity_type is None else entity_type + self.entity_attributes = kwargs + + +class EntityExistsError(DioptraError): + """ + The requested entity already exists. + Args: + entity_type: the entity type name (e.g. "group" or "queue") + existing_id: the id of the existing entity + kwargs: the attribute value pairs used to request the entity + """ + + def __init__(self, entity_type: str, existing_id: int, **kwargs: typing.Any): + super().__init__( + "".join( + [ + f"The {entity_type}", + *add_attribute_values(**kwargs), + " is not available.", + ] + ) + ) + self.entity_type = entity_type + self.entity_attributes = kwargs + self.existing_id = existing_id + + +class LockError(DioptraError): + """ + Top-level Lock Error. + + Args: + message: a message describing the lock error + """ + + def __init__(self, message: str): + super().__init__(message) + + +class ReadOnlyLockError(LockError): + """The type has a read-only lock and cannot be modified.""" + + def __init__(self, type: str, **kwargs: typing.Any): + super().__init__( + "".join( + [ + f"The {type} type", + *add_attribute_values(**kwargs), + " has a read-only lock and cannot be modified.", + ] + ) + ) + self.entity_type = type + self.entity_attributes = kwargs + + +class BackendDatabaseError(DioptraError): """The backend database returned an unexpected response.""" + def __init__(self): + super().__init__( + "The backend database returned an unexpected response, please " + "contact the system administrator." + ) + -class SearchNotImplementedError(Exception): +class SearchNotImplementedError(DioptraError): """The search functionality has not been implemented.""" + def __init__(self): + super().__init__("The search functionality has not been implemented.") -class SearchParseError(Exception): - """The search query could not be parsed.""" +class SearchParseError(DioptraError): + """The search query could not be parsed.""" -class ResourceDoesNotExistError(Exception): - """The resource does not exist.""" + def __init__(self, context: str, error: str): + super().__init__("The provided search query could not be parsed.") + self.context = context + self.error = error -class DraftDoesNotExistError(Exception): +class DraftDoesNotExistError(DioptraError): """The requested draft does not exist.""" + def __init__(self, **kwargs: typing.Any): + super().__init__( + "".join( + [ + "The requested draft", + *add_attribute_values(**kwargs), + " does not exist.", + ] + ) + ) + self.entity_attributes = kwargs + -class DraftAlreadyExistsError(Exception): +class DraftAlreadyExistsError(DioptraError): """The draft already exists.""" + def __init__(self, type: str, id: int): + super().__init__(f"A draft for a [{type}] with id: {id} already exists.") + self.resource_type = type + self.resource_id = id -def register_base_error_handlers(api: Api) -> None: - @api.errorhandler(BackendDatabaseError) - def handle_backend_database_error(error): - return { - "message": "The backend database returned an unexpected response, please " - "contact the system administrator" - }, 500 - @api.errorhandler(SearchNotImplementedError) - def handle_search_not_implemented_error(error): - return {"message": "The search functionality has not been implemented"}, 501 +class SortParameterValidationError(DioptraError): + """The sort parameters are not valid.""" - @api.errorhandler(SearchParseError) - def handle_search_parse_error(error): - return { - "message": "The provided search query could not be parsed", - "query": error.args[0], - "reason": error.args[1], - }, 422 + def __init__(self, type: str, column: str, **kwargs): + super().__init__(f"The sort parameter, {column}, for {type} is not sortable.") - @api.errorhandler(ResourceDoesNotExistError) - def handle_resource_does_not_exist(error): - return {"message": "Not Found - The requested resource does not exist"}, 404 - @api.errorhandler(DraftDoesNotExistError) - def handle_draft_does_not_exist(error): - return {"message": "Not Found - The requested draft does not exist"}, 404 +class QueryParameterValidationError(DioptraError): + """Input parameters failed validation.""" - @api.errorhandler(DraftAlreadyExistsError) - def handle_draft_already_exists(error): - return ( - {"message": "Bad Request - The draft for this resource already exists."}, - 400, + def __init__(self, type: str, constraint: str, **kwargs): + super().__init__( + "".join( + [ + f"Input parameters for {type} failed {constraint} check", + *add_attribute_values(**kwargs), + ".", + ] + ) + ) + self.resource_type = type + self.constraint = constraint + self.parameters = kwargs + + +class QueryParameterNotUniqueError(QueryParameterValidationError): + """Query Parameters failed unique validatation check.""" + + def __init__(self, type: str, **kwargs): + super().__init__(type, "unique", **kwargs) + + +class JobInvalidStatusTransitionError(DioptraError): + """The requested status transition is invalid.""" + + def __init__(self): + super().__init__("The requested job status update is invalid.") + + +class JobInvalidParameterNameError(DioptraError): + """The requested job parameter name is invalid.""" + + def __init__(self): + super().__init__( + "A provided job parameter name does not match any entrypoint " "parameters." + ) + + +class JobMlflowRunAlreadySetError(DioptraError): + """The requested job already has an mlflow run id set.""" + + def __init__(self): + super().__init__( + "The requested job already has an mlflow run id set. It may " + "not be changed." ) -def register_error_handlers(api: Api) -> None: +class EntityDependencyError(DioptraError): + """ + Base Error for dependency problems between entities. + + Args: + message: a message describing the dependecy error + """ + + def __init__(self, message: str): + super().__init__(message) + + +class EntityNotRegisteredError(DioptraError): + """ + An entity could not be located based on a relationship with another entity. + + Args: + parent_type: the parent or owning type of the relation + parent_id: the parent or owning id of the relation + child_type: the child or dependent type of the relation + child_id: the child or dependent id of the relation + """ + + def __init__( + self, parent_type: str, parent_id: int, child_type: str, child_id: int + ): + super().__init__( + f"The requested {child_type} having id ({child_id}) is not registered to " + f"the {parent_type} having id ({parent_id})." + ) + self.parent_type = parent_type + self.parent_id = parent_id + self.child_type = child_type + self.child_id = child_id + + +class PluginParameterTypeMatchesBuiltinTypeError(DioptraError): + """The plugin parameter type name cannot match a built-in type.""" + + def __init__(self): + super().__init__( + "The requested plugin parameter type name matches a built-in " + "type. Please select another and resubmit." + ) + + +# User Errors +class NoCurrentUserError(DioptraError): + """There is no currently logged-in user.""" + + def __init__(self): + super().__init__("There is no currently logged-in user.") + + +class UserPasswordChangeError(DioptraError): + """Password change failed.""" + + def __init__(self, message: str): + super().__init__(message) + + +class UserPasswordError(DioptraError): + """Password Error.""" + + def __init__(self, message: str): + super().__init__(message) + + +def error_result( + error: DioptraError, status: http.HTTPStatus, detail: dict[str, typing.Any] +) -> tuple[dict[str, typing.Any], int]: + return { + "error": error.__class__.__name__, + "message": f"{status.phrase} - {error.message}", + "detail": detail, + "originating_path": request.full_path, + }, status.value + + +# Silenced Complexity error for this function since it is a straitfoward registration of +# error handlers +def register_error_handlers(api: Api, **kwargs) -> None: # noqa: C901 """Registers the error handlers with the main application. Args: api: The main REST |Api| object. """ + log: BoundLogger = kwargs.get("log", LOGGER.new()) + + @api.errorhandler(EntityDoesNotExistError) + def handle_resource_does_not_exist_error(error: EntityDoesNotExistError): + log.debug( + "Entity not found", entity_type=error.entity_type, **error.entity_attributes + ) + return error_result( + error, + http.HTTPStatus.NOT_FOUND, + {"entity_type": error.entity_type, **error.entity_attributes}, + ) + + @api.errorhandler(EntityExistsError) + def handle_entity_exists_error(error: EntityExistsError): + log.debug( + "Entity exists", + entity_type=error.entity_type, + existing_id=error.existing_id, + **error.entity_attributes, + ) + return error_result( + error, + http.HTTPStatus.CONFLICT, + { + "entity_type": error.entity_type, + "existing_id": error.existing_id, + "entity_attributes": {**error.entity_attributes}, + }, + ) + + @api.errorhandler(BackendDatabaseError) + def handle_backend_database_error(error: BackendDatabaseError): + log.error(error.to_message()) + return error_result(error, http.HTTPStatus.INTERNAL_SERVER_ERROR, {}) + + @api.errorhandler(SearchNotImplementedError) + def handle_search_not_implemented_error(error: SearchNotImplementedError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.NOT_IMPLEMENTED, {}) + + @api.errorhandler(SearchParseError) + def handle_search_parse_error(error: SearchParseError): + log.debug(error.to_message()) + return error_result( + error, + http.HTTPStatus.UNPROCESSABLE_ENTITY, + {"query": error.args[0], "reason": error.args[1]}, + ) + + @api.errorhandler(DraftDoesNotExistError) + def handle_draft_does_not_exist(error: DraftDoesNotExistError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.NOT_FOUND, {}) + + @api.errorhandler(DraftAlreadyExistsError) + def handle_draft_already_exists(error: DraftAlreadyExistsError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.BAD_REQUEST, {}) + + @api.errorhandler(LockError) + def handle_lock_error(error: LockError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.FORBIDDEN, {}) + + @api.errorhandler(NoCurrentUserError) + def handle_no_current_user_error(error: NoCurrentUserError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.UNAUTHORIZED, {}) + + @api.errorhandler(UserPasswordChangeError) + def handle_password_change_error(error: UserPasswordChangeError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.FORBIDDEN, {}) + + @api.errorhandler(UserPasswordError) + def handle_user_password_error(error: UserPasswordError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.UNAUTHORIZED, {}) - from dioptra.restapi import v1 - - register_base_error_handlers(api) - v1.artifacts.errors.register_error_handlers(api) - v1.entrypoints.errors.register_error_handlers(api) - v1.experiments.errors.register_error_handlers(api) - v1.groups.errors.register_error_handlers(api) - v1.jobs.errors.register_error_handlers(api) - v1.models.errors.register_error_handlers(api) - v1.plugin_parameter_types.errors.register_error_handlers(api) - v1.plugins.errors.register_error_handlers(api) - v1.queues.errors.register_error_handlers(api) - v1.tags.errors.register_error_handlers(api) - v1.users.errors.register_error_handlers(api) + @api.errorhandler(DioptraError) + def handle_base_error(error: DioptraError): + log.debug(error.to_message()) + return error_result(error, http.HTTPStatus.BAD_REQUEST, {}) diff --git a/src/dioptra/restapi/utils.py b/src/dioptra/restapi/utils.py index 5208cf124..ecdbb5f0f 100644 --- a/src/dioptra/restapi/utils.py +++ b/src/dioptra/restapi/utils.py @@ -25,6 +25,7 @@ import datetime import functools +from collections import Counter from importlib.resources import as_file, files from typing import Any, Callable, List, Protocol, Type, cast @@ -325,3 +326,26 @@ def setup_injection(api: Api, injector: Injector) -> None: ma.URL: str, ma.UUID: str, } + + +# Validation Functions +def find_non_unique(name: str, parameters: list[dict[str, Any]]) -> list[str]: + """ + Finds all values of a key that are not unique in a list of dictionaries. + Useful for checking that a provided input satisfies uniqueness constraints. + + Note that the key name must be in every dictionary of the provided list. + + Args: + name: the name of the parameter to check + parameters: the input parameters to check + + Returns: + A list of all values that were provided more than once, or an empty list if all + values of the key were unique + """ + name_count: Counter = Counter() + # this line fails if a parameter is missing a "name" value + name_count.update([parameter[name] for parameter in parameters]) + # create a list of all name values that appear more than once + return [key for key in name_count.keys() if name_count[key] > 1] diff --git a/src/dioptra/restapi/v1/artifacts/__init__.py b/src/dioptra/restapi/v1/artifacts/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/artifacts/__init__.py +++ b/src/dioptra/restapi/v1/artifacts/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/artifacts/controller.py b/src/dioptra/restapi/v1/artifacts/controller.py index 917cbd325..a92dbd7a9 100644 --- a/src/dioptra/restapi/v1/artifacts/controller.py +++ b/src/dioptra/restapi/v1/artifacts/controller.py @@ -83,12 +83,16 @@ def get(self): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] artifacts, total_num_artifacts = self._artifact_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -101,6 +105,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_artifacts, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/artifacts/schema.py b/src/dioptra/restapi/v1/artifacts/schema.py index 093465b44..6d38710f5 100644 --- a/src/dioptra/restapi/v1/artifacts/schema.py +++ b/src/dioptra/restapi/v1/artifacts/schema.py @@ -22,6 +22,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -84,5 +85,6 @@ class ArtifactGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /artifacts endpoint.""" diff --git a/src/dioptra/restapi/v1/artifacts/service.py b/src/dioptra/restapi/v1/artifacts/service.py index 8827385c5..96cc99f5e 100644 --- a/src/dioptra/restapi/v1/artifacts/service.py +++ b/src/dioptra/restapi/v1/artifacts/service.py @@ -26,14 +26,17 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.jobs.service import ExperimentJobIdService, JobIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ArtifactAlreadyExistsError, ArtifactDoesNotExistError - LOGGER: BoundLogger = structlog.stdlib.get_logger() RESOURCE_TYPE: Final[str] = "artifact" @@ -41,6 +44,12 @@ "uri": lambda x: models.Artifact.uri.like(x, escape="/"), "description": lambda x: models.Artifact.description.like(x, escape="/"), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "uri": models.Artifact.uri, + "createdOn": models.Artifact.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.Artifact.description, +} class ArtifactService(object): @@ -87,14 +96,14 @@ def create( The newly created artifact object. Raises: - ArtifactAlreadyExistsError: If the artifact already exists. + EntityExistsError: If the artifact already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._artifact_uri_service.get(uri, log=log) is not None: - log.debug("Artifact uri already exists", uri=uri) - raise ArtifactAlreadyExistsError + duplicate = self._artifact_uri_service.get(uri, log=log) + if duplicate is not None: + raise EntityExistsError(RESOURCE_TYPE, duplicate.resource_id, uri=uri) job_dict = cast( utils.JobDict, @@ -128,6 +137,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> Any: """Fetch a list of artifacts, optionally filtering by search string and paging @@ -138,6 +149,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of artifacts to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of artifacts and the total number of artifacts @@ -185,7 +198,7 @@ def get( return [], total_num_artifacts # get latest artifact snapshots - lastest_artifacts_stmt = ( + latest_artifacts_stmt = ( select(models.Artifact) .join(models.Resource) .where( @@ -197,7 +210,18 @@ def get( .offset(page_index) .limit(page_length) ) - artifacts = db.session.scalars(lastest_artifacts_stmt).all() + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + latest_artifacts_stmt = latest_artifacts_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + + artifacts = db.session.scalars(latest_artifacts_stmt).all() drafts_stmt = select( models.DraftResource.payload["resource_id"].as_string().cast(Integer) @@ -284,7 +308,7 @@ def get( artifact_uri: str, error_if_not_found: bool = False, **kwargs, - ) -> utils.ArtifactDict | None: + ) -> models.Artifact | None: """Fetch an artifact by its unique uri. Args: @@ -297,7 +321,7 @@ def get( The artifact object if found, otherwise None. Raises: - ArtifactDoesNotExistError: If the artifact is not found and + EntityDoesNotExistError: If the artifact is not found and `error_if_not_found` is True. """ @@ -319,8 +343,7 @@ def get( if artifact is None: if error_if_not_found: - log.debug("Artifact not found", artifact_uri=artifact_uri) - raise ArtifactDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, artifact_uri=artifact_uri) return None @@ -347,7 +370,7 @@ def get( The artifact object if found, otherwise None. Raises: - ArtifactDoesNotExistError: If the artifact is not found and + EntityDoesNotExistError: If the artifact is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -367,8 +390,7 @@ def get( if artifact is None: if error_if_not_found: - log.debug("Artifact not found", artifact_id=artifact_id) - raise ArtifactDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, artifact_id=artifact_id) return None @@ -407,9 +429,9 @@ def modify( The updated artifact object. Raises: - ArtifactDoesNotExistError: If the artifact is not found and + EntityDoesNotExistError: If the artifact is not found and `error_if_not_found` is True. - ArtifactAlreadyExistsError: If the artifact name already exists. + EntityExistsError: If the artifact name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) diff --git a/src/dioptra/restapi/v1/entrypoints/__init__.py b/src/dioptra/restapi/v1/entrypoints/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/entrypoints/__init__.py +++ b/src/dioptra/restapi/v1/entrypoints/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/entrypoints/controller.py b/src/dioptra/restapi/v1/entrypoints/controller.py index 36792afd5..ad2c25724 100644 --- a/src/dioptra/restapi/v1/entrypoints/controller.py +++ b/src/dioptra/restapi/v1/entrypoints/controller.py @@ -100,12 +100,16 @@ def get(self): search_string = parsed_query_params["search"] page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] entrypoints, total_num_entrypoints = self._entrypoint_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -118,6 +122,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_entrypoints, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/entrypoints/errors.py b/src/dioptra/restapi/v1/entrypoints/errors.py deleted file mode 100644 index 5d2c229f1..000000000 --- a/src/dioptra/restapi/v1/entrypoints/errors.py +++ /dev/null @@ -1,66 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the entrypoint endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class EntrypointAlreadyExistsError(Exception): - """The entrypoint name already exists.""" - - -class EntrypointDoesNotExistError(Exception): - """The requested entrypoint does not exist.""" - - -class EntrypointPluginDoesNotExistError(Exception): - """The requested plugin does not exist for the entrypoint.""" - - -class EntrypointParameterNamesNotUniqueError(Exception): - """Mutliple entrypoint parameters share the same name.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(EntrypointDoesNotExistError) - def handle_entrypoint_does_not_exist_error(error): - return {"message": "Not Found - The requested entrypoint does not exist"}, 404 - - @api.errorhandler(EntrypointPluginDoesNotExistError) - def handle_entrypoint_plugin_does_not_exist_error(error): - return { - "message": "Not Found - The requested plugin does not exist for this " - "entrypoint" - }, 404 - - @api.errorhandler(EntrypointAlreadyExistsError) - def handle_entrypoint_already_exists_error(error): - return ( - { - "message": "Bad Request - The entrypoint name on the registration form " - "already exists. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(EntrypointParameterNamesNotUniqueError) - def handle_entrypoint_parameter_names_not_unique_error(error): - return { - "message": "Bad Request - The entrypoint contains multiple parameters " - "with the same name." - }, 400 diff --git a/src/dioptra/restapi/v1/entrypoints/schema.py b/src/dioptra/restapi/v1/entrypoints/schema.py index 07573aed8..af0220c11 100644 --- a/src/dioptra/restapi/v1/entrypoints/schema.py +++ b/src/dioptra/restapi/v1/entrypoints/schema.py @@ -23,6 +23,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -95,7 +96,9 @@ class EntrypointParameterSchema(Schema): attribute="parameter_type", metadata=dict(description="Data type of the Entrypoint parameter."), required=True, - validate=validate.OneOf(["string", "float", "path", "uri"]), + validate=validate.OneOf( + ["string", "float", "integer", "boolean", "list", "mapping"] + ), ) @@ -227,5 +230,6 @@ class EntrypointGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /entrypoints endpoint.""" diff --git a/src/dioptra/restapi/v1/entrypoints/service.py b/src/dioptra/restapi/v1/entrypoints/service.py index 8ae147566..a8f3cf711 100644 --- a/src/dioptra/restapi/v1/entrypoints/service.py +++ b/src/dioptra/restapi/v1/entrypoints/service.py @@ -27,22 +27,23 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import resource_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + QueryParameterNotUniqueError, + SortParameterValidationError, +) +from dioptra.restapi.utils import find_non_unique from dioptra.restapi.v1 import utils from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.plugins.service import PluginIdsService -from dioptra.restapi.v1.queues.errors import QueueDoesNotExistError +from dioptra.restapi.v1.queues.service import RESOURCE_TYPE as QUEUE_RESOURCE_TYPE from dioptra.restapi.v1.queues.service import QueueIdsService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ( - EntrypointAlreadyExistsError, - EntrypointDoesNotExistError, - EntrypointParameterNamesNotUniqueError, - EntrypointPluginDoesNotExistError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() +PLUGIN_RESOURCE_TYPE: Final[str] = "entry_point_plugin" RESOURCE_TYPE: Final[str] = "entry_point" SEARCHABLE_FIELDS: Final[dict[str, Any]] = { @@ -50,6 +51,12 @@ "description": lambda x: models.EntryPoint.description.like(x, escape="/"), "task_graph": lambda x: models.EntryPoint.task_graph.like(x, escape="/"), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.EntryPoint.name, + "createdOn": models.EntryPoint.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.EntryPoint.description, +} class EntrypointService(object): @@ -103,17 +110,15 @@ def create( The newly created entrypoint object. Raises: - EntrypointAlreadyExistsError: If a entrypoint with the given name already - exists. + EntityExistsError: If a entrypoint with the given name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if ( - self._entrypoint_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Entrypoint name already exists", name=name, group_id=group_id) - raise EntrypointAlreadyExistsError + duplicate = self._entrypoint_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) group = self._group_id_service.get(group_id, error_if_not_found=True) queues = self._queue_ids_service.get(queue_ids, error_if_not_found=True) @@ -175,6 +180,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.EntrypointDict], int]: """Fetch a list of entrypoints, optionally filtering by search string and paging @@ -185,6 +192,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of entrypoints to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of entrypoints and the total number of entrypoints @@ -243,6 +252,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + entrypoints_stmt = entrypoints_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + entrypoints = list(db.session.scalars(entrypoints_stmt).unique().all()) queue_ids = set( @@ -321,7 +341,7 @@ def get( The entrypoint object if found, otherwise None. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found and + EntityDoesNotExistError: If the entrypoint is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -341,8 +361,9 @@ def get( if entrypoint is None: if error_if_not_found: - log.debug("Entrypoint not found", entrypoint_id=entrypoint_id) - raise EntrypointDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, entrypoint_id=entrypoint_id + ) return None @@ -397,15 +418,16 @@ def modify( The updated entrypoint object. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found and + EntityDoesNotExistError: If the entrypoint is not found and `error_if_not_found` is True. - EntrypointAlreadyExistsError: If the entrypoint name already exists. + EntityExistsError: If the entrypoint name already exists. + QueryParameterNotUniqueError: If the values for the "name" parameter in the + parameters list is not unique """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - - parameter_names = [parameter["name"] for parameter in parameters] - if len(parameter_names) > len(set(parameter_names)): - raise EntrypointParameterNamesNotUniqueError + duplicates = find_non_unique("name", parameters) + if len(duplicates) > 0: + raise QueryParameterNotUniqueError(RESOURCE_TYPE, name=duplicates) entrypoint_dict = self.get( entrypoint_id, error_if_not_found=error_if_not_found, log=log @@ -416,13 +438,14 @@ def modify( entrypoint = entrypoint_dict["entry_point"] group_id = entrypoint.resource.group_id - if ( - name != entrypoint.name - and self._entrypoint_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Entrypoint name already exists", name=name, group_id=group_id) - raise EntrypointAlreadyExistsError + if name != entrypoint.name: + duplicate = self._entrypoint_name_service.get( + name, group_id=group_id, log=log + ) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) queues = self._queue_ids_service.get(queue_ids, error_if_not_found=True) @@ -494,7 +517,7 @@ def delete(self, entrypoint_id: int, **kwargs) -> dict[str, Any]: entrypoint_resource = db.session.scalars(stmt).first() if entrypoint_resource is None: - raise EntrypointDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, entrypoint_id=entrypoint_id) deleted_resource_lock = models.ResourceLock( resource_lock_type=resource_lock_types.DELETE, @@ -544,7 +567,7 @@ def get( The plugin snapshots for the entrypoint. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found. + EntityDoesNotExistError: If the entrypoint is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug("Get entrypoint by id", entrypoint_id=entrypoint_id) @@ -577,8 +600,8 @@ def append( The updated entrypoint object. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found. - EntrypointAlreadyExistsError: If the entrypoint name already exists. + EntityDoesNotExistError: If the entrypoint is not found. + EntityExistsError: If the entrypoint name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -692,7 +715,7 @@ def get( The plugin snapshots for the entrypoint. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found. + EntityDoesNotExistError: If the entrypoint or plugin is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug("Get entrypoint by id", entrypoint_id=entrypoint_id) @@ -709,7 +732,9 @@ def get( for entry_point_plugin_file in entrypoint.entry_point_plugin_files } if plugin_id not in plugins: - raise EntrypointPluginDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_RESOURCE_TYPE, entrypoint_id=entrypoint_id, plugin_id=plugin_id + ) plugin = utils.PluginWithFilesDict( plugin=plugins[plugin_id], plugin_files=[], has_draft=None @@ -738,8 +763,7 @@ def delete( A dictionary reporting the status of the request. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found. - EntrypointPluginDoesNotExistError: If the plugin is not found. + EntityDoesNotExistError: If the entrypoint or plugin is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -754,7 +778,9 @@ def delete( plugin.plugin.resource_id for plugin in entrypoint.entry_point_plugin_files ) if plugin_id not in plugin_ids: - raise EntrypointPluginDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_RESOURCE_TYPE, entrypoint_id=entrypoint_id, plugin_id=plugin_id + ) # create a new snapshot with the plugin removed entrypoint_parameters = [ @@ -824,7 +850,7 @@ def get( The entrypoint object if found, otherwise None. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found and + EntityDoesNotExistError: If the entrypoint is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -846,10 +872,9 @@ def get( entrypoint_ids_missing = set(entrypoint_ids) - set( entrypoint.resource_id for entrypoint in entrypoints ) - log.debug( - "Entrypoint not found", entrypoint_ids=list(entrypoint_ids_missing) + raise EntityDoesNotExistError( + RESOURCE_TYPE, entrypoint_ids=list(entrypoint_ids_missing) ) - raise EntrypointDoesNotExistError return entrypoints @@ -890,7 +915,7 @@ def get( The list of plugins. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found and + EntityDoesNotExistError: If the entrypoint is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -927,9 +952,9 @@ def append( The updated list of queues resource objects. Raises: - EntrypointDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. - QueueDoesNotExistError: If one or more queues are not found. + EntityDoesNotExistError: If one or more queues are not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug( @@ -954,11 +979,6 @@ def append( new_queues = self._queue_ids_service.get( list(new_queue_ids), error_if_not_found=True, log=log ) - if error_if_not_found and len(new_queues) != len(new_queue_ids): - found_queue_ids = set(queue.resource_id for queue in new_queues) - missing_queue_ids = new_queue_ids - found_queue_ids - log.debug(queue_ids=list(missing_queue_ids)) - raise QueueDoesNotExistError entrypoint.children.extend([queue.resource for queue in new_queues]) @@ -989,9 +1009,9 @@ def modify( The updated queue resource object. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. - QueueDoesNotExistError: If one or more queues are not found. + EntityDoesNotExistError: If one or more queues are not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -1103,7 +1123,7 @@ def delete(self, entrypoint_id: int, queue_id, **kwargs) -> dict[str, Any]: removed_queue = queue_resources.pop(queue_id, None) if removed_queue is None: - raise QueueDoesNotExistError + raise EntityDoesNotExistError(QUEUE_RESOURCE_TYPE, queue_id=queue_id) plugin_resources = [ resource @@ -1140,7 +1160,7 @@ def get( The entrypoint object if found, otherwise None. Raises: - EntrypointDoesNotExistError: If the entrypoint is not found and + EntityDoesNotExistError: If the entrypoint is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -1161,8 +1181,9 @@ def get( if entrypoint is None: if error_if_not_found: - log.debug("Entrypoint not found", name=name) - raise EntrypointDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, name=name, group_id=group_id + ) return None diff --git a/src/dioptra/restapi/v1/experiments/__init__.py b/src/dioptra/restapi/v1/experiments/__init__.py index 006f5798f..99936763a 100644 --- a/src/dioptra/restapi/v1/experiments/__init__.py +++ b/src/dioptra/restapi/v1/experiments/__init__.py @@ -15,6 +15,3 @@ # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode """The experiments endpoint subpackage.""" -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/experiments/controller.py b/src/dioptra/restapi/v1/experiments/controller.py index 503a30e08..6ffb50f60 100644 --- a/src/dioptra/restapi/v1/experiments/controller.py +++ b/src/dioptra/restapi/v1/experiments/controller.py @@ -112,12 +112,16 @@ def get(self): search_string = parsed_query_params["search"] page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] experiments, total_num_experiments = self._experiment_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -130,6 +134,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_experiments, + sort_by=sort_by_string, + descending=descending, ) @login_required @@ -260,12 +266,16 @@ def get(self, id: int): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = unquote(parsed_query_params["sort_by"]) + descending = parsed_query_params["descending"] jobs, total_num_jobs = self._experiment_job_service.get( experiment_id=id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -278,6 +288,8 @@ def get(self, id: int): index=page_index, length=page_length, total_num_elements=total_num_jobs, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/experiments/errors.py b/src/dioptra/restapi/v1/experiments/errors.py deleted file mode 100644 index 69b0f5f2a..000000000 --- a/src/dioptra/restapi/v1/experiments/errors.py +++ /dev/null @@ -1,42 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the experiment endpoints.""" -from flask_restx import Api - - -class ExperimentAlreadyExistsError(Exception): - """The experiment name already exists.""" - - -class ExperimentDoesNotExistError(Exception): - """The requested experiment does not exist.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(ExperimentAlreadyExistsError) - def handle_experiment_already_exists_error(error): - return ( - { - "message": "Bad Request - The experiment name on the registration form " - "already exists. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(ExperimentDoesNotExistError) - def handle_experiment_does_not_exist_error(error): - return {"message": "Not Found - The requested experiment does not exist"}, 404 diff --git a/src/dioptra/restapi/v1/experiments/schema.py b/src/dioptra/restapi/v1/experiments/schema.py index 54bcfd52b..c078cf67a 100644 --- a/src/dioptra/restapi/v1/experiments/schema.py +++ b/src/dioptra/restapi/v1/experiments/schema.py @@ -22,6 +22,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -120,5 +121,6 @@ class ExperimentGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /experiments endpoint.""" diff --git a/src/dioptra/restapi/v1/experiments/service.py b/src/dioptra/restapi/v1/experiments/service.py index 43964db05..df1d1f2ee 100644 --- a/src/dioptra/restapi/v1/experiments/service.py +++ b/src/dioptra/restapi/v1/experiments/service.py @@ -27,15 +27,20 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import resource_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils -from dioptra.restapi.v1.entrypoints.errors import EntrypointDoesNotExistError +from dioptra.restapi.v1.entrypoints.service import ( + RESOURCE_TYPE as ENTRYPOINT_RESOURCE_TYPE, +) from dioptra.restapi.v1.entrypoints.service import EntrypointIdsService from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ExperimentAlreadyExistsError, ExperimentDoesNotExistError - LOGGER: BoundLogger = structlog.stdlib.get_logger() RESOURCE_TYPE: Final[str] = "experiment" @@ -44,6 +49,12 @@ "description": lambda x: models.Experiment.description.like(x, escape="/"), "tag": lambda x: models.Experiment.tags.any(models.Tag.name.like(x, escape="/")), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.Experiment.name, + "createdOn": models.Experiment.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.Experiment.description, +} class ExperimentService(object): @@ -93,17 +104,16 @@ def create( The newly created experiment object. Raises: - ExperimentAlreadyExistsError: If an experiment with the given name already + EntityExistsError: If an experiment with the given name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if ( - self._experiment_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Experiment name already exists", name=name, group_id=group_id) - raise ExperimentAlreadyExistsError + duplicate = self._experiment_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) group = self._group_id_service.get(group_id, error_if_not_found=True) entrypoints = ( @@ -147,6 +157,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.ExperimentDict], int]: """Fetch a list of experiments, optionally filtering by search string and paging @@ -157,6 +169,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first page to be returned. page_length: The maximum number of experiments to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of experiments and the total number of experiments @@ -214,6 +228,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + experiments_stmt = experiments_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + experiments = list(db.session.scalars(experiments_stmt).all()) entrypoint_ids = { @@ -294,7 +319,7 @@ def get( The experiment object if found, otherwise none. Raises: - ExperimentDoesNotExistError: If the experiment is not found and if + EntityDoesNotExistError: If the experiment is not found and if `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -314,8 +339,9 @@ def get( if experiment is None: if error_if_not_found: - log.debug("Experiment not found", experiment_id=experiment_id) - raise ExperimentDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, experiment_id=experiment_id + ) return None @@ -372,9 +398,9 @@ def modify( The updated experiment object. Raises: - ExperimentDoesNotExistError: If the experiment is not found and + EntityDoesNotExistError: If the experiment is not found and `error_if_not_found` is True. - ExperimentAlreadyExistsError: If the experiment name already exists. + EntityExistsError: If the experiment name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -387,13 +413,14 @@ def modify( experiment = experiment_dict["experiment"] group_id = experiment.resource.group_id - if ( - name != experiment.name - and self._experiment_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Experiment name already exists", name=name, group_id=group_id) - raise ExperimentAlreadyExistsError + if name != experiment.name: + duplicate = self._experiment_name_service.get( + name, group_id=group_id, log=log + ) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) entrypoints = self._entrypoint_ids_service.get( entrypoint_ids, error_if_not_found=True, log=log @@ -427,7 +454,7 @@ def delete(self, experiment_id: int, **kwargs) -> dict[str, Any]: """Delete an experiment. Args: - experiment_id: The unqiue id of the experiment. + experiment_id: The unique id of the experiment. Returns: A dictionary reporting the status of the request. @@ -440,7 +467,7 @@ def delete(self, experiment_id: int, **kwargs) -> dict[str, Any]: experiment_resource = db.session.scalars(stmt).first() if experiment_resource is None: - raise ExperimentDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, experiment_id=experiment_id) deleted_resource_lock = models.ResourceLock( resource_lock_type=resource_lock_types.DELETE, @@ -489,7 +516,7 @@ def get( The list of plugins. Raises: - ExperimentDoesNotExistError: If the experiment is not found and + EntityDoesNotExistError: If the experiment is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -527,9 +554,9 @@ def append( The updated list of entrypoints resource objects. Raises: - ExperimentDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the experiment is not found and `error_if_not_found` is True. - EntrypointDoesNotExistError: If one or more entrypoints are not found. + EntityDoesNotExistError: If one or more entrypoints are not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug( @@ -558,8 +585,9 @@ def append( entrypoint.resource_id for entrypoint in new_entrypoints ) missing_entrypoint_ids = new_entrypoint_ids - found_entrypoint_ids - log.debug(entrypoint_ids=list(missing_entrypoint_ids)) - raise EntrypointDoesNotExistError + raise EntityDoesNotExistError( + ENTRYPOINT_RESOURCE_TYPE, entrypoint_ids=list(missing_entrypoint_ids) + ) experiment.children.extend( [entrypoint.resource for entrypoint in new_entrypoints] @@ -594,9 +622,9 @@ def modify( The updated entrypoint resource object. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. - EntrypointDoesNotExistError: If one or more entrypoints are not found. + EntityDoesNotExistError: If one or more entrypoints are not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -701,7 +729,11 @@ def delete(self, experiment_id: int, entrypoint_id, **kwargs) -> dict[str, Any]: removed_entrypoint = entrypoint_resources.pop(entrypoint_id, None) if removed_entrypoint is None: - raise EntrypointDoesNotExistError + raise EntityDoesNotExistError( + ENTRYPOINT_RESOURCE_TYPE, + experiment_id=experiment_id, + entrypoint_id=entrypoint_id, + ) experiment.children = list(entrypoint_resources.values()) @@ -737,7 +769,7 @@ def get( The experiment object if found, otherwise None. Raises: - ExperimentDoesNotExistError: If the experiment is not found and + EntityDoesNotExistError: If the experiment is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -758,8 +790,9 @@ def get( if experiment is None: if error_if_not_found: - log.debug("Experiment not found", name=name) - raise ExperimentDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, experiment_name=name, group_id=group_id + ) return None diff --git a/src/dioptra/restapi/v1/groups/__init__.py b/src/dioptra/restapi/v1/groups/__init__.py index 9d5cefcdb..e80d1a337 100644 --- a/src/dioptra/restapi/v1/groups/__init__.py +++ b/src/dioptra/restapi/v1/groups/__init__.py @@ -15,6 +15,3 @@ # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode """The groups endpoint subpackage.""" -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/groups/controller.py b/src/dioptra/restapi/v1/groups/controller.py index 77989503f..d9cf83f64 100644 --- a/src/dioptra/restapi/v1/groups/controller.py +++ b/src/dioptra/restapi/v1/groups/controller.py @@ -194,7 +194,7 @@ def post(self, id: int): @accepts(schema=GroupMemberSchema(many=True), api=api) @responds(schema=GroupMemberSchema(many=True), api=api) def put(self, id: int): - """Modifies all Group Members' permisssions.""" + """Modifies all Group Members' permissions.""" log = LOGGER.new( request_id=str(uuid.uuid4()), resource="GroupMember", diff --git a/src/dioptra/restapi/v1/groups/errors.py b/src/dioptra/restapi/v1/groups/errors.py deleted file mode 100644 index 3d7449852..000000000 --- a/src/dioptra/restapi/v1/groups/errors.py +++ /dev/null @@ -1,41 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the group endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class GroupNameNotAvailableError(Exception): - """The group name is not available.""" - - -class GroupDoesNotExistError(Exception): - """The requested group does not exist.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(GroupDoesNotExistError) - def handle_user_does_not_exist_error(error): - return {"message": "Not Found - The requested group does not exist"}, 404 - - @api.errorhandler(GroupNameNotAvailableError) - def handle_no_current_user_error(error): - return ( - {"message": "Bad Request - The group name is not available"}, - 400, - ) diff --git a/src/dioptra/restapi/v1/groups/service.py b/src/dioptra/restapi/v1/groups/service.py index 09109bac3..271b9d6ea 100644 --- a/src/dioptra/restapi/v1/groups/service.py +++ b/src/dioptra/restapi/v1/groups/service.py @@ -27,11 +27,13 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import group_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, +) from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import GroupDoesNotExistError, GroupNameNotAvailableError - LOGGER: BoundLogger = structlog.stdlib.get_logger() DEFAULT_GROUP_MEMBER_PERMISSIONS: Final[dict[str, bool]] = { @@ -58,6 +60,8 @@ "name": lambda x: models.Group.name.like(x, escape="/"), } +GROUP_TYPE: Final[str] = "group" + class GroupService(object): """The service methods used for creating and managing groups.""" @@ -104,9 +108,9 @@ def create( """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._group_name_service.get(name) is not None: - log.debug("Group name already exists", name=name) - raise GroupNameNotAvailableError + duplicate = self._group_name_service.get(name) + if duplicate is not None: + raise EntityExistsError("group", duplicate.group_id, name=name) new_group = models.Group(name=name, creator=creator) self._group_member_service.create( @@ -222,7 +226,7 @@ def get( The group object if found, otherwise None. Raises: - UserDoesNotExistError: If the group is not found and `error_if_not_found` + EntityDoesNotExistError: If the group is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -233,8 +237,7 @@ def get( if group is None: if error_if_not_found: - log.debug("Group not found", group_id=group_id) - raise GroupDoesNotExistError + raise EntityDoesNotExistError(GROUP_TYPE, group_id=group_id) return None @@ -261,7 +264,7 @@ def modify( The group object. Raises: - GroupDoesNotExistError: If the group is not found and `error_if_not_found` + EntityDoesNotExistError: If the group is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -272,14 +275,13 @@ def modify( if group is None: if error_if_not_found: - log.debug("Group not found", group_id=group_id) - raise GroupDoesNotExistError + raise EntityDoesNotExistError(GROUP_TYPE, group_id=group_id) return None - if self._group_name_service.get(name, log=log) is not None: - log.debug("Group name already exists", name=name) - raise GroupNameNotAvailableError + duplicate = self._group_name_service.get(name, log=log) + if duplicate is not None: + raise EntityExistsError(GROUP_TYPE, duplicate.group_id, name=name) current_timestamp = datetime.datetime.now(tz=datetime.timezone.utc) group.last_modified_on = current_timestamp @@ -307,7 +309,7 @@ def delete(self, group_id: int, **kwargs) -> dict[str, Any]: group = db.session.scalars(stmt).first() if group is None: - raise GroupDoesNotExistError + raise EntityDoesNotExistError(GROUP_TYPE, group_id=group_id) name = group.name @@ -339,7 +341,7 @@ def get( The group object if found, otherwise None. Raises: - GroupDoesNotExistError: If the group is not found and `error_if_not_found` + EntityDoesNotExistError: If the group is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -350,8 +352,7 @@ def get( if group is None: if error_if_not_found: - log.debug("Group not found", name=name) - raise GroupDoesNotExistError + raise EntityDoesNotExistError(GROUP_TYPE, name=name) return None diff --git a/src/dioptra/restapi/v1/jobs/__init__.py b/src/dioptra/restapi/v1/jobs/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/jobs/__init__.py +++ b/src/dioptra/restapi/v1/jobs/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/jobs/controller.py b/src/dioptra/restapi/v1/jobs/controller.py index 52025b141..11576034c 100644 --- a/src/dioptra/restapi/v1/jobs/controller.py +++ b/src/dioptra/restapi/v1/jobs/controller.py @@ -92,12 +92,16 @@ def get(self): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] jobs, total_num_jobs = self._job_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -110,6 +114,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_jobs, + sort_by=sort_by_string, + descending=descending, ) diff --git a/src/dioptra/restapi/v1/jobs/errors.py b/src/dioptra/restapi/v1/jobs/errors.py deleted file mode 100644 index bd44e2a51..000000000 --- a/src/dioptra/restapi/v1/jobs/errors.py +++ /dev/null @@ -1,94 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the job endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class JobDoesNotExistError(Exception): - """The requested job does not exist.""" - - -class JobInvalidStatusTransitionError(Exception): - """The requested status transition is invalid.""" - - -class JobInvalidParameterNameError(Exception): - """The requested job parameter name is invalid.""" - - -class JobMlflowRunAlreadySetError(Exception): - """The requested job already has an mlflow run id set.""" - - -class ExperimentJobDoesNotExistError(Exception): - """The requested experiment job does not exist.""" - - -class EntryPointNotRegisteredToExperimentError(Exception): - """The requested entry point is not registered to the provided experiment.""" - - -class QueueNotRegisteredToEntryPointError(Exception): - """The requested queue is not registered to the provided entry point.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(JobDoesNotExistError) - def handle_job_does_not_exist_error(error): - return {"message": "Not Found - The requested job does not exist"}, 404 - - @api.errorhandler(JobInvalidStatusTransitionError) - def handle_job_invalid_status_transition_error(error): - return { - "message": "Bad Request - The requested job status update is invalid" - }, 400 - - @api.errorhandler(JobInvalidParameterNameError) - def handle_job_invalid_parameter_name_error(error): - return { - "message": "Bad Request - A provided job parameter name does not match any " - "entrypoint parameters" - }, 400 - - @api.errorhandler(JobMlflowRunAlreadySetError) - def handle_job_mlflow_run_already_set_error(error): - return { - "message": "Bad Request - The requested job already has an mlflow run id " - "set. It may not be changed." - }, 400 - - @api.errorhandler(ExperimentJobDoesNotExistError) - def handle_experiment_job_does_not_exist_error(error): - return { - "message": "Not Found - The requested experiment job does not exist" - }, 404 - - @api.errorhandler(EntryPointNotRegisteredToExperimentError) - def handle_entry_point_not_registered_to_experiment_error(error): - return { - "message": "Bad Request - The requested entry point is not registered to " - "the provided experiment" - }, 400 - - @api.errorhandler(QueueNotRegisteredToEntryPointError) - def handle_queue_not_registered_to_entry_point_error(error): - return { - "message": "Bad Request - The requested queue is not registered to the " - "provided entry point" - }, 400 diff --git a/src/dioptra/restapi/v1/jobs/schema.py b/src/dioptra/restapi/v1/jobs/schema.py index 5a44a128e..7a0fe01ea 100644 --- a/src/dioptra/restapi/v1/jobs/schema.py +++ b/src/dioptra/restapi/v1/jobs/schema.py @@ -23,6 +23,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -157,6 +158,7 @@ class JobGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /jobs endpoint.""" @@ -164,6 +166,7 @@ class JobGetQueryParameters( class ExperimentJobGetQueryParameters( PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /experiments/{id}/jobs endpoint.""" diff --git a/src/dioptra/restapi/v1/jobs/service.py b/src/dioptra/restapi/v1/jobs/service.py index 0aa1fed14..81a6168bf 100644 --- a/src/dioptra/restapi/v1/jobs/service.py +++ b/src/dioptra/restapi/v1/jobs/service.py @@ -27,25 +27,30 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityNotRegisteredError, + JobInvalidParameterNameError, + JobInvalidStatusTransitionError, + JobMlflowRunAlreadySetError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils +from dioptra.restapi.v1.entrypoints.service import ( + RESOURCE_TYPE as ENTRYPOINT_RESOURCE_TYPE, +) from dioptra.restapi.v1.entrypoints.service import EntrypointIdService +from dioptra.restapi.v1.experiments.service import ( + RESOURCE_TYPE as EXPERIMENT_RESOURCE_TYPE, +) from dioptra.restapi.v1.experiments.service import ExperimentIdService from dioptra.restapi.v1.groups.service import GroupIdService +from dioptra.restapi.v1.queues.service import RESOURCE_TYPE as QUEUE_RESOURCE_TYPE from dioptra.restapi.v1.queues.service import QueueIdService from dioptra.restapi.v1.shared.rq_service import RQServiceV1 from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ( - EntryPointNotRegisteredToExperimentError, - ExperimentJobDoesNotExistError, - JobDoesNotExistError, - JobInvalidParameterNameError, - JobInvalidStatusTransitionError, - JobMlflowRunAlreadySetError, - QueueNotRegisteredToEntryPointError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() RESOURCE_TYPE: Final[str] = "job" @@ -55,6 +60,12 @@ "timeout": lambda x: models.Job.timeout.like(x), "tag": lambda x: models.Job.tags.any(models.Tag.name.like(x, escape="/")), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "description": models.Job.description, + "createdOn": models.Job.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "status": models.Job.status, +} JOB_STATUS_TRANSITIONS: Final[dict[str, Any]] = { "queued": {"started", "deferred"}, "started": {"finished", "failed"}, @@ -118,7 +129,7 @@ def create( The newly created job object. Raises: - JobAlreadyExistsError: If a job with the given name already exists. + EntityExistsError: If a job with the given name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -155,12 +166,12 @@ def create( ) if entrypoint_id not in set(experiment_entry_point_ids): - log.debug( - "Entry point not registered to experiment", - entrypoint_id=entrypoint_id, - experiment_id=experiment_id, + raise EntityNotRegisteredError( + EXPERIMENT_RESOURCE_TYPE, + experiment_id, + ENTRYPOINT_RESOURCE_TYPE, + entrypoint_id, ) - raise EntryPointNotRegisteredToExperimentError # Validate that the provided queue_id is registered to the entrypoint parent_entry_point = aliased(models.EntryPoint) @@ -183,12 +194,9 @@ def create( ) if queue_id not in set(entry_point_queue_ids): - log.debug( - "Queue not registered to entry point", - queue_id=queue_id, - entrypoint_id=entrypoint_id, + raise EntityNotRegisteredError( + ENTRYPOINT_RESOURCE_TYPE, entrypoint_id, QUEUE_RESOURCE_TYPE, queue_id ) - raise QueueNotRegisteredToEntryPointError # Fetch the validated queue queue_dict = cast( @@ -274,6 +282,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.JobDict], int]: """Fetch a list of jobs, optionally filtering by search string and paging @@ -284,6 +294,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of jobs to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of jobs and the total number of jobs matching @@ -339,6 +351,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + jobs_stmt = jobs_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + jobs = list(db.session.scalars(jobs_stmt).all()) job_dicts: dict[int, utils.JobDict] = { @@ -385,7 +408,7 @@ def get( The job object if found, otherwise None. Raises: - JobDoesNotExistError: If the job is not found and `error_if_not_found` + EntityDoesNotExistError: If the job is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -404,8 +427,7 @@ def get( if job is None: if error_if_not_found: - log.debug("Job not found", job_id=job_id) - raise JobDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, job_id=job_id) return None @@ -442,7 +464,7 @@ def delete(self, job_id: int, **kwargs) -> dict[str, Any]: job_resource = db.session.scalars(stmt).first() if job_resource is None: - raise JobDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, job_id=job_id) deleted_resource_lock = models.ResourceLock( resource_lock_type="delete", @@ -500,8 +522,7 @@ def get( job = db.session.scalars(stmt).first() if job is None: - log.debug("Job not found", job_id=job_id) - raise JobDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, job_id=job_id) return {"status": job.status, "id": job.resource_id} @@ -566,6 +587,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.JobDict], int]: """Fetch a list of jobs for a given experiment, optionally filtering by search @@ -576,13 +599,15 @@ def get( search_string: A search string used to filter results. page_index: The index of the first page to be returned. page_length: The maximum number of experiments to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of jobs and the total number of jobs matching the query. Raises: - ExperimentDoesNotExistError: If the experiment is not found. + EntityDoesNotExistError: If the experiment is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug("Get full list of jobs for experiment", experiment_id=experiment_id) @@ -638,6 +663,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + jobs_stmt = jobs_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + jobs = list(db.session.scalars(jobs_stmt).all()) job_dicts: dict[int, utils.JobDict] = { @@ -682,7 +718,7 @@ def get(self, experiment_id: int, job_id: int, **kwargs) -> utils.JobDict: The job object if found, otherwise None. Raises: - ExperimentJobDoesNotExistError: If the job associated with the experiment + EntityDoesNotExistError: If the job associated with the experiment is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -694,12 +730,9 @@ def get(self, experiment_id: int, job_id: int, **kwargs) -> utils.JobDict: experiment_job = db.session.scalar(experiment_job_stmt) if experiment_job is None: - log.debug( - "Experiment Job not found", - job_id=job_id, - experiment_id=experiment_id, + raise EntityDoesNotExistError( + RESOURCE_TYPE, job_id=job_id, experiment_id=experiment_id ) - raise ExperimentJobDoesNotExistError return cast( utils.JobDict, @@ -729,12 +762,9 @@ def delete(self, experiment_id: int, job_id: int, **kwargs) -> dict[str, Any]: experiment_job = db.session.scalar(experiment_job_stmt) if experiment_job is None: - log.debug( - "Job associated with experiment not found", - job_id=job_id, - experiment_id=experiment_id, + raise EntityDoesNotExistError( + RESOURCE_TYPE, job_id=job_id, experiment_id=experiment_id ) - raise ExperimentJobDoesNotExistError return self._job_id_service.delete( job_id=job_id, diff --git a/src/dioptra/restapi/v1/models/__init__.py b/src/dioptra/restapi/v1/models/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/models/__init__.py +++ b/src/dioptra/restapi/v1/models/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/models/controller.py b/src/dioptra/restapi/v1/models/controller.py index ab97b0ba6..e9c6c0c75 100644 --- a/src/dioptra/restapi/v1/models/controller.py +++ b/src/dioptra/restapi/v1/models/controller.py @@ -99,12 +99,16 @@ def get(self): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] models, total_num_models = self._model_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -117,6 +121,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_models, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/models/errors.py b/src/dioptra/restapi/v1/models/errors.py deleted file mode 100644 index fb87d885c..000000000 --- a/src/dioptra/restapi/v1/models/errors.py +++ /dev/null @@ -1,54 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the model endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class ModelAlreadyExistsError(Exception): - """The model name already exists.""" - - -class ModelDoesNotExistError(Exception): - """The requested model does not exist.""" - - -class ModelVersionDoesNotExistError(Exception): - """The requested version of the model does not exist.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(ModelDoesNotExistError) - def handle_model_does_not_exist_error(error): - return {"message": "Not Found - The requested model does not exist"}, 404 - - @api.errorhandler(ModelVersionDoesNotExistError) - def handle_model_version_does_not_exist_error(error): - return { - "message": "Not Found - The requested model version does not exist" - }, 404 - - @api.errorhandler(ModelAlreadyExistsError) - def handle_model_already_exists_error(error): - return ( - { - "message": "Bad Request - The model name on the registration form " - "already exists. Please select another and resubmit." - }, - 400, - ) diff --git a/src/dioptra/restapi/v1/models/schema.py b/src/dioptra/restapi/v1/models/schema.py index ae23cd7b7..fc6ac768d 100644 --- a/src/dioptra/restapi/v1/models/schema.py +++ b/src/dioptra/restapi/v1/models/schema.py @@ -23,6 +23,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -157,6 +158,7 @@ class ModelGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /models endpoint.""" diff --git a/src/dioptra/restapi/v1/models/service.py b/src/dioptra/restapi/v1/models/service.py index 2f12922f9..7bfd6bf18 100644 --- a/src/dioptra/restapi/v1/models/service.py +++ b/src/dioptra/restapi/v1/models/service.py @@ -27,18 +27,17 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils from dioptra.restapi.v1.artifacts.service import ArtifactIdService from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ( - ModelAlreadyExistsError, - ModelDoesNotExistError, - ModelVersionDoesNotExistError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() MODEL_RESOURCE_TYPE: Final[str] = "ml_model" @@ -50,6 +49,12 @@ MODEL_VERSION_SEARCHABLE_FIELDS: Final[dict[str, Any]] = { "description": lambda x: models.MlModelVersion.description.like(x, escape="/"), } +MODEL_SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.MlModel.name, + "createdOn": models.MlModel.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.MlModel.description, +} class ModelService(object): @@ -93,13 +98,15 @@ def create( The newly created model object. Raises: - ModelAlreadyExistsError: If a model with the given name already exists. + EntityExistsError: If a model with the given name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._model_name_service.get(name, group_id=group_id, log=log) is not None: - log.debug("Model name already exists", name=name, group_id=group_id) - raise ModelAlreadyExistsError + duplicate = self._model_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + MODEL_RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) group = self._group_id_service.get(group_id, error_if_not_found=True) @@ -132,6 +139,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> Any: """Fetch a list of models, optionally filtering by search string and paging @@ -142,6 +151,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of models to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of models and the total number of models matching @@ -200,6 +211,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in MODEL_SORTABLE_FIELDS: + sort_column = MODEL_SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + latest_ml_models_stmt = latest_ml_models_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in MODEL_SORTABLE_FIELDS: + raise SortParameterValidationError(MODEL_RESOURCE_TYPE, sort_by_string) + ml_models = db.session.scalars(latest_ml_models_stmt).all() # extract list of model ids @@ -301,7 +323,7 @@ def get( The model object if found, otherwise None. Raises: - ModelDoesNotExistError: If the model is not found and `error_if_not_found` + EntityDoesNotExistError: If the model is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -321,8 +343,7 @@ def get( if ml_model is None: if error_if_not_found: - log.debug("Model not found", model_id=model_id) - raise ModelDoesNotExistError + raise EntityDoesNotExistError(MODEL_RESOURCE_TYPE, model_id=model_id) return None @@ -379,9 +400,9 @@ def modify( The updated model object. Raises: - ModelDoesNotExistError: If the model is not found and `error_if_not_found` + EntityDoesNotExistError: If the model is not found and `error_if_not_found` is True. - ModelAlreadyExistsError: If the model name already exists. + EntityExistsError: If the model name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -390,9 +411,6 @@ def modify( ) if ml_model_dict is None: - if error_if_not_found: - raise ModelDoesNotExistError - return None ml_model = ml_model_dict["ml_model"] @@ -400,13 +418,15 @@ def modify( has_draft = ml_model_dict["has_draft"] group_id = ml_model.resource.group_id - if ( - name != ml_model.name - and self._model_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Model name already exists", name=name, group_id=group_id) - raise ModelAlreadyExistsError + if name != ml_model.name: + duplicate = self._model_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + MODEL_RESOURCE_TYPE, + duplicate.resource_id, + name=name, + group_id=group_id, + ) new_ml_model = models.MlModel( name=name, @@ -448,7 +468,7 @@ def delete(self, model_id: int, **kwargs) -> dict[str, Any]: model_resource = db.session.scalars(stmt).first() if model_resource is None: - raise ModelDoesNotExistError + raise EntityDoesNotExistError(MODEL_RESOURCE_TYPE, model_id=model_id) deleted_resource_lock = models.ResourceLock( resource_lock_type="delete", @@ -569,7 +589,7 @@ def get( None. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -680,11 +700,11 @@ def get( The requested version the resource object if found, otherwise None. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - log.debug("Get resource snaphot by id", model_id=model_id) + log.debug("Get resource snapshot by id", model_id=model_id) ml_model_dict = self._model_id_service.get( model_id, error_if_not_found=error_if_not_found, log=log @@ -710,8 +730,11 @@ def get( if latest_version is None: if error_if_not_found: - log.debug("Model version not found", version_number=version_number) - raise ModelVersionDoesNotExistError + raise EntityDoesNotExistError( + MODEL_VERSION_RESOURCE_TYPE, + model_id=model_id, + version_number=version_number, + ) return None @@ -741,9 +764,9 @@ def modify( The updated model object. Raises: - ModelDoesNotExistError: If the model is not found and `error_if_not_found` + EntityDoesNotExistError: If the model is not found and `error_if_not_found` is True. - ModelAlreadyExistsError: If the model name already exists. + EntityExistsError: If the model name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -802,7 +825,7 @@ def get( The model object if found, otherwise None. Raises: - ModelDoesNotExistError: If the model is not found and `error_if_not_found` + EntityDoesNotExistError: If the model is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -823,8 +846,9 @@ def get( if ml_model is None: if error_if_not_found: - log.debug("Model not found", name=name) - raise ModelDoesNotExistError + raise EntityDoesNotExistError( + MODEL_RESOURCE_TYPE, name=name, group_id=group_id + ) return None diff --git a/src/dioptra/restapi/v1/plugin_parameter_types/__init__.py b/src/dioptra/restapi/v1/plugin_parameter_types/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/plugin_parameter_types/__init__.py +++ b/src/dioptra/restapi/v1/plugin_parameter_types/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/plugin_parameter_types/controller.py b/src/dioptra/restapi/v1/plugin_parameter_types/controller.py index 84830c9e9..a16727f46 100644 --- a/src/dioptra/restapi/v1/plugin_parameter_types/controller.py +++ b/src/dioptra/restapi/v1/plugin_parameter_types/controller.py @@ -96,6 +96,8 @@ def get(self): search_string = parsed_query_params["search"] page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] ( plugin_parameter_types, @@ -105,6 +107,8 @@ def get(self): search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -117,6 +121,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_plugin_param_types, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/plugin_parameter_types/errors.py b/src/dioptra/restapi/v1/plugin_parameter_types/errors.py deleted file mode 100644 index 4ff36220a..000000000 --- a/src/dioptra/restapi/v1/plugin_parameter_types/errors.py +++ /dev/null @@ -1,84 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the plugin parameter type endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class PluginParameterTypeMatchesBuiltinTypeError(Exception): - """The plugin parameter type name cannot match a built-in type.""" - - -class PluginParameterTypeAlreadyExistsError(Exception): - """The plugin parameter type name already exists.""" - - -class PluginParameterTypeDoesNotExistError(Exception): - """The requested plugin parameter type does not exist.""" - - -class PluginParameterTypeReadOnlyLockError(Exception): - """The plugin parameter type has a read-only lock and cannot be modified.""" - - -class PluginParameterTypeMissingParameterError(Exception): - """The requested plugin parameter type is missing a required parameter.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(PluginParameterTypeMatchesBuiltinTypeError) - def handle_plugin_parameter_type_matches_builtin_type_error(error): - return { - "message": "Bad Request - The requested plugin parameter type name " - "matches a built-in type. Please select another and resubmit." - }, 400 - - @api.errorhandler(PluginParameterTypeDoesNotExistError) - def handle_plugin_parameter_type_does_not_exist_error(error): - return { - "message": "Not Found - The requested plugin parameter type does " - "not exist" - }, 404 - - @api.errorhandler(PluginParameterTypeReadOnlyLockError) - def handle_plugin_parameter_type_read_only_lock_error(error): - return { - "message": "Forbidden - The plugin parameter type has a read-only " - "lock and cannot be modified." - }, 403 - - @api.errorhandler(PluginParameterTypeMissingParameterError) - def handle_plugin_parameter_type_missing_parameter_error(error): - return ( - { - "message": "Forbidden - The requested plugin parameter " - "type is missing a required parameter." - }, - 400, - ) - - @api.errorhandler(PluginParameterTypeAlreadyExistsError) - def handle_plugin_parameter_type_already_exists_error(error): - return ( - { - "message": "Bad Request - The plugin parameter type name on " - "the registration form already exists. Please select " - "another and resubmit." - }, - 400, - ) diff --git a/src/dioptra/restapi/v1/plugin_parameter_types/schema.py b/src/dioptra/restapi/v1/plugin_parameter_types/schema.py index b059d8b7c..c556f6309 100644 --- a/src/dioptra/restapi/v1/plugin_parameter_types/schema.py +++ b/src/dioptra/restapi/v1/plugin_parameter_types/schema.py @@ -22,6 +22,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -87,6 +88,7 @@ class PluginParameterTypeGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /pluginParameterTypes endpoint.""" diff --git a/src/dioptra/restapi/v1/plugin_parameter_types/service.py b/src/dioptra/restapi/v1/plugin_parameter_types/service.py index b66f5c13f..e4ce40fa8 100644 --- a/src/dioptra/restapi/v1/plugin_parameter_types/service.py +++ b/src/dioptra/restapi/v1/plugin_parameter_types/service.py @@ -25,19 +25,19 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import resource_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + PluginParameterTypeMatchesBuiltinTypeError, + ReadOnlyLockError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters from dioptra.task_engine.type_registry import BUILTIN_TYPES -from .errors import ( - PluginParameterTypeAlreadyExistsError, - PluginParameterTypeDoesNotExistError, - PluginParameterTypeMatchesBuiltinTypeError, - PluginParameterTypeReadOnlyLockError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() RESOURCE_TYPE: Final[str] = "plugin_task_parameter_type" @@ -50,6 +50,12 @@ models.Tag.name.like(x, escape="/") ), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.PluginTaskParameterType.name, + "createdOn": models.PluginTaskParameterType.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.PluginTaskParameterType.description, +} class PluginParameterTypeService(object): @@ -100,8 +106,8 @@ def create( Raises: PluginParameterTypeMatchesBuiltinTypeError: If the plugin parameter type name matches a built-in type. - PluginParameterTypeAlreadyExistsError: If a plugin parameter type - with the given name already exists. + EntityExistsError: If a plugin parameter type with the given name already + exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -113,18 +119,13 @@ def create( ) raise PluginParameterTypeMatchesBuiltinTypeError - if ( - self._plugin_parameter_type_name_service.get( - name, group_id=group_id, log=log - ) - is not None - ): - log.debug( - "Plugin Parameter Type name already exists", - name=name, - group_id=group_id, + duplicate = self._plugin_parameter_type_name_service.get( + name, group_id=group_id, log=log + ) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id ) - raise PluginParameterTypeAlreadyExistsError group = self._group_id_service.get(group_id, error_if_not_found=True) @@ -156,6 +157,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.PluginParameterTypeDict], int]: """Fetch a list of plugin parameter types, optionally filtering by @@ -167,6 +170,8 @@ def get( page_index: The index of the first group to be returned. page_length: The maximum number of plugin parameter types to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of plugin parameter types and the total @@ -225,6 +230,19 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + plugin_parameter_types_stmt = plugin_parameter_types_stmt.order_by( + sort_column + ) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + plugin_parameter_types = list( db.session.scalars(plugin_parameter_types_stmt).all() ) @@ -294,7 +312,7 @@ def get( The plugin parameter type object if found, otherwise None. Raises: - PluginParameterTypeDoesNotExistError: If the plugin parameter type + EntityDoesNotExistError: If the plugin parameter type is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -317,11 +335,9 @@ def get( if plugin_parameter_type is None: if error_if_not_found: - log.debug( - "Plugin Parameter Type not found", - plugin_parameter_type_id=plugin_parameter_type_id, + raise EntityDoesNotExistError( + RESOURCE_TYPE, plugin_parameter_type_id=plugin_parameter_type_id ) - raise PluginParameterTypeDoesNotExistError return None @@ -368,9 +384,9 @@ def modify( The updated plugin parameter type object. Raises: - PluginParameterTypeDoesNotExistError: If the plugin parameter type + EntityDoesNotExistError: If the plugin parameter type is not found and `error_if_not_found` is True. - PluginParameterTypeAlreadyExistsError: If the plugin parameter type + EntityExistsError: If the plugin parameter type name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -386,12 +402,11 @@ def modify( group_id = plugin_parameter_type.resource.group_id if plugin_parameter_type.resource.is_readonly: - log.debug( - "The Plugin Parameter Type is read-only and cannot be modified", + raise ReadOnlyLockError( + RESOURCE_TYPE, plugin_parameter_type_id=plugin_parameter_type_id, name=plugin_parameter_type.name, ) - raise PluginParameterTypeReadOnlyLockError if name.strip().lower() in BUILTIN_TYPES: log.debug( @@ -401,19 +416,14 @@ def modify( ) raise PluginParameterTypeMatchesBuiltinTypeError - if ( - name != plugin_parameter_type.name - and self._plugin_parameter_type_name_service.get( + if name != plugin_parameter_type.name: + duplicate = self._plugin_parameter_type_name_service.get( name, group_id=group_id, log=log ) - is not None - ): - log.debug( - "Plugin Parameter Type name already exists", - name=name, - group_id=group_id, - ) - raise PluginParameterTypeAlreadyExistsError + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) new_plugin_parameter_type = models.PluginTaskParameterType( name=name, @@ -457,14 +467,14 @@ def delete(self, plugin_parameter_type_id: int, **kwargs) -> dict[str, Any]: plugin_parameter_type_resource = db.session.scalars(stmt).first() if plugin_parameter_type_resource is None: - raise PluginParameterTypeDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, plugin_parameter_type_id=plugin_parameter_type_id + ) if plugin_parameter_type_resource.is_readonly: - log.debug( - "The Plugin Parameter Type is read-only and cannot be deleted", - plugin_parameter_type_id=plugin_parameter_type_id, + raise ReadOnlyLockError( + RESOURCE_TYPE, plugin_parameter_type_id=plugin_parameter_type_id ) - raise PluginParameterTypeReadOnlyLockError deleted_resource_lock = models.ResourceLock( resource_lock_type=resource_lock_types.DELETE, @@ -505,7 +515,7 @@ def get( The plugin parameter type object if found, otherwise None. Raises: - PluginParameterTypeDoesNotExistError: If the plugin parameter type + EntityDoesNotExistError: If the plugin parameter type is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -530,8 +540,9 @@ def get( if plugin_parameter_type is None: if error_if_not_found: - log.debug("Plugin Parameter Type not found", name=name) - raise PluginParameterTypeDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, name=name, group_id=group_id + ) return None diff --git a/src/dioptra/restapi/v1/plugins/__init__.py b/src/dioptra/restapi/v1/plugins/__init__.py index 8b612d5e8..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/plugins/__init__.py +++ b/src/dioptra/restapi/v1/plugins/__init__.py @@ -14,7 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode - -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/plugins/controller.py b/src/dioptra/restapi/v1/plugins/controller.py index b4cad92ee..5a9992eaf 100644 --- a/src/dioptra/restapi/v1/plugins/controller.py +++ b/src/dioptra/restapi/v1/plugins/controller.py @@ -78,7 +78,7 @@ # WARNING: Do not move the PluginFile Snapshots sub-endpoint definitions. -# They must be declared first because of an issue related interations with the schemas. +# They must be declared first because of an issue related interactions with the schemas. PluginFileSnapshotsResource = generate_nested_resource_snapshots_endpoint( api=api, resource_model=models.PluginFile, @@ -127,12 +127,16 @@ def get(self): search_string = parsed_query_params["search"] page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] plugins, total_num_plugins = self._plugin_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -145,6 +149,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_plugins, + sort_by=sort_by_string, + descending=descending, ) @login_required @@ -261,12 +267,16 @@ def get(self, id: int): search_string = parsed_query_params["search"] page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] plugin_files, total_num_plugin_files = self._plugin_id_file_service.get( plugin_id=id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) @@ -280,6 +290,8 @@ def get(self, id: int): index=page_index, length=page_length, total_num_elements=total_num_plugin_files, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/plugins/errors.py b/src/dioptra/restapi/v1/plugins/errors.py deleted file mode 100644 index 90ab703d0..000000000 --- a/src/dioptra/restapi/v1/plugins/errors.py +++ /dev/null @@ -1,110 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the plugin endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class PluginAlreadyExistsError(Exception): - """The plugin name already exists.""" - - -class PluginDoesNotExistError(Exception): - """The requested plugin does not exist.""" - - -class PluginFileAlreadyExistsError(Exception): - """The plugin file filename already exists.""" - - -class PluginFileDoesNotExistError(Exception): - """The requested plugin file does not exist.""" - - -class PluginTaskParameterTypeNotFoundError(Exception): - """One ore more referenced plugin task parameter types were not found.""" - - -class PluginTaskNameAlreadyExistsError(Exception): - """More than one plugin task is being assigned the same name.""" - - -class PluginTaskInputParameterNameAlreadyExistsError(Exception): - """More than one plugin task input parameter is being assigned the same name.""" - - -class PluginTaskOutputParameterNameAlreadyExistsError(Exception): - """More than one plugin task output parameter is being assigned the same name.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(PluginDoesNotExistError) - def handle_plugin_does_not_exist_error(error): - return {"message": "Not Found - The requested plugin does not exist"}, 404 - - @api.errorhandler(PluginAlreadyExistsError) - def handle_plugin_already_exists_error(error): - return ( - { - "message": "Bad Request - The plugin name on the registration form " - "already exists. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(PluginFileDoesNotExistError) - def handle_plugin_file_does_not_exist_error(error): - return {"message": "Not Found - The requested plugin file does not exist"}, 404 - - @api.errorhandler(PluginFileAlreadyExistsError) - def handle_plugin_file_already_exists_error(error): - return ( - { - "message": "Bad Request - The plugin file filename on the " - "registration form already exists. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(PluginTaskParameterTypeNotFoundError) - def handle_plugin_task_parameter_type_not_found_error(error): - return { - "message": "Bad Request - One or more referenced plugin task parameter " - "types were not found." - }, 400 - - @api.errorhandler(PluginTaskNameAlreadyExistsError) - def handle_plugin_task_name_already_exists_error(error): - return { - "message": "Bad Request - More than one plugin task is being assigned the " - "same name." - }, 400 - - @api.errorhandler(PluginTaskInputParameterNameAlreadyExistsError) - def handle_plugin_task_input_parameter_name_already_exists_error(error): - return { - "message": "Bad Request - More than one plugin task input parameter is " - "being assigned the same name." - }, 400 - - @api.errorhandler(PluginTaskOutputParameterNameAlreadyExistsError) - def handle_plugin_task_output_parameter_name_already_exists_error(error): - return { - "message": "Bad Request - More than one plugin task output parameter is " - "being assigned the same name." - }, 400 diff --git a/src/dioptra/restapi/v1/plugins/schema.py b/src/dioptra/restapi/v1/plugins/schema.py index 3eacc964a..410b4ece7 100644 --- a/src/dioptra/restapi/v1/plugins/schema.py +++ b/src/dioptra/restapi/v1/plugins/schema.py @@ -27,6 +27,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -220,6 +221,7 @@ class PluginGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /plugins endpoint.""" @@ -286,5 +288,6 @@ class PluginFilePageSchema(BasePageSchema): class PluginFileGetQueryParameters( PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /plugins/{id}/files/ endpoint.""" diff --git a/src/dioptra/restapi/v1/plugins/service.py b/src/dioptra/restapi/v1/plugins/service.py index b41926ad8..fadb12ec4 100644 --- a/src/dioptra/restapi/v1/plugins/service.py +++ b/src/dioptra/restapi/v1/plugins/service.py @@ -29,22 +29,18 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import resource_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + QueryParameterNotUniqueError, + SortParameterValidationError, +) +from dioptra.restapi.utils import find_non_unique from dioptra.restapi.v1 import utils from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ( - PluginAlreadyExistsError, - PluginDoesNotExistError, - PluginFileAlreadyExistsError, - PluginFileDoesNotExistError, - PluginTaskInputParameterNameAlreadyExistsError, - PluginTaskNameAlreadyExistsError, - PluginTaskOutputParameterNameAlreadyExistsError, - PluginTaskParameterTypeNotFoundError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() PLUGIN_RESOURCE_TYPE: Final[str] = "plugin" @@ -58,6 +54,18 @@ "description": lambda x: models.PluginFile.description.like(x, escape="/"), "contents": lambda x: models.PluginFile.contents.like(x, escape="/"), } +PLUGIN_SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.Plugin.name, + "createdOn": models.Plugin.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.Plugin.description, +} +PLUGIN_FILE_SORTABLE_FIELDS: Final[dict[str, Any]] = { + "filename": models.PluginFile.filename, + "createdOn": models.PluginFile.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.PluginFile.description, +} class PluginService(object): @@ -92,13 +100,18 @@ def create( The newly created plugin object. Raises: - PluginAlreadyExistsError: If a plugin with the given name already exists. + EntityExistsError: If a plugin with the given name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._plugin_name_service.get(name, group_id=group_id, log=log) is not None: - log.debug("Plugin name already exists", name=name, group_id=group_id) - raise PluginAlreadyExistsError + duplicate = self._plugin_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + PLUGIN_RESOURCE_TYPE, + duplicate.resource_id, + name=name, + group_id=group_id, + ) group = self._group_id_service.get(group_id, error_if_not_found=True) @@ -127,6 +140,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.PluginWithFilesDict], int]: """Fetch a list of plugins, optionally filtering by search string and paging @@ -137,6 +152,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of plugins to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of plugins and the total number of plugins @@ -196,6 +213,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in PLUGIN_SORTABLE_FIELDS: + sort_column = PLUGIN_SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + latest_plugins_stmt = latest_plugins_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in PLUGIN_SORTABLE_FIELDS: + raise SortParameterValidationError(PLUGIN_RESOURCE_TYPE, sort_by_string) + plugins = db.session.scalars(latest_plugins_stmt).all() # extract list of plugin ids @@ -296,7 +324,7 @@ def get( The plugin object if found, otherwise None. Raises: - PluginDoesNotExistError: If the plugin is not found and `error_if_not_found` + EntityDoesNotExistError: If the plugin is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -316,8 +344,7 @@ def get( if plugin is None: if error_if_not_found: - log.debug("Plugin not found", plugin_id=plugin_id) - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) return None @@ -372,9 +399,9 @@ def modify( The updated plugin object. Raises: - PluginDoesNotExistError: If the plugin is not found and `error_if_not_found` + EntityDoesNotExistError: If the plugin is not found and `error_if_not_found` is True. - PluginAlreadyExistsError: If the plugin name already exists. + EntityExistsError: If the plugin name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -389,13 +416,15 @@ def modify( plugin_files = plugin_dict["plugin_files"] group_id = plugin.resource.group_id - if ( - name != plugin.name - and self._plugin_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Plugin name already exists", name=name, group_id=group_id) - raise PluginAlreadyExistsError + if name != plugin.name: + duplicate = self._plugin_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + PLUGIN_RESOURCE_TYPE, + duplicate.resource_id, + name=name, + group_id=group_id, + ) new_plugin = models.Plugin( name=name, @@ -435,7 +464,7 @@ def delete(self, plugin_id: int, **kwargs) -> dict[str, Any]: plugin_resource = db.session.scalar(stmt) if plugin_resource is None: - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) deleted_resource_lock = models.ResourceLock( resource_lock_type=resource_lock_types.DELETE, @@ -468,11 +497,9 @@ def get( A list of plugin objects. Raises: - PluginDoesNotExistError: If the plugin is not found and `error_if_not_found` + EntityDoesNotExistError: If the plugin is not found and `error_if_not_found` is True. """ - log: BoundLogger = kwargs.get("log", LOGGER.new()) - latest_plugins_stmt = ( select(models.Plugin) .join(models.Resource) @@ -489,8 +516,9 @@ def get( plugin_ids_missing = set(plugin_ids) - set( plugin.resource_id for plugin in plugins ) - log.debug("Plugin not found", plugin_ids=list(plugin_ids_missing)) - raise PluginDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_RESOURCE_TYPE, plugin_ids=list(plugin_ids_missing) + ) # extract list of plugin ids plugin_ids = [plugin.resource_id for plugin in plugins] @@ -578,7 +606,7 @@ def get( The plugin object if found, otherwise None. Raises: - PluginDoesNotExistError: If the plugin is not found and `error_if_not_found` + EntityDoesNotExistError: If the plugin is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -599,8 +627,9 @@ def get( if plugin is None: if error_if_not_found: - log.debug("Plugin not found", name=name) - raise PluginDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_RESOURCE_TYPE, name=name, group_id=group_id + ) return plugin @@ -623,7 +652,7 @@ def get( The plugin file object if found, otherwise None. Raises: - PluginFileDoesNotExistError: If the plugin is not found and + EntityDoesNotExistError: If the plugin is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -648,8 +677,9 @@ def get( if plugin_file is None: if error_if_not_found: - log.debug("Plugin file not found", filename=filename) - raise PluginFileDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_FILE_RESOURCE_TYPE, plugin_id=plugin_id, filename=filename + ) return None @@ -704,7 +734,7 @@ def create( The newly created plugin file object. Raises: - PluginFileAlreadyExistsError: If a plugin file with the given filename + EntityExistsError: If a plugin file with the given filename already exists. """ @@ -718,14 +748,16 @@ def create( ) # Validate that the proposed filename hasn't already been used in the plugin. - if ( - self._plugin_file_name_service.get(filename, plugin_id=plugin_id, log=log) - is not None - ): - log.debug( - "Plugin filename already exists", filename=filename, plugin_id=plugin_id + duplicate = self._plugin_file_name_service.get( + filename, plugin_id=plugin_id, log=log + ) + if duplicate is not None: + raise EntityExistsError( + PLUGIN_FILE_RESOURCE_TYPE, + duplicate.resource_id, + filename=filename, + plugin_id=plugin_id, ) - raise PluginFileAlreadyExistsError # The owner of the PluginFile resource must match the owner of the Plugin # resource. @@ -764,6 +796,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.PluginFileDict], int]: """Fetch a list of plugin files associated with a plugin, optionally @@ -774,6 +808,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of plugins to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of plugins and the total number of plugins @@ -815,8 +851,7 @@ def get( plugin = db.session.scalar(latest_plugin_stmt) if plugin is None: - log.debug("Plugin not found", plugin_id=plugin_id) - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) latest_plugin_files_count_stmt = ( select(func.count(models.PluginFile.resource_id)) @@ -855,6 +890,19 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in PLUGIN_FILE_SORTABLE_FIELDS: + sort_column = PLUGIN_FILE_SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + latest_plugin_files_stmt = latest_plugin_files_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in PLUGIN_FILE_SORTABLE_FIELDS: + raise SortParameterValidationError( + PLUGIN_FILE_RESOURCE_TYPE, sort_by_string + ) + plugin_files_dict: dict[int, utils.PluginFileDict] = { plugin_file.resource_id: utils.PluginFileDict( plugin=plugin, plugin_file=plugin_file, has_draft=False @@ -899,7 +947,7 @@ def delete(self, plugin_id: int, **kwargs) -> dict[str, Any]: plugin_resource = db.session.scalar(stmt) if plugin_resource is None: - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) latest_plugin_files_stmt = ( select(models.PluginFile) @@ -960,7 +1008,7 @@ def get( The plugin object if found, otherwise None. Raises: - PluginDoesNotExistError: If the plugin or plugin file is not found and + EntityDoesNotExistError: If the plugin or plugin file is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -982,8 +1030,7 @@ def get( if plugin is None: if error_if_not_found: - log.debug("Plugin not found", plugin_id=plugin_id) - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) return None @@ -1002,8 +1049,11 @@ def get( if plugin_file is None: if error_if_not_found: - log.debug("Plugin file not found", plugin_file_id=plugin_file_id) - raise PluginFileDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_FILE_RESOURCE_TYPE, + plugin_id=plugin_id, + plugin_file_id=plugin_file_id, + ) return None @@ -1052,7 +1102,7 @@ def modify( The updated plugin file object. Raises: - PluginDoesNotExistError: If the plugin or plugin file is not found and + EntityDoesNotExistError: If the plugin or plugin file is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -1070,17 +1120,17 @@ def modify( plugin = plugin_file_dict["plugin"] plugin_file = plugin_file_dict["plugin_file"] - if ( - filename != plugin_file.filename - and self._plugin_file_name_service.get( + if filename != plugin_file.filename: + duplicate = self._plugin_file_name_service.get( filename, plugin_id=plugin_id, log=log ) - is not None - ): - log.debug( - "Plugin filename already exists", filename=filename, plugin_id=plugin_id - ) - raise PluginFileAlreadyExistsError + if duplicate is not None: + raise EntityExistsError( + PLUGIN_FILE_RESOURCE_TYPE, + duplicate.resource_id, + filename=filename, + plugin_id=plugin_id, + ) updated_plugin_file = models.PluginFile( filename=filename, @@ -1123,7 +1173,7 @@ def delete(self, plugin_id: int, plugin_file_id: int, **kwargs) -> dict[str, Any plugin_resource = db.session.scalar(stmt) if plugin_resource is None: - raise PluginDoesNotExistError + raise EntityDoesNotExistError(PLUGIN_RESOURCE_TYPE, plugin_id=plugin_id) plugin_file_stmt = ( select(models.PluginFile) @@ -1139,7 +1189,11 @@ def delete(self, plugin_id: int, plugin_file_id: int, **kwargs) -> dict[str, Any plugin_file = db.session.scalar(plugin_file_stmt) if plugin_file is None: - raise PluginFileDoesNotExistError + raise EntityDoesNotExistError( + PLUGIN_FILE_RESOURCE_TYPE, + plugin_id=plugin_id, + plugin_file_id=plugin_file_id, + ) plugin_file_id_to_return = plugin_file.resource_id # to return to user db.session.add( @@ -1164,27 +1218,21 @@ def _construct_plugin_task( parameter_types_id_to_orm: dict[int, models.PluginTaskParameterType], log: BoundLogger, ) -> models.PluginTask: - input_param_names = [x["name"] for x in task["input_params"]] - unique_input_param_names = set(input_param_names) - - if len(unique_input_param_names) != len(input_param_names): - log.error( - "One or more input parameters have the same name", + duplicates = find_non_unique("name", task["input_params"]) + if len(duplicates) > 0: + raise QueryParameterNotUniqueError( + "plugin task input parameter", plugin_task_name=task["name"], - input_param_names=input_param_names, + input_param_names=duplicates, ) - raise PluginTaskInputParameterNameAlreadyExistsError - output_param_names = [x["name"] for x in task["output_params"]] - unique_output_param_names = set(output_param_names) - - if len(unique_output_param_names) != len(output_param_names): - log.error( - "One or more output parameters have the same name", + duplicates = find_non_unique("name", task["output_params"]) + if len(duplicates) > 0: + raise QueryParameterNotUniqueError( + "plugin task output parameter", plugin_task_name=task["name"], - output_param_names=output_param_names, + output_param_names=duplicates, ) - raise PluginTaskOutputParameterNameAlreadyExistsError input_parameters_list = [] for parameter_number, input_param in enumerate(task["input_params"]): @@ -1256,13 +1304,12 @@ def _get_referenced_parameter_types( if not len(parameter_types) == len(parameter_type_ids): returned_parameter_type_ids = set([x.resource_id for x in parameter_types]) ids_not_found = parameter_type_ids - returned_parameter_type_ids - log.error( - "One or more referenced plugin task parameter types were not found", + raise EntityDoesNotExistError( + "plugin task parameter types", num_expected=len(parameter_type_ids), num_found=len(parameter_types), ids_not_found=sorted(list(ids_not_found)), ) - raise PluginTaskParameterTypeNotFoundError return {x.resource_id: x for x in parameter_types} @@ -1273,12 +1320,9 @@ def _add_plugin_tasks( if not tasks: return None - task_names = [x["name"] for x in tasks] - unique_task_names = set(task_names) - - if len(unique_task_names) != len(tasks): - log.error("One or more tasks have the same name", task_names=task_names) - raise PluginTaskNameAlreadyExistsError + duplicates = find_non_unique("name", tasks) + if len(duplicates) > 0: + raise QueryParameterNotUniqueError("plugin task", task_names=duplicates) parameter_types_id_to_orm = _get_referenced_parameter_types(tasks, log=log) or {} for task in tasks: diff --git a/src/dioptra/restapi/v1/queues/__init__.py b/src/dioptra/restapi/v1/queues/__init__.py index f2c5735af..c68b10594 100644 --- a/src/dioptra/restapi/v1/queues/__init__.py +++ b/src/dioptra/restapi/v1/queues/__init__.py @@ -14,7 +14,6 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors from .controller import api -__all__ = ["api", "errors"] +__all__ = ["api"] diff --git a/src/dioptra/restapi/v1/queues/controller.py b/src/dioptra/restapi/v1/queues/controller.py index 6f7e6f11f..2540370a5 100644 --- a/src/dioptra/restapi/v1/queues/controller.py +++ b/src/dioptra/restapi/v1/queues/controller.py @@ -86,12 +86,16 @@ def get(self): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] queues, total_num_queues = self._queue_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -104,6 +108,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_queues, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/queues/errors.py b/src/dioptra/restapi/v1/queues/errors.py deleted file mode 100644 index b7fe2f04f..000000000 --- a/src/dioptra/restapi/v1/queues/errors.py +++ /dev/null @@ -1,52 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the queue endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class QueueAlreadyExistsError(Exception): - """The queue name already exists.""" - - -class QueueDoesNotExistError(Exception): - """The requested queue does not exist.""" - - -class QueueLockedError(Exception): - """The requested queue is locked.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(QueueDoesNotExistError) - def handle_queue_does_not_exist_error(error): - return {"message": "Not Found - The requested queue does not exist"}, 404 - - @api.errorhandler(QueueLockedError) - def handle_queue_locked_error(error): - return {"message": "Forbidden - The requested queue is locked."}, 403 - - @api.errorhandler(QueueAlreadyExistsError) - def handle_queue_already_exists_error(error): - return ( - { - "message": "Bad Request - The queue name on the registration form " - "already exists. Please select another and resubmit." - }, - 400, - ) diff --git a/src/dioptra/restapi/v1/queues/schema.py b/src/dioptra/restapi/v1/queues/schema.py index 606267119..5bde27563 100644 --- a/src/dioptra/restapi/v1/queues/schema.py +++ b/src/dioptra/restapi/v1/queues/schema.py @@ -22,6 +22,7 @@ GroupIdQueryParametersSchema, PagingQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, generate_base_resource_ref_schema, generate_base_resource_schema, ) @@ -86,5 +87,6 @@ class QueueGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /queues endpoint.""" diff --git a/src/dioptra/restapi/v1/queues/service.py b/src/dioptra/restapi/v1/queues/service.py index d3730050c..a9e552637 100644 --- a/src/dioptra/restapi/v1/queues/service.py +++ b/src/dioptra/restapi/v1/queues/service.py @@ -27,13 +27,16 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import resource_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + SortParameterValidationError, +) from dioptra.restapi.v1 import utils from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import QueueAlreadyExistsError, QueueDoesNotExistError - LOGGER: BoundLogger = structlog.stdlib.get_logger() RESOURCE_TYPE: Final[str] = "queue" @@ -42,6 +45,12 @@ "description": lambda x: models.Queue.description.like(x, escape="/"), "tag": lambda x: models.Queue.tags.any(models.Tag.name.like(x, escape="/")), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.Queue.name, + "createdOn": models.Queue.created_on, + "lastModifiedOn": models.Resource.last_modified_on, + "description": models.Queue.description, +} class QueueService(object): @@ -85,18 +94,20 @@ def create( The newly created queue object. Raises: - QueueAlreadyExistsError: If a queue with the given name already exists. - GroupDoesNotExistError: If the group with the provided ID does not exist. + EntityExistsError: If a queue with the given name already exists. + EntityDoesNotExistError: If the group with the provided ID does not exist. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._queue_name_service.get(name, group_id=group_id, log=log) is not None: - log.debug("Queue name already exists", name=name, group_id=group_id) - raise QueueAlreadyExistsError + duplicate = self._queue_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) group = self._group_id_service.get(group_id, error_if_not_found=True) - resource = models.Resource(resource_type="queue", owner=group) + resource = models.Resource(resource_type=RESOURCE_TYPE, owner=group) new_queue = models.Queue( name=name, description=description, resource=resource, creator=current_user ) @@ -118,6 +129,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[utils.QueueDict], int]: """Fetch a list of queues, optionally filtering by search string and paging @@ -128,6 +141,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of queues to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of queues and the total number of queues matching @@ -183,6 +198,17 @@ def get( .offset(page_index) .limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + queues_stmt = queues_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + queues = list(db.session.scalars(queues_stmt).all()) drafts_stmt = select( @@ -235,7 +261,7 @@ def get( The queue object if found, otherwise None. Raises: - QueueDoesNotExistError: If the queue is not found and `error_if_not_found` + EntityDoesNotExistError: If the queue is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -254,8 +280,7 @@ def get( if queue is None: if error_if_not_found: - log.debug("Queue not found", queue_id=queue_id) - raise QueueDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, queue_id=queue_id) return None @@ -296,9 +321,9 @@ def modify( The updated queue object. Raises: - QueueDoesNotExistError: If the queue is not found and `error_if_not_found` + EntityDoesNotExistError: If the queue is not found and `error_if_not_found` is True. - QueueAlreadyExistsError: If the queue name already exists. + EntityExistsError: If the queue name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -309,13 +334,12 @@ def modify( queue = queue_dict["queue"] group_id = queue.resource.group_id - if ( - name != queue.name - and self._queue_name_service.get(name, group_id=group_id, log=log) - is not None - ): - log.debug("Queue name already exists", name=name, group_id=group_id) - raise QueueAlreadyExistsError + if name != queue.name: + duplicate = self._queue_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.resource_id, name=name, group_id=group_id + ) new_queue = models.Queue( name=name, @@ -346,7 +370,7 @@ def delete(self, queue_id: int, **kwargs) -> dict[str, Any]: A dictionary reporting the status of the request. Raises: - QueueDoesNotExistError: If the queue is not found. + EntityDoesNotExistError: If the queue is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -356,7 +380,7 @@ def delete(self, queue_id: int, **kwargs) -> dict[str, Any]: queue_resource = db.session.scalars(stmt).first() if queue_resource is None: - raise QueueDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, queue_id=queue_id) deleted_resource_lock = models.ResourceLock( resource_lock_type=resource_lock_types.DELETE, @@ -389,7 +413,7 @@ def get( The queue object if found, otherwise None. Raises: - QueueDoesNotExistError: If the queue is not found and `error_if_not_found` + EntityDoesNotExistError: If the queue is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -410,8 +434,9 @@ def get( queue_ids_missing = set(queue_ids) - set( queue.resource_id for queue in queues ) - log.debug("Queue not found", queue_ids=list(queue_ids_missing)) - raise QueueDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, queue_ids=list(queue_ids_missing) + ) return queues @@ -438,7 +463,7 @@ def get( The queue object if found, otherwise None. Raises: - QueueDoesNotExistError: If the queue is not found and `error_if_not_found` + EntityDoesNotExistError: If the queue is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -458,8 +483,7 @@ def get( if queue is None: if error_if_not_found: - log.debug("Queue not found", name=name) - raise QueueDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, name=name) return None diff --git a/src/dioptra/restapi/v1/schemas.py b/src/dioptra/restapi/v1/schemas.py index c8b9f374b..c71e65c43 100644 --- a/src/dioptra/restapi/v1/schemas.py +++ b/src/dioptra/restapi/v1/schemas.py @@ -238,6 +238,24 @@ class SearchQueryParametersSchema(Schema): ) +class SortByGetQueryParametersSchema(Schema): + """A schema for adding sort query parameters to a resource endpoint.""" + + sortBy = fields.String( + attribute="sort_by", + metadata=dict(description="The name of the column to sort."), + load_default="", + ) + + descending = fields.Bool( + attribute="descending", + metadata=dict( + description="Boolean indicating whether to sort by descending or not." + ), + load_default=False, + ) + + class ResourceGetQueryParameters( PagingQueryParametersSchema, SearchQueryParametersSchema, diff --git a/src/dioptra/restapi/v1/shared/drafts/controller.py b/src/dioptra/restapi/v1/shared/drafts/controller.py index 0850e93d0..710560ac0 100644 --- a/src/dioptra/restapi/v1/shared/drafts/controller.py +++ b/src/dioptra/restapi/v1/shared/drafts/controller.py @@ -191,7 +191,9 @@ def put(self, draftId: int): request_id=str(uuid.uuid4()), resource="Draft", request_type="POST" ) parsed_obj = request.parsed_obj # type: ignore - draft = self._draft_id_service.modify(draftId, payload=parsed_obj, log=log) + draft = self._draft_id_service.modify( + draftId, payload=parsed_obj, log=log, error_if_not_found=True + ) return utils.build_resource_draft( cast(models.DraftResource, draft), request_schema ) diff --git a/src/dioptra/restapi/v1/shared/drafts/service.py b/src/dioptra/restapi/v1/shared/drafts/service.py index 94e22115a..099d11234 100644 --- a/src/dioptra/restapi/v1/shared/drafts/service.py +++ b/src/dioptra/restapi/v1/shared/drafts/service.py @@ -31,9 +31,8 @@ BackendDatabaseError, DraftAlreadyExistsError, DraftDoesNotExistError, - ResourceDoesNotExistError, + EntityDoesNotExistError, ) -from dioptra.restapi.v1.groups.errors import GroupDoesNotExistError from dioptra.restapi.v1.groups.service import GroupIdService LOGGER: BoundLogger = structlog.stdlib.get_logger() @@ -159,7 +158,7 @@ def create( The newly created draft object. Raises: - GroupDoesNotExistError: If the group with the provided ID does not exist. + EntityDoesNotExistError: If the group with the provided ID does not exist. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -173,7 +172,9 @@ def create( ) resource = db.session.scalar(stmt) if resource is None: - raise GroupDoesNotExistError + raise EntityDoesNotExistError( + self._resource_type, resource_id=base_resource_id + ) group = resource.owner draft_payload = { @@ -249,8 +250,7 @@ def get( if draft is None: if error_if_not_found: - log.debug("Draft not found", draft_resource_id=draft_id) - raise DraftDoesNotExistError + raise DraftDoesNotExistError(draft_resource_id=draft_id) return None @@ -371,8 +371,7 @@ def get( if draft is None: if error_if_not_found: - log.debug("Draft not found", resource_id=resource_id) - raise DraftDoesNotExistError + raise DraftDoesNotExistError(resource_id=resource_id) return None, num_other_drafts @@ -407,11 +406,11 @@ def create( resource = db.session.scalars(stmt).first() if resource is None: - raise ResourceDoesNotExistError + raise EntityDoesNotExistError(self._resource_type, resource_id=resource_id) existing_draft, num_other_drafts = self.get(resource_id, log=log) if existing_draft: - raise DraftAlreadyExistsError + raise DraftAlreadyExistsError(self._resource_type, resource_id) draft_payload = { "resource_data": payload, diff --git a/src/dioptra/restapi/v1/shared/search_parser.py b/src/dioptra/restapi/v1/shared/search_parser.py index 4af4cbc99..c737d8701 100644 --- a/src/dioptra/restapi/v1/shared/search_parser.py +++ b/src/dioptra/restapi/v1/shared/search_parser.py @@ -62,7 +62,7 @@ def _define_query_grammar() -> pp.ParserElement: (escape | pp.Word(pp.printables + " ", exclude_chars='\\?*"\n'))[1, ...] ) - # The search strings are a sequence of one ore more valid characters and wildcards + # The search strings are a sequence of one or more valid characters and wildcards unquoted_search_word = (unquoted_word | wildcard)[1, ...] unquoted_search_string = (unquoted_words | wildcard)[1, ...] sgl_quoted_search_string = ( diff --git a/src/dioptra/restapi/v1/shared/snapshots/service.py b/src/dioptra/restapi/v1/shared/snapshots/service.py index 5301a0033..e2769c393 100644 --- a/src/dioptra/restapi/v1/shared/snapshots/service.py +++ b/src/dioptra/restapi/v1/shared/snapshots/service.py @@ -25,7 +25,7 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import BackendDatabaseError, ResourceDoesNotExistError +from dioptra.restapi.errors import BackendDatabaseError, EntityDoesNotExistError from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters LOGGER: BoundLogger = structlog.stdlib.get_logger() @@ -74,7 +74,7 @@ def get( None. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -87,8 +87,9 @@ def get( if resource is None: if error_if_not_found: - log.debug("Resource not found", resource_id=resource_id) - raise ResourceDoesNotExistError + raise EntityDoesNotExistError( + self._resource_type, resource_id=resource_id + ) return None @@ -176,7 +177,7 @@ def get( The requested snapshot the resource object if found, otherwise None. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -189,8 +190,9 @@ def get( if resource is None: if error_if_not_found: - log.debug("Resource not found", resource_id=resource_id) - raise ResourceDoesNotExistError + raise EntityDoesNotExistError( + self._resource_type, resource_id=resource_id + ) return None @@ -207,8 +209,9 @@ def get( if snapshot is None: if error_if_not_found: - log.debug("Resource snapshot not found", snapshot_id=snapshot_id) - raise ResourceDoesNotExistError + raise EntityDoesNotExistError( + self._resource_type + "_snapshot", snapshot_id=snapshot_id + ) return None diff --git a/src/dioptra/restapi/v1/shared/tags/service.py b/src/dioptra/restapi/v1/shared/tags/service.py index 1cb0e4569..c3c181e44 100644 --- a/src/dioptra/restapi/v1/shared/tags/service.py +++ b/src/dioptra/restapi/v1/shared/tags/service.py @@ -25,8 +25,8 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import ResourceDoesNotExistError -from dioptra.restapi.v1.tags.errors import TagDoesNotExistError +from dioptra.restapi.errors import EntityDoesNotExistError +from dioptra.restapi.v1.tags.service import RESOURCE_TYPE as TAG_RESOURCE_TYPE from dioptra.restapi.v1.tags.service import TagIdService LOGGER: BoundLogger = structlog.stdlib.get_logger() @@ -69,7 +69,7 @@ def get( The list of tags if the resource is found, otherwise None. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -100,7 +100,7 @@ def append( The updated tag resource object. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. TagDoesNotExistError: If one or more tags are not found. """ @@ -147,9 +147,9 @@ def modify( The updated tag resource object. Raises: - ResourceDoesNotExistError: If the resource is not found and + EntityDoesNotExistError: If the resource is not found and `error_if_not_found` is True. - TagDoesNotExistError: If one or more tags are not found. + EntityDoesNotExistError: If one or more tags are not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -232,7 +232,9 @@ def delete(self, resource_id: int, tag_id, **kwargs) -> dict[str, Any]: current_tags = resource.tags tag_exists = tag_id in {tag.tag_id for tag in current_tags} if not tag_exists: - raise TagDoesNotExistError + raise EntityDoesNotExistError( + TAG_RESOURCE_TYPE, resource_id=resource_id, tag_id=tag_id + ) resource.tags = [tag for tag in current_tags if tag.tag_id != tag_id] @@ -259,7 +261,6 @@ def get(self, resource_id: int, **kwargs) -> models.Resource: resource = db.session.scalar(stmt) if resource is None: - log.debug(f"{self._resource_type} not found", resource_id=resource_id) - raise ResourceDoesNotExistError + raise EntityDoesNotExistError(self._resource_type, resource_id=resource_id) return resource diff --git a/src/dioptra/restapi/v1/tags/__init__.py b/src/dioptra/restapi/v1/tags/__init__.py index 11ce655e6..ab0a41a34 100644 --- a/src/dioptra/restapi/v1/tags/__init__.py +++ b/src/dioptra/restapi/v1/tags/__init__.py @@ -14,6 +14,3 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/tags/controller.py b/src/dioptra/restapi/v1/tags/controller.py index cfaa3164a..fccd4b262 100644 --- a/src/dioptra/restapi/v1/tags/controller.py +++ b/src/dioptra/restapi/v1/tags/controller.py @@ -75,12 +75,16 @@ def get(self): search_string = unquote(parsed_query_params["search"]) page_index = parsed_query_params["index"] page_length = parsed_query_params["page_length"] + sort_by_string = parsed_query_params["sort_by"] + descending = parsed_query_params["descending"] tags, total_num_tags = self._tag_service.get( group_id=group_id, search_string=search_string, page_index=page_index, page_length=page_length, + sort_by_string=sort_by_string, + descending=descending, log=log, ) return utils.build_paging_envelope( @@ -93,6 +97,8 @@ def get(self): index=page_index, length=page_length, total_num_elements=total_num_tags, + sort_by=sort_by_string, + descending=descending, ) @login_required diff --git a/src/dioptra/restapi/v1/tags/errors.py b/src/dioptra/restapi/v1/tags/errors.py deleted file mode 100644 index 0e86ee4a1..000000000 --- a/src/dioptra/restapi/v1/tags/errors.py +++ /dev/null @@ -1,38 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the tag endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class TagAlreadyExistsError(Exception): - """The tag name already exists.""" - - -class TagDoesNotExistError(Exception): - """The requested tag does not exist.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(TagDoesNotExistError) - def handle_tag_does_not_exist_error(error): - return {"message": "Not Found - The requested tag does not exist"}, 404 - - @api.errorhandler(TagAlreadyExistsError) - def handle_tag_already_exists_error(error): - return {"message": "Bad Request - The tag name already exists."}, 400 diff --git a/src/dioptra/restapi/v1/tags/schema.py b/src/dioptra/restapi/v1/tags/schema.py index 7e9fe069a..84a2339ba 100644 --- a/src/dioptra/restapi/v1/tags/schema.py +++ b/src/dioptra/restapi/v1/tags/schema.py @@ -26,6 +26,7 @@ PagingQueryParametersSchema, ResourceTypeQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ) from dioptra.restapi.v1.users.schema import UserRefSchema @@ -117,6 +118,7 @@ class TagGetQueryParameters( PagingQueryParametersSchema, GroupIdQueryParametersSchema, SearchQueryParametersSchema, + SortByGetQueryParametersSchema, ): """The query parameters for the GET method of the /tags endpoint.""" diff --git a/src/dioptra/restapi/v1/tags/service.py b/src/dioptra/restapi/v1/tags/service.py index eda7fdcff..a81a905c9 100644 --- a/src/dioptra/restapi/v1/tags/service.py +++ b/src/dioptra/restapi/v1/tags/service.py @@ -27,17 +27,26 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + SortParameterValidationError, +) from dioptra.restapi.v1.groups.service import GroupIdService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import TagAlreadyExistsError, TagDoesNotExistError - LOGGER: BoundLogger = structlog.stdlib.get_logger() +RESOURCE_TYPE: Final[str] = "tag" SEARCHABLE_FIELDS: Final[dict[str, Any]] = { "name": lambda x: models.Tag.name.like(x), } +SORTABLE_FIELDS: Final[dict[str, Any]] = { + "name": models.Tag.name, + "createdOn": models.Tag.created_on, + "lastModifiedOn": models.Tag.last_modified_on, +} class TagService(object): @@ -80,14 +89,16 @@ def create( The newly created tag object. Raises: - TagAlreadyExistsError: If a tag with the given name already exists. - GroupDoesNotExistError: If the group with the provided ID does not exist. + EntityExistsError: If a tag with the given name already exists. + EntityDoesNotExistError: If the group with the provided ID does not exist. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) - if self._tag_name_service.get(name, group_id=group_id, log=log) is not None: - log.debug("Tag name already exists", name=name, group_id=group_id) - raise TagAlreadyExistsError + duplicate = self._tag_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.tag_id, name=name, group_id=group_id + ) group = self._group_id_service.get(group_id, error_if_not_found=True) @@ -108,6 +119,8 @@ def get( search_string: str, page_index: int, page_length: int, + sort_by_string: str, + descending: bool, **kwargs, ) -> tuple[list[models.Tag], int]: """Fetch a list of tags, optionally filtering by search string and paging @@ -118,6 +131,8 @@ def get( search_string: A search string used to filter results. page_index: The index of the first group to be returned. page_length: The maximum number of tags to be returned. + sort_by_string: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: A tuple containing a list of tags and the total number of tags matching @@ -154,6 +169,17 @@ def get( tags_stmt = ( select(models.Tag).where(*filters).offset(page_index).limit(page_length) ) + + if sort_by_string and sort_by_string in SORTABLE_FIELDS: + sort_column = SORTABLE_FIELDS[sort_by_string] + if descending: + sort_column = sort_column.desc() + else: + sort_column = sort_column.asc() + tags_stmt = tags_stmt.order_by(sort_column) + elif sort_by_string and sort_by_string not in SORTABLE_FIELDS: + raise SortParameterValidationError(RESOURCE_TYPE, sort_by_string) + tags = list(db.session.scalars(tags_stmt).all()) return tags, total_num_tags @@ -193,7 +219,7 @@ def get( The tag object if found, otherwise None. Raises: - TagDoesNotExistError: If the tag is not found and `error_if_not_found` + EntityDoesNotExistError: If the tag is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -204,8 +230,7 @@ def get( if tag is None: if error_if_not_found: - log.debug("Tag not found", tag_id=tag_id) - raise TagDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, tag_id=tag_id) return None @@ -233,9 +258,9 @@ def modify( The updated tag object. Raises: - TagDoesNotExistError: If the tag is not found and `error_if_not_found` + EntityDoesNotExistError: If the tag is not found and `error_if_not_found` is True. - TagAlreadyExistsError: If the tag name already exists. + EntityExistsError: If the tag name already exists. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -245,12 +270,12 @@ def modify( return None group_id = tag.group_id - if ( - name != tag.name - and self._tag_name_service.get(name, group_id=group_id, log=log) is not None - ): - log.debug("Tag name already exists", name=name, group_id=group_id) - raise TagAlreadyExistsError + if name != tag.name: + duplicate = self._tag_name_service.get(name, group_id=group_id, log=log) + if duplicate is not None: + raise EntityExistsError( + RESOURCE_TYPE, duplicate.tag_id, name=name, group_id=group_id + ) current_timestamp = datetime.datetime.now(tz=datetime.timezone.utc) tag.name = name @@ -280,7 +305,7 @@ def delete( The tag object if found, otherwise None. Raises: - TagDoesNotExistError: If the tag is not found. + EntityDoesNotExistError: If the tag is not found. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) log.debug("Get tag by id", tag_id=tag_id) @@ -289,8 +314,7 @@ def delete( tag = db.session.scalar(stmt) if tag is None: - log.debug("Tag not found", tag_id=tag_id) - raise TagDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, tag_id=tag_id) tag_id = tag.tag_id db.session.delete(tag) @@ -339,7 +363,7 @@ def get( The tag object if found, otherwise None. Raises: - TagDoesNotExistError: If the tag is not found and `error_if_not_found` + EntityDoesNotExistError: If the tag is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -350,8 +374,7 @@ def get( if tag is None: if error_if_not_found: - log.debug("Tag not found", tag_id=tag_id) - raise TagDoesNotExistError + raise EntityDoesNotExistError(RESOURCE_TYPE, tag_id=tag_id) return None @@ -409,7 +432,7 @@ def get( The tag object if found, otherwise None. Raises: - TagDoesNotExistError: If the tag is not found and `error_if_not_found` + EntityDoesNotExistError: If the tag is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -423,8 +446,9 @@ def get( if tag is None: if error_if_not_found: - log.debug("Tag not found", name=name) - raise TagDoesNotExistError + raise EntityDoesNotExistError( + RESOURCE_TYPE, name=name, group_id=group_id + ) return None diff --git a/src/dioptra/restapi/v1/users/__init__.py b/src/dioptra/restapi/v1/users/__init__.py index 0491fe75b..ff72e5b3b 100644 --- a/src/dioptra/restapi/v1/users/__init__.py +++ b/src/dioptra/restapi/v1/users/__init__.py @@ -15,6 +15,3 @@ # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode """The users endpoint subpackage.""" -from . import errors - -__all__ = ["errors"] diff --git a/src/dioptra/restapi/v1/users/errors.py b/src/dioptra/restapi/v1/users/errors.py deleted file mode 100644 index 12ab460f9..000000000 --- a/src/dioptra/restapi/v1/users/errors.py +++ /dev/null @@ -1,115 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the user endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class NoCurrentUserError(Exception): - """There is no currently logged-in user.""" - - -class UserPasswordChangeError(Exception): - """Password change failed.""" - - -class UserPasswordChangeSamePasswordError(Exception): - """Password change failed.""" - - -class UserPasswordExpiredError(Exception): - """Password expired.""" - - -class UserPasswordVerificationError(Exception): - """Password verification failed.""" - - -class UsernameNotAvailableError(Exception): - """The username is not available.""" - - -class UserEmailNotAvailableError(Exception): - """The email address is not available.""" - - -class UserDoesNotExistError(Exception): - """The requested user does not exist.""" - - -class UserRegistrationError(Exception): - """The user registration form contains invalid parameters.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(NoCurrentUserError) - def handle_no_current_user_error(error): - return {"message": "There is no currently logged-in user"}, 401 - - @api.errorhandler(UserPasswordChangeError) - def handle_user_password_change_error_error(error): - return {"message": "Password Change Failed"}, 403 - - @api.errorhandler(UserPasswordChangeSamePasswordError) - def handle_user_password_change_same_error_error(error): - return { - "message": "Password Change Failed - The provided password matches" - "the existing password. Please provide a different password." - }, 403 - - @api.errorhandler(UserPasswordExpiredError) - def handle_user_password_expired_error(error): - return {"message": "Password expired."}, 401 - - @api.errorhandler(UserPasswordVerificationError) - def handle_user_password_verification_error_error(error): - return {"message": "Password Verification Failed"}, 403 - - @api.errorhandler(UserDoesNotExistError) - def handle_user_does_not_exist_error(error): - return {"message": "Not Found - The requested user does not exist"}, 404 - - @api.errorhandler(UsernameNotAvailableError) - def handle_username_not_available_error(error): - return ( - { - "message": "Bad Request - The username on the registration form " - "is not available. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(UserEmailNotAvailableError) - def handle_email_not_available_error(error): - return ( - { - "message": "Bad Request - The email on the registration form " - "is not available. Please select another and resubmit." - }, - 400, - ) - - @api.errorhandler(UserRegistrationError) - def handle_user_registration_error(error): - return ( - { - "message": "Bad Request - The user registration form contains " - "invalid parameters. Please verify and resubmit." - }, - 400, - ) diff --git a/src/dioptra/restapi/v1/users/service.py b/src/dioptra/restapi/v1/users/service.py index a3bff19d3..7f425059c 100644 --- a/src/dioptra/restapi/v1/users/service.py +++ b/src/dioptra/restapi/v1/users/service.py @@ -29,7 +29,15 @@ from dioptra.restapi.db import db, models from dioptra.restapi.db.models.constants import user_lock_types -from dioptra.restapi.errors import BackendDatabaseError +from dioptra.restapi.errors import ( + BackendDatabaseError, + EntityDoesNotExistError, + EntityExistsError, + NoCurrentUserError, + QueryParameterValidationError, + UserPasswordChangeError, + UserPasswordError, +) from dioptra.restapi.v1.groups.service import GroupMemberService, GroupNameService from dioptra.restapi.v1.plugin_parameter_types.service import ( BuiltinPluginParameterTypeService, @@ -37,18 +45,6 @@ from dioptra.restapi.v1.shared.password_service import PasswordService from dioptra.restapi.v1.shared.search_parser import construct_sql_query_filters -from .errors import ( - NoCurrentUserError, - UserDoesNotExistError, - UserEmailNotAvailableError, - UsernameNotAvailableError, - UserPasswordChangeError, - UserPasswordChangeSamePasswordError, - UserPasswordExpiredError, - UserPasswordVerificationError, - UserRegistrationError, -) - LOGGER: BoundLogger = structlog.stdlib.get_logger() DEFAULT_GROUP_NAME: Final[str] = "public" @@ -128,17 +124,19 @@ def create( log: BoundLogger = kwargs.get("log", LOGGER.new()) if password != confirm_password: - raise UserRegistrationError( - "The password and confirmation password did not match." + raise QueryParameterValidationError( + "password", "equivalence", password="***", confirmation="***" ) - if self._user_name_service.get(username, log=log) is not None: - log.debug("Username already exists", username=username) - raise UsernameNotAvailableError + duplicate = self._user_name_service.get(username, log=log) + if duplicate is not None: + raise EntityExistsError("User", duplicate.user_id, username=username) - if self._get_user_by_email(email_address, log=log) is not None: - log.debug("Email already exists", email_address=email_address) - raise UserEmailNotAvailableError + duplicate = self._get_user_by_email(email_address, log=log) + if duplicate is not None: + raise EntityExistsError( + "User", duplicate.user_id, email_address=email_address + ) hashed_password = self._user_password_service.hash(password, log=log) new_user: models.User = models.User( @@ -237,7 +235,7 @@ def _get_user_by_email( The user object if found, otherwise None. Raises: - UserDoesNotExistError: If the user is not found and `error_if_not_found` + EntityDoesNotExistError: If the user is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -250,8 +248,7 @@ def _get_user_by_email( if user is None: if error_if_not_found: - log.debug("User not found", email_address=email_address) - raise UserDoesNotExistError + raise EntityDoesNotExistError("User", email_address=email_address) return None @@ -317,7 +314,7 @@ def get( The user object if found, otherwise None. Raises: - UserDoesNotExistError: If the user is not found and `error_if_not_found` + EntityDoesNotExistError: If the user is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -328,8 +325,7 @@ def get( if user is None: if error_if_not_found: - log.debug("User not found", user_id=user_id) - raise UserDoesNotExistError + raise EntityDoesNotExistError("User", user_id=user_id) return None @@ -379,7 +375,7 @@ def __init__( user_id_service: UserIdService, user_password_service: UserPasswordService, ) -> None: - """Initialize the current current user service. + """Initialize the current user service. All arguments are provided via dependency injection. @@ -399,10 +395,9 @@ def get(self, **kwargs) -> models.User: Raises: NoCurrentUserError: If there is no current user. """ - log: BoundLogger = kwargs.get("log", LOGGER.new()) + log: BoundLogger = kwargs.get("log", LOGGER.new()) # noqa: F841 if not current_user.is_authenticated: - log.debug("There is no current user.") raise NoCurrentUserError return cast(models.User, current_user) @@ -527,7 +522,7 @@ def get( The user object if found, otherwise None. Raises: - UserDoesNotExistError: If the user is not found and `error_if_not_found` + EntityDoesNotExistError: If the user is not found and `error_if_not_found` is True. """ log: BoundLogger = kwargs.get("log", LOGGER.new()) @@ -538,8 +533,7 @@ def get( if user is None: if error_if_not_found: - log.debug("User not found", username=username) - raise UserDoesNotExistError + raise EntityDoesNotExistError("User", username=username) return None @@ -595,12 +589,10 @@ def authenticate( ) if not authenticated and error_if_failed: - log.debug("Password authentication failed.") - raise UserPasswordVerificationError + raise UserPasswordError("Password authentication failed.") if expiration_date < current_timestamp: - log.debug("Password expired") - raise UserPasswordExpiredError + raise UserPasswordError("Password expired.") return authenticated @@ -637,15 +629,17 @@ def change( if not self._password_service.verify( password=current_password, hashed_password=str(user.password), log=log ): - raise UserPasswordChangeError + raise UserPasswordChangeError("Invalid Current Password.") if new_password != confirm_new_password: - raise UserPasswordChangeError + raise UserPasswordChangeError( + "Confirmation password does not match new password." + ) if self._password_service.verify( password=new_password, hashed_password=str(user.password), log=log ): - raise UserPasswordChangeSamePasswordError + raise UserPasswordChangeError("New password matches old password.") timestamp = datetime.datetime.now(tz=datetime.timezone.utc) user.password = self._password_service.hash(password=new_password, log=log) diff --git a/src/dioptra/restapi/v1/utils.py b/src/dioptra/restapi/v1/utils.py index 190deb30a..349737517 100644 --- a/src/dioptra/restapi/v1/utils.py +++ b/src/dioptra/restapi/v1/utils.py @@ -15,7 +15,7 @@ # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode """Utility functions to help in building responses from ORM models""" -from typing import Any, Callable, Final, TypedDict, cast +from typing import Any, Callable, Final, Optional, TypedDict, cast from urllib.parse import urlencode, urlunparse from marshmallow import Schema @@ -871,7 +871,9 @@ def build_plugin_file(plugin_file_with_plugin: PluginFileDict) -> dict[str, Any] def build_plugin_task(plugin_task: models.PluginTask) -> PluginTaskDict: input_params: list[PluginTaskInputParameterDict] = [] - for input_parameter in plugin_task.input_parameters: + for input_parameter in sorted( + plugin_task.input_parameters, key=lambda x: x.parameter_number + ): input_params.append( PluginTaskInputParameterDict( name=input_parameter.name, @@ -883,7 +885,9 @@ def build_plugin_task(plugin_task: models.PluginTask) -> PluginTaskDict: ) output_params: list[PluginTaskOutputParameterDict] = [] - for output_parameter in plugin_task.output_parameters: + for output_parameter in sorted( + plugin_task.output_parameters, key=lambda x: x.parameter_number + ): output_params.append( PluginTaskOutputParameterDict( name=output_parameter.name, @@ -990,6 +994,8 @@ def build_paging_envelope( index: int, length: int, total_num_elements: int, + sort_by: Optional[str] = None, + descending: Optional[bool] = None, ) -> dict[str, Any]: """Build the paging envelope for a response. @@ -1004,6 +1010,8 @@ def build_paging_envelope( index: The index of the current page. length: The number of results to return per page. total_num_elements: The total number of elements in the collection. + sort_by: The name of the column to sort. + descending: Boolean indicating whether to sort by descending or not. Returns: The paging envelope for the response. @@ -1016,6 +1024,8 @@ def build_paging_envelope( "index": index, "is_complete": is_complete, "total_num_results": total_num_elements, + "sort_by": sort_by, + "descending": descending, "first": build_paging_url( route_prefix, group_id=group_id, diff --git a/src/dioptra/restapi/v1/workflows/errors.py b/src/dioptra/restapi/v1/workflows/errors.py deleted file mode 100644 index c5723ec4a..000000000 --- a/src/dioptra/restapi/v1/workflows/errors.py +++ /dev/null @@ -1,41 +0,0 @@ -# This Software (Dioptra) is being made available as a public service by the -# National Institute of Standards and Technology (NIST), an Agency of the United -# States Department of Commerce. This software was developed in part by employees of -# NIST and in part by NIST contractors. Copyright in portions of this software that -# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant -# to Title 17 United States Code Section 105, works of NIST employees are not -# subject to copyright protection in the United States. However, NIST may hold -# international copyright in software created by its employees and domestic -# copyright (or licensing rights) in portions of software that were assigned or -# licensed to NIST. To the extent that NIST holds copyright in this software, it is -# being made available under the Creative Commons Attribution 4.0 International -# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts -# of the software developed or licensed by NIST. -# -# ACCESS THE FULL CC BY 4.0 LICENSE HERE: -# https://creativecommons.org/licenses/by/4.0/legalcode -"""Error handlers for the workflows endpoints.""" -from __future__ import annotations - -from flask_restx import Api - - -class JobEntryPointDoesNotExistError(Exception): - """The job's entry point does not exist.""" - - -class JobExperimentDoesNotExistError(Exception): - """The experiment associated with the job does not exist.""" - - -def register_error_handlers(api: Api) -> None: - @api.errorhandler(JobEntryPointDoesNotExistError) - def handle_experiment_job_does_not_exist_error(error): - return {"message": "Not Found - The job's entry point does not exist"}, 404 - - @api.errorhandler(JobExperimentDoesNotExistError) - def handle_experiment_does_not_exist_error(error): - return { - "message": "Not Found - The experiment associated with the job does not " - "exist" - }, 404 diff --git a/src/dioptra/restapi/v1/workflows/lib/export_job_parameters.py b/src/dioptra/restapi/v1/workflows/lib/export_job_parameters.py index 0affabfed..3a10b7b5b 100644 --- a/src/dioptra/restapi/v1/workflows/lib/export_job_parameters.py +++ b/src/dioptra/restapi/v1/workflows/lib/export_job_parameters.py @@ -23,9 +23,10 @@ from dioptra.restapi.db import models +from .type_coercions import GlobalParameterType, coerce_to_type + LOGGER: BoundLogger = structlog.stdlib.get_logger() -FLOAT_PARAM_TYPE: Final[str] = "float" JSON_FILE_ENCODING: Final[str] = "utf-8" @@ -47,27 +48,15 @@ def export_job_parameters( log = logger or LOGGER.new() # noqa: F841 job_params_json_path = Path(base_dir, "parameters").with_suffix(".json") - job_parameters: dict[str, str | int | float | None] = {} + job_parameters: dict[str, GlobalParameterType] = {} for param_value in job_param_values: - if param_value.parameter.parameter_type == FLOAT_PARAM_TYPE: - job_parameters[param_value.parameter.name] = _convert_to_number( - param_value.value - ) - - else: - job_parameters[param_value.parameter.name] = param_value.value + value = coerce_to_type( + x=param_value.value, + type_name=param_value.parameter.parameter_type, + ) + job_parameters[param_value.parameter.name] = value with job_params_json_path.open("wt", encoding=JSON_FILE_ENCODING) as f: json.dump(job_parameters, f, indent=2) return job_params_json_path - - -def _convert_to_number(number: str | None) -> int | float | None: - if number is None: - return None - - if number.isnumeric(): - return int(number) - - return float(number) diff --git a/src/dioptra/restapi/v1/workflows/lib/export_task_engine_yaml.py b/src/dioptra/restapi/v1/workflows/lib/export_task_engine_yaml.py index c61e36a69..d89923b84 100644 --- a/src/dioptra/restapi/v1/workflows/lib/export_task_engine_yaml.py +++ b/src/dioptra/restapi/v1/workflows/lib/export_task_engine_yaml.py @@ -24,8 +24,22 @@ from dioptra.restapi.db import models from dioptra.task_engine.type_registry import BUILTIN_TYPES +from .type_coercions import ( + BOOLEAN_PARAM_TYPE, + FLOAT_PARAM_TYPE, + INTEGER_PARAM_TYPE, + STRING_PARAM_TYPE, + coerce_to_type, +) + LOGGER: BoundLogger = structlog.stdlib.get_logger() +EXPLICIT_GLOBAL_TYPES: Final[set[str]] = { + STRING_PARAM_TYPE, + BOOLEAN_PARAM_TYPE, + INTEGER_PARAM_TYPE, + FLOAT_PARAM_TYPE, +} YAML_FILE_ENCODING: Final[str] = "utf-8" YAML_EXPORT_SETTINGS: Final[dict[str, Any]] = { "indent": 2, @@ -37,6 +51,7 @@ def export_task_engine_yaml( entrypoint: models.EntryPoint, entry_point_plugin_files: list[models.EntryPointPluginFile], + plugin_parameter_types: list[models.PluginTaskParameterType], base_dir: Path, logger: BoundLogger | None = None, ) -> Path: @@ -45,6 +60,8 @@ def export_task_engine_yaml( Args: entrypoint: The entrypoint to export. entry_point_plugin_files: The entrypoint's plugin files. + plugin_parameter_types: The latest snapshots of the plugin parameter types + accessible to the entrypoint. base_dir: The directory to export the task engine YAML file to. logger: A structlog logger object to use for logging. A new logger will be created if None. @@ -55,7 +72,9 @@ def export_task_engine_yaml( log = logger or LOGGER.new() # noqa: F841 task_yaml_path = Path(base_dir, entrypoint.name).with_suffix(".yml") task_engine_dict = build_task_engine_dict( - entrypoint=entrypoint, entry_point_plugin_files=entry_point_plugin_files + entrypoint=entrypoint, + entry_point_plugin_files=entry_point_plugin_files, + plugin_parameter_types=plugin_parameter_types, ) with task_yaml_path.open("wt", encoding=YAML_FILE_ENCODING) as f: @@ -67,6 +86,7 @@ def export_task_engine_yaml( def build_task_engine_dict( entrypoint: models.EntryPoint, entry_point_plugin_files: list[models.EntryPointPluginFile], + plugin_parameter_types: list[models.PluginTaskParameterType], logger: BoundLogger | None = None, ) -> dict[str, Any]: """Build a dictionary representation of a task engine YAML file. @@ -74,6 +94,8 @@ def build_task_engine_dict( Args: entrypoint: The entrypoint to export. entry_point_plugin_files: The entrypoint's plugin files. + plugin_parameter_types: The latest snapshots of the plugin parameter types + accessible to the entrypoint. logger: A structlog logger object to use for logging. A new logger will be created if None. @@ -81,7 +103,9 @@ def build_task_engine_dict( A dictionary representation of a task engine YAML file. """ log = logger or LOGGER.new() # noqa: F841 - tasks, parameter_types = extract_tasks(entry_point_plugin_files) + tasks, parameter_types = extract_tasks( + entry_point_plugin_files, plugin_parameter_types=plugin_parameter_types + ) parameters = extract_parameters(entrypoint) graph = extract_graph(entrypoint) return { @@ -107,17 +131,32 @@ def extract_parameters( A dictionary of the entrypoint's parameters. """ log = logger or LOGGER.new() # noqa: F841 - return {param.name: param.default_value for param in entrypoint.parameters} + parameters: dict[str, Any] = {} + for param in entrypoint.parameters: + default_value = param.default_value + parameters[param.name] = { + "default": coerce_to_type(x=default_value, type_name=param.parameter_type) + } + + if param.parameter_type in EXPLICIT_GLOBAL_TYPES: + parameters[param.name]["type"] = ( + _convert_parameter_type_to_task_engine_type(param.parameter_type) + ) + + return parameters def extract_tasks( entry_point_plugin_files: list[models.EntryPointPluginFile], + plugin_parameter_types: list[models.PluginTaskParameterType], logger: BoundLogger | None = None, ) -> tuple[dict[str, Any], dict[str, Any]]: """Extract the plugin tasks and parameter types from the entrypoint plugin files. Args: entry_point_plugin_files: The entrypoint's plugin files. + plugin_parameter_types: The latest snapshots of the plugin parameter types + accessible to the entrypoint. logger: A structlog logger object to use for logging. A new logger will be created if None. @@ -134,8 +173,12 @@ def extract_tasks( plugin_file = entry_point_plugin_file.plugin_file for task in plugin_file.tasks: - input_parameters = task.input_parameters - output_parameters = task.output_parameters + input_parameters = sorted( + task.input_parameters, key=lambda x: x.parameter_number + ) + output_parameters = sorted( + task.output_parameters, key=lambda x: x.parameter_number + ) tasks[task.plugin_task_name] = { "plugin": _build_plugin_field(plugin, plugin_file, task), @@ -155,6 +198,24 @@ def extract_tasks( if name not in BUILTIN_TYPES: parameter_types[name] = param.parameter_type.structure + # HACK: THIS IS A WORKAROUND THAT VIOLATES IDEMPOTENCE/REPRODUCIBILITY! + # + # This workaround allows users to create and use parameter types that are + # only used indirectly, such as when defining a structured parameter type. + # This is a "hack" because the objects in `plugin_parameter_types` are the + # latest available snapshots, not the snapshots that were associated with + # the plugins when the entrypoint was saved/updated. This is in contrast + # with the parameter types accumulated in the previous for loop block, which + # are linked to the entrypoint and job by their snapshot id instead of the + # resource id. This difference means that the task engine YAML files are not + # 100% reproducible, as any changes to an "indirect" plugin parameter type + # will be immediately reflected in subsequent download requests made to the + # job files workflow. + for parameter_type in plugin_parameter_types: + name = parameter_type.name + if name not in BUILTIN_TYPES and name not in parameter_types: + parameter_types[name] = parameter_type.structure + return tasks, parameter_types @@ -212,3 +273,15 @@ def _build_task_outputs( {output_param.name: output_param.parameter_type.name} for output_param in output_parameters ] + + +def _convert_parameter_type_to_task_engine_type(parameter_type: str) -> Any: + conversion_map = { + "boolean": "boolean", + "string": "string", + "float": "number", + "integer": "integer", + "list": {"list": "any"}, + "mapping": {"mapping": ["string", "any"]}, + } + return conversion_map[parameter_type] diff --git a/src/dioptra/restapi/v1/workflows/lib/package_job_files.py b/src/dioptra/restapi/v1/workflows/lib/package_job_files.py index edd05c6c7..b2c904bd0 100644 --- a/src/dioptra/restapi/v1/workflows/lib/package_job_files.py +++ b/src/dioptra/restapi/v1/workflows/lib/package_job_files.py @@ -40,6 +40,7 @@ def package_job_files( entry_point: models.EntryPoint, entry_point_plugin_files: list[models.EntryPointPluginFile], job_parameter_values: list[models.EntryPointParameterValue], + plugin_parameter_types: list[models.PluginTaskParameterType], file_type: FileTypes, logger: BoundLogger | None = None, ) -> IO[bytes]: @@ -51,6 +52,8 @@ def package_job_files( entry_point: The job's entrypoint. entry_point_plugin_files: The job's entrypoint plugin files. job_parameter_values: The job's assigned parameter values. + plugin_parameter_types: The latest snapshots of the plugin parameter types + accessible to the job. file_type: The type of file to package the job files into. logger: A structlog logger object to use for logging. A new logger will be created if None. @@ -72,6 +75,7 @@ def package_job_files( task_engine_yaml_path = export_task_engine_yaml( entrypoint=entry_point, entry_point_plugin_files=entry_point_plugin_files, + plugin_parameter_types=plugin_parameter_types, base_dir=base_dir, logger=log, ) diff --git a/src/dioptra/restapi/v1/workflows/lib/run_dioptra_job.py.tmpl b/src/dioptra/restapi/v1/workflows/lib/run_dioptra_job.py.tmpl index d126dd4c1..7abca7ce8 100644 --- a/src/dioptra/restapi/v1/workflows/lib/run_dioptra_job.py.tmpl +++ b/src/dioptra/restapi/v1/workflows/lib/run_dioptra_job.py.tmpl @@ -24,9 +24,11 @@ import structlog import yaml from structlog.stdlib import BoundLogger +from dioptra.sdk.utilities.contexts import env_vars from dioptra.sdk.utilities.contexts import sys_path_dirs +from dioptra.task_engine.issues import IssueSeverity from dioptra.task_engine.task_engine import run_experiment -from dioptra.task_engine.validation import is_valid +from dioptra.task_engine.validation import validate LOGGER: BoundLogger = structlog.stdlib.get_logger() DIOPTRA_JOB_ID = "dioptra.jobId" @@ -57,12 +59,21 @@ def main( log.error("Plugins directory does not exist", plugins_dir=str(plugins_dir)) raise ValueError(f"Plugins directory {plugins_dir} does not exist") - job_yaml = _load_job_yaml(JOB_YAML_PATH) - job_parameters = _load_job_params(JOB_PARAMS_JSON_PATH) + try: + job_yaml = _load_job_yaml(JOB_YAML_PATH) + + except Exception as e: + log.exception("Could not load job YAML file") + raise e + + try: + job_parameters = _load_job_params(JOB_PARAMS_JSON_PATH) - if not is_valid(job_yaml): - log.error("Job YAML was invalid!") - raise ValueError("Job YAML was invalid!") + except Exception as e: + log.exception("Could not load parameters JSON file") + raise e + + _validate_yaml(job_yaml, log) if enable_mlflow_tracking: if dioptra_client is None: @@ -101,7 +112,7 @@ def _run_job( log = logger or LOGGER.new(job_id=JOB_ID, experiment_id=EXPERIMENT_ID) # noqa: F841 try: - with sys_path_dirs(dirs=(str(plugins_dir),)): + with sys_path_dirs(dirs=(str(plugins_dir),)), env_vars({"__JOB_ID": str(JOB_ID)}): run_experiment(job_yaml, job_parameters) log.info("=== Run succeeded ===") @@ -140,7 +151,7 @@ def _run_mlflow_tracked_job( mlflow.log_dict(job_yaml, Path(JOB_YAML_PATH).name) mlflow.log_params(job_parameters) - with sys_path_dirs(dirs=(str(plugins_dir),)): + with sys_path_dirs(dirs=(str(plugins_dir),)), env_vars({"__JOB_ID": str(JOB_ID)}): run_experiment(job_yaml, job_parameters) log.info("=== Run succeeded ===") @@ -164,6 +175,27 @@ def _load_job_params(filepath: str) -> MutableMapping[str, Any]: return cast(MutableMapping[str, Any], json.load(f)) +def _validate_yaml( + job_yaml: Mapping[str, Any], + logger: BoundLogger | None = None, +) -> None: + log = logger or LOGGER.new(job_id=JOB_ID, experiment_id=EXPERIMENT_ID) # noqa: F841 + + issues = validate(job_yaml) + errors: list[str] = [] + + for issue in issues: + if issue.severity is IssueSeverity.WARNING: + log.warn("Found issue with Job YAML", message=issue.message) + + if issue.severity is IssueSeverity.ERROR: + log.error("Found error in Job YAML", message=issue.message) + errors.append(issue.message) + + if errors: + raise ValueError(f"Errors found in Job YAML: {errors}") + + if __name__ == "__main__": # Running the file as a script does not enable the Mlflow Tracking capability. This # is useful for debugging whether the job YAML and plugins are set up appropriately. diff --git a/src/dioptra/restapi/v1/workflows/lib/type_coercions.py b/src/dioptra/restapi/v1/workflows/lib/type_coercions.py new file mode 100644 index 000000000..c88e56127 --- /dev/null +++ b/src/dioptra/restapi/v1/workflows/lib/type_coercions.py @@ -0,0 +1,90 @@ +# This Software (Dioptra) is being made available as a public service by the +# National Institute of Standards and Technology (NIST), an Agency of the United +# States Department of Commerce. This software was developed in part by employees of +# NIST and in part by NIST contractors. Copyright in portions of this software that +# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant +# to Title 17 United States Code Section 105, works of NIST employees are not +# subject to copyright protection in the United States. However, NIST may hold +# international copyright in software created by its employees and domestic +# copyright (or licensing rights) in portions of software that were assigned or +# licensed to NIST. To the extent that NIST holds copyright in this software, it is +# being made available under the Creative Commons Attribution 4.0 International +# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts +# of the software developed or licensed by NIST. +# +# ACCESS THE FULL CC BY 4.0 LICENSE HERE: +# https://creativecommons.org/licenses/by/4.0/legalcode +import json +from typing import Any, Final, cast + +JsonType = dict[str, Any] | list[Any] +GlobalParameterType = str | float | int | bool | dict[str, Any] | list[Any] | None + + +BOOLEAN_PARAM_TYPE: Final[str] = "boolean" +FLOAT_PARAM_TYPE: Final[str] = "float" +INTEGER_PARAM_TYPE: Final[str] = "integer" +LIST_PARAM_TYPE: Final[str] = "list" +MAPPING_PARAM_TYPE: Final[str] = "mapping" +STRING_PARAM_TYPE: Final[str] = "string" + + +def coerce_to_type(x: str | None, type_name: str) -> GlobalParameterType: + coerce_fn_registry = { + BOOLEAN_PARAM_TYPE: to_boolean_type, + FLOAT_PARAM_TYPE: to_float_type, + INTEGER_PARAM_TYPE: to_integer_type, + LIST_PARAM_TYPE: to_list_type, + MAPPING_PARAM_TYPE: to_mapping_type, + STRING_PARAM_TYPE: to_string_type, + } + + if type_name not in coerce_fn_registry: + raise ValueError(f"Invalid parameter type: {type_name}.") + + if x is None: + return None + + coerce_fn = coerce_fn_registry[type_name] + return cast(GlobalParameterType, coerce_fn(x)) + + +def to_string_type(x: str) -> str: + return x + + +def to_boolean_type(x: str) -> bool: + if x.lower() not in {"true", "false"}: + raise ValueError(f"Not a boolean: {x}") + + return x.lower() == "true" + + +def to_float_type(x: str) -> float: + # TODO: Handle coercion failures + return float(x) + + +def to_integer_type(x: str) -> int: + # TODO: Handle coercion failures + return int(x) + + +def to_list_type(x: str) -> list[Any]: + # TODO: Handle coercion failures + x_coerced = cast(JsonType, json.loads(x)) + + if not isinstance(x_coerced, list): + raise ValueError(f"Not a list: {x}") + + return x_coerced + + +def to_mapping_type(x: str) -> dict[str, Any]: + # TODO: Handle coercion failures + x_coerced = cast(JsonType, json.loads(x)) + + if not isinstance(x_coerced, dict): + raise ValueError(f"Not a mapping: {x}") + + return x_coerced diff --git a/src/dioptra/restapi/v1/workflows/lib/views.py b/src/dioptra/restapi/v1/workflows/lib/views.py index 8459dcced..d4bf3340d 100644 --- a/src/dioptra/restapi/v1/workflows/lib/views.py +++ b/src/dioptra/restapi/v1/workflows/lib/views.py @@ -19,8 +19,13 @@ from structlog.stdlib import BoundLogger from dioptra.restapi.db import db, models - -from ..errors import JobEntryPointDoesNotExistError +from dioptra.restapi.errors import EntityDoesNotExistError +from dioptra.restapi.v1.entrypoints.service import ( + RESOURCE_TYPE as ENTRYPONT_RESOURCE_TYPE, +) +from dioptra.restapi.v1.experiments.service import ( + RESOURCE_TYPE as EXPERIMENT_RESOURCE_TYPE, +) LOGGER: BoundLogger = structlog.stdlib.get_logger() @@ -48,11 +53,7 @@ def get_entry_point( entry_point = db.session.scalar(entry_point_stmt) if entry_point is None: - log.debug( - "The job's entrypoint does not exist", - job_id=job_id, - ) - raise JobEntryPointDoesNotExistError + raise EntityDoesNotExistError(ENTRYPONT_RESOURCE_TYPE, job_id=job_id) return entry_point @@ -78,11 +79,7 @@ def get_experiment(job_id: int, logger: BoundLogger | None = None) -> models.Exp experiment = db.session.scalar(experiment_stmt) if experiment is None: - log.debug( - "The experiment associated with the job does not exist", - job_id=job_id, - ) - raise JobEntryPointDoesNotExistError + raise EntityDoesNotExistError(EXPERIMENT_RESOURCE_TYPE, job_id=job_id) return experiment @@ -135,3 +132,34 @@ def get_job_parameter_values( models.EntryPointParameterValue.job_resource_id == job_id, ) return list(db.session.scalars(entry_point_param_values_stmt).unique().all()) + + +def get_plugin_parameter_types( + job_id: int, logger: BoundLogger | None = None +) -> list[models.PluginTaskParameterType]: + """Run a query to get the plugin task parameter types for the job. + + Args: + job_id: The ID of the job to get the plugin task parameter types for. + logger: A structlog logger object to use for logging. A new logger will be + created if None. + + Returns: + The plugin files for the entrypoint. + """ + log = logger or LOGGER.new() # noqa: F841 + + group_id_stmt = select(models.Resource.group_id).where( + models.Resource.resource_id == job_id + ) + plugin_parameter_types_stmt = ( + select(models.PluginTaskParameterType) + .join(models.Resource) + .where( + models.Resource.is_deleted == False, # noqa: E712 + models.Resource.group_id == group_id_stmt.scalar_subquery(), + models.Resource.latest_snapshot_id + == models.PluginTaskParameterType.resource_snapshot_id, + ) + ) + return list(db.session.scalars(plugin_parameter_types_stmt).all()) diff --git a/src/dioptra/restapi/v1/workflows/service.py b/src/dioptra/restapi/v1/workflows/service.py index 3150c831d..d5769e274 100644 --- a/src/dioptra/restapi/v1/workflows/service.py +++ b/src/dioptra/restapi/v1/workflows/service.py @@ -20,7 +20,8 @@ import structlog from structlog.stdlib import BoundLogger -from .lib import package_job_files, views +from .lib import views +from .lib.package_job_files import package_job_files from .schema import FileTypes LOGGER: BoundLogger = structlog.stdlib.get_logger() @@ -51,12 +52,16 @@ def get(self, job_id: int, file_type: FileTypes, **kwargs) -> IO[bytes]: job_id=job_id, logger=log ) job_parameter_values = views.get_job_parameter_values(job_id=job_id, logger=log) + plugin_parameter_types = views.get_plugin_parameter_types( + job_id=job_id, logger=log + ) return package_job_files( job_id=job_id, experiment=experiment, entry_point=entry_point, entry_point_plugin_files=entry_point_plugin_files, job_parameter_values=job_parameter_values, + plugin_parameter_types=plugin_parameter_types, file_type=file_type, logger=log, ) diff --git a/src/dioptra/rq/__version__.py b/src/dioptra/rq/__version__.py index 694c5ce36..ccdd03af1 100644 --- a/src/dioptra/rq/__version__.py +++ b/src/dioptra/rq/__version__.py @@ -14,4 +14,4 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -__version__ = "1.0.0" +__version__ = "1.0.1" diff --git a/src/dioptra/rq/tasks/run_v1_dioptra_job.py b/src/dioptra/rq/tasks/run_v1_dioptra_job.py index eaba19702..524b0d40a 100644 --- a/src/dioptra/rq/tasks/run_v1_dioptra_job.py +++ b/src/dioptra/rq/tasks/run_v1_dioptra_job.py @@ -133,7 +133,7 @@ def _extract_scheme_and_netloc(api_url: str) -> tuple[str, str]: return parsed_api_url.scheme, parsed_api_url.netloc -def run_v1_dioptra_job(job_id: int, experiment_id: int) -> None: +def run_v1_dioptra_job(job_id: int, experiment_id: int) -> None: # noqa: C901 """Fetches the job files from the Dioptra API and runs the job. Args: @@ -180,17 +180,41 @@ def run_v1_dioptra_job(job_id: int, experiment_id: int) -> None: run_dioptra_job_path = working_dir / "run_dioptra_job.py" # Use client to download the job files for the provided job_id - job_files_package = client.download_job_files( - job_id=job_id, output_dir=working_dir - ) + try: + job_files_package = client.download_job_files( + job_id=job_id, output_dir=working_dir + ) + + except Exception as e: + client.set_job_status( + job_id=job_id, experiment_id=experiment_id, status="failed" + ) + log.exception("Could not download job files") + raise e # Unpack the (trusted) tar.gz file in it. - with tarfile.open(job_files_package, mode="r:*") as tar: - tar.extractall(path=working_dir, filter="data") + try: + with tarfile.open(job_files_package, mode="r:*") as tar: + tar.extractall(path=working_dir, filter="data") + + except Exception as e: + client.set_job_status( + job_id=job_id, experiment_id=experiment_id, status="failed" + ) + log.exception("Could not extract from tar file") + raise e # Import the run_dioptra_job.py file as a module - with sys_path_dirs(dirs=(str(working_dir),)): - run_dioptra_job = importlib.import_module(run_dioptra_job_path.stem) + try: + with sys_path_dirs(dirs=(str(working_dir),)): + run_dioptra_job = importlib.import_module(run_dioptra_job_path.stem) + + except Exception as e: + client.set_job_status( + job_id=job_id, experiment_id=experiment_id, status="failed" + ) + log.exception("Could not import run_dioptra_job.py") + raise e # Execute the main function in the included script file. try: diff --git a/src/dioptra/sdk/__version__.py b/src/dioptra/sdk/__version__.py index 694c5ce36..ccdd03af1 100644 --- a/src/dioptra/sdk/__version__.py +++ b/src/dioptra/sdk/__version__.py @@ -14,4 +14,4 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode -__version__ = "1.0.0" +__version__ = "1.0.1" diff --git a/src/dioptra/sdk/exceptions/task_engine.py b/src/dioptra/sdk/exceptions/task_engine.py index db06ebb99..0937527d2 100644 --- a/src/dioptra/sdk/exceptions/task_engine.py +++ b/src/dioptra/sdk/exceptions/task_engine.py @@ -67,7 +67,7 @@ def __str__(self) -> str: class StepNotFoundError(StepError): - """A reference to a non-existent step.""" + """A reference to a nonexistent step.""" def __init__(self, step_name: str, context_step_name: Optional[str] = None) -> None: super().__init__("Step not found: " + step_name, context_step_name) @@ -76,7 +76,7 @@ def __init__(self, step_name: str, context_step_name: Optional[str] = None) -> N class OutputNotFoundError(StepError): - """A reference to a non-existent output of an existing step.""" + """A reference to a nonexistent output of an existing step.""" def __init__( self, step_name: str, output_name: str, context_step_name: Optional[str] = None @@ -135,7 +135,7 @@ def __init__( class TaskPluginNotFoundError(StepError): - """A reference to a non-existent task plugin.""" + """A reference to a nonexistent task plugin.""" def __init__( self, task_plugin_short_name: str, context_step_name: Optional[str] = None diff --git a/src/dioptra/sdk/utilities/contexts/__init__.py b/src/dioptra/sdk/utilities/contexts/__init__.py index 7f3a3b2c1..869a68c92 100644 --- a/src/dioptra/sdk/utilities/contexts/__init__.py +++ b/src/dioptra/sdk/utilities/contexts/__init__.py @@ -14,8 +14,9 @@ # # ACCESS THE FULL CC BY 4.0 LICENSE HERE: # https://creativecommons.org/licenses/by/4.0/legalcode +from ._env_vars import env_vars from ._plugin_dirs import plugin_dirs from ._redirect_print import redirect_print from ._sys_path_dirs import sys_path_dirs -__all__ = ["plugin_dirs", "redirect_print", "sys_path_dirs"] +__all__ = ["plugin_dirs", "redirect_print", "sys_path_dirs", "env_vars"] diff --git a/src/dioptra/sdk/utilities/contexts/_env_vars.py b/src/dioptra/sdk/utilities/contexts/_env_vars.py new file mode 100644 index 000000000..aab391762 --- /dev/null +++ b/src/dioptra/sdk/utilities/contexts/_env_vars.py @@ -0,0 +1,48 @@ +import os +from contextlib import contextmanager +from typing import Iterator + + +@contextmanager +def env_vars(env_updates: dict[str, str]) -> Iterator[None]: + """Create a context for temporarily updating environment variables. + + Args: + env_updates: A dictionary that maps the environment variables (keys) to a new + value. Both the keys and values must be strings. + + Examples: + The example below shows how to use env_vars to set/update the value of the + environment variable __A within a context block. First, import the os module + and check the current value of __A (we provide a a default value because this + environment variable should not exist). + + >>> import os + >>> print(os.getenv("__A", "default value of __A")) + default value of __A + + Next, set up a with statement using env_vars to set a new value for __A confirm + that the update worked. + + >>> with env_vars({"__A": "new value of __A"}): + ... print(os.getenv("__A", "default value of A")) + new value of __A + + Finally, confirm that __A has been restored to its default value after exiting + the with statement. + + >>> print(os.getenv("__A", "default value of __A")) + default value of __A + + Note: + This code is adapted from https://stackoverflow.com/a/34333710. + """ + original_env = os.environ.copy() + os.environ.update(env_updates) + + try: + yield + + finally: + os.environ.clear() + os.environ.update(original_env) diff --git a/src/dioptra/task_engine/error_message.py b/src/dioptra/task_engine/error_message.py index 018197b38..ecc7f4e9b 100644 --- a/src/dioptra/task_engine/error_message.py +++ b/src/dioptra/task_engine/error_message.py @@ -220,7 +220,7 @@ def _get_one_of_alternative_names( # rare case... would only apply to true/false schemas I think. name = "Alternative #" + str(idx + 1) - # uniquefy names, just in case... + # uniquify names, just in case... name_count = name_counts[name] name_counts[name] += 1 if name_count == 0: @@ -259,7 +259,7 @@ def _is_valid_for_sub_schema( resolver=jsonschema.validators.RefResolver.from_schema(full_schema), ) - return cast(bool, validator.is_valid(sub_instance)) + return validator.is_valid(sub_instance) def _one_of_too_many_alternatives_satisfied_message_lines( @@ -280,11 +280,15 @@ def _one_of_too_many_alternatives_satisfied_message_lines( in another, with indented lines. """ - alt_names = _get_one_of_alternative_names(error.validator_value, schema) + # In this specific case, validator_value contains the oneOf alternative + # schemas, but the typing is such that mypy can't tell that's the case. + alt_schemas = cast(Iterable[Any], error.validator_value) + + alt_names = _get_one_of_alternative_names(alt_schemas, schema) error_desc = "Must be exactly one of: {}".format(", ".join(alt_names)) satisfied_alt_names = [] - for alt_name, alt_schema in zip(alt_names, error.validator_value): + for alt_name, alt_schema in zip(alt_names, alt_schemas): # Perform a little "mini" validation to determine which alternatives # were satisfied, and describe them in the error message. if _is_valid_for_sub_schema(schema, alt_schema, error.instance): @@ -323,9 +327,13 @@ def _one_of_no_alternatives_satisfied_message_lines( message_lines = [] + # In this specific case, validator_value contains the oneOf alternative + # schemas, but the typing is such that mypy can't tell that's the case. + alt_schemas = cast(Iterable[Any], error.validator_value) + # First error message line describes the error in basic terms. - alt_names = _get_one_of_alternative_names(error.validator_value, schema) + alt_names = _get_one_of_alternative_names(alt_schemas, schema) basic_desc = ( "Must be exactly one of: {}; all alternatives failed validation." ).format(", ".join(alt_names)) diff --git a/src/frontend/README.md b/src/frontend/README.md index ef97b8b1f..aa029fecc 100644 --- a/src/frontend/README.md +++ b/src/frontend/README.md @@ -6,110 +6,7 @@ This template should help get you started developing with Vue 3 in Vite. In order to get a development instance of the web app to work properly, the REST API also needs to be served. -The following steps will be necessary: - -- Create a [Python virtual environment](../../README.md#setting-up-the-python-virtual-environment) and use `pip-sync` to install the development packages - -- Follow the [User Setup](../../README.md#user-setup) instructions - - - Be sure to activate the virtual environment you created in the previous step - - - Install the other prerequisites needed to use the cookiecutter template - - - Use the cookiecutter template to generate the scripts, configuration files, and Docker Compose files you will need for your development environment - - - Build the containers - -- Run a database migration to add the latest table definitions to a local SQLite database that will be stored in the project root using the following commands if using bash shell: - - ```sh - export DIOPTRA_RESTAPI_DEV_DATABASE_URI=sqlite:///$(pwd)/dioptra-dev.db - export DIOPTRA_RESTAPI_ENV=dev - export DIOPTRA_SESSION_PROTECTION=none - dioptra-db autoupgrade - ``` - -- If running windows powershell, use these commands instead: - - ``` - $env:DIOPTRA_RESTAPI_DEV_DATABASE_URI="sqlite:///$pwd\dioptra-dev.db" - $env:DIOPTRA_RESTAPI_ENV="dev" - $env:DIOPTRA_SESSION_PROTECTION="none" - dioptra-db autoupgrade - ``` - -- Several modifications to the files produced from the cookiecutter template will be necessary - - - First modify the `init-deployments.sh` so that the `main` function at the bottom of the file has been commented out: - - ```sh - main() { - parse_args "${@}" - init_scripts - # init_extra_ca_certificates - init_named_volumes - init_minio - # start_db_service - # manage_postgres_ssl - stop_services - } - ``` - - - Modify the `docker-compose.yml` - - - Comment out all of the services except for `dioptra-deployment-redis` and `dioptra-deployment-minio` (the `volumes` section at the bottom can be left unmodified) - - - Add the following `ports` section to `dioptra-deployment-minio` service: - - ```yaml - ports: - - 127.0.0.1:9000:9000/tcp - - 127.0.0.1:9001:9001/tcp - ``` - - - Add the following `ports` section to `dioptra-deployment-redis` service: - - ```yaml - ports: - - 127.0.0.1:6379:6379/tcp - ``` - -- Run the `init-deployments.sh` script - -- Now create a new script file outside of the source code directory, `start-flask`, to start-up the flask server in development mode. - - - `chmod 755 start-flask` to make it executable - - - Environment variables from the `secrets/dioptra-deployment-restapi.env` file should be added - - - Environment variables from `envs/dioptra-deployment-restapi.env` should be copied - - - for `DIOPTRA_RESTAPI_ENV` change from `prod` to `dev` - - - Change the hostname for each of the URLs to `localhost` from their generated values - - - The final script file should look something like the below: - - ```sh - export AWS_ACCESS_KEY_ID=dioptra-restapi - export AWS_SECRET_ACCESS_KEY= - export MLFLOW_S3_ENDPOINT_URL=http://localhost:9000 - export MLFLOW_TRACKING_URI=http://localhost:5000 - export RQ_REDIS_URI=redis://localhost:6379/0 - export DIOPTRA_RESTAPI_DEV_DATABASE_URI=sqlite:///$(pwd)/dioptra-dev.db - export DIOPTRA_RESTAPI_ENV=dev - flask run --host ::1 - ``` - -- Prior to running `start-flask` you will need to run `docker-compose up -d` in the cookie cutter template directory to start some required services - - - Checking that everything started normally can be done through `docker-compose logs -f` - - - Shutting down the services can be done through `docker-compose down` - -- When running the `start-flask` script as configured above you will need to run it the current directory as the project directory where the SQLite database was initialized. - -From here, move on to starting the vite development server using the instructions below. +- Follow the instructions in (Local Development Setup) ../../DEVELOPER.md#local-development-setup-without-containers to get a local development enivronment up and running. ## Recommended IDE Setup diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json new file mode 100644 index 000000000..f34b55fa4 --- /dev/null +++ b/src/frontend/package-lock.json @@ -0,0 +1,3927 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@codemirror/lang-python": "^6.1.6", + "@codemirror/lang-yaml": "^6.0.0", + "@codemirror/lint": "^6.5.0", + "@codemirror/theme-one-dark": "^6.1.2", + "@quasar/extras": "^1.16.9", + "axios": "^1.6.7", + "codemirror": "^6.0.1", + "js-yaml": "^4.1.0", + "pinia": "^2.1.7", + "quasar": "^2.14.2", + "vue": "^3.3.11", + "vue-codemirror": "^6.1.1", + "vue-router": "^4.2.5", + "yaml": "^2.5.0" + }, + "devDependencies": { + "@quasar/vite-plugin": "^1.6.0", + "@rushstack/eslint-patch": "^1.3.3", + "@tsconfig/node18": "^18.2.2", + "@types/node": "^18.19.3", + "@vitejs/plugin-vue": "^4.5.2", + "@vue/eslint-config-prettier": "^8.0.0", + "@vue/eslint-config-typescript": "^12.0.0", + "@vue/tsconfig": "^0.5.0", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.17.0", + "npm-run-all2": "^6.1.1", + "prettier": "^3.0.3", + "sass": "^1.70.0", + "typescript": "~5.3.0", + "vite": "^5.0.10", + "vue-tsc": "^1.8.25" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz", + "integrity": "sha512-fdfj6e6ZxZf8yrkMHUSJJir7OJkHkZKaOZGzLWIYp2PZ3jd+d+UjG8zVPqJF6d3bKxkhvXTPan/UZ1t7Bqm0gA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", + "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", + "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.1.tgz", + "integrity": "sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", + "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", + "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", + "license": "MIT" + }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", + "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.28.5", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.5.tgz", + "integrity": "sha512-NkUtfUa1lV7Jqg5DfHE/uLl7jKyoymDkaueMQXzePYuezL7FwX3ATANy74iAGlHCGe25hBGB0R+I5dC5EZ5JBg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", + "license": "MIT" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", + "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz", + "integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.14.tgz", + "integrity": "sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", + "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@quasar/extras": { + "version": "1.16.12", + "resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.16.12.tgz", + "integrity": "sha512-hLlb3Buxo38Xg/2w0BTkz98RBh/VH8apZ2r6Fl8YpPgrVQ0diHyN/BVTvIOk5Kch2y38L2kvwOIddsB2UcCuIg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/@quasar/vite-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@quasar/vite-plugin/-/vite-plugin-1.7.0.tgz", + "integrity": "sha512-ia4w1n4DuPYm92MQLPNpMqLJID1WGGRyVGxkVeg8V+V25Vh3p9QBo++iuXR4sW/bCmzzx66Ko6VStsr1zp90GQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + }, + "peerDependencies": { + "@vitejs/plugin-vue": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "quasar": "^2.16.0", + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", + "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node18": { + "version": "18.2.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.4.tgz", + "integrity": "sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.19.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.40.tgz", + "integrity": "sha512-MIxieZHrm4Ee8XArBIc+Or9HINt2StOmCbgRcXGSJl8q14svRvkZPe7LJq9HKtTI1SK3wU8b91TjntUm7T69Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "1.11.1" + } + }, + "node_modules/@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.32.tgz", + "integrity": "sha512-8tCVWkkLe/QCWIsrIvExUGnhYCAOroUs5dzhSoKL5w4MJS8uIYiou+pOPSVIOALOQ80B0jBs+Ri+kd5+MBnCDw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.32", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.32.tgz", + "integrity": "sha512-PbSgt9KuYo4fyb90dynuPc0XFTfFPs3sCTbPLOLlo+PrUESW1gn/NjSsUvhR+mI2AmmEzexwYMxbHDldxSOr2A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.32.tgz", + "integrity": "sha512-STy9im/WHfaguJnfKjjVpMHukxHUrOKjm2vVCxiojQJyo3Sb6Os8SMXBr/MI+ekpstEGkDONfqAQoSbZhspLYw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.32", + "@vue/compiler-dom": "3.4.32", + "@vue/compiler-ssr": "3.4.32", + "@vue/shared": "3.4.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.39", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.32.tgz", + "integrity": "sha512-nyu/txTecF6DrxLrpLcI34xutrvZPtHPBj9yRoPxstIquxeeyywXpYZrQMsIeDfBhlw1abJb9CbbyZvDw2kjdg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==", + "license": "MIT" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz", + "integrity": "sha512-55dPqtC4PM/yBjhAr+yEw6+7KzzdkBuLmnhBrDfp4I48+wy+Giqqj9yUr5T2uD/BkBROjjmqnLZmXRdOx/VtQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.0.0" + }, + "peerDependencies": { + "eslint": ">= 8.0.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz", + "integrity": "sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", + "vue-eslint-parser": "^9.3.1" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.32.tgz", + "integrity": "sha512-1P7QvghAzhSIWmiNmh4MNkLVjr2QTNDcFv2sKmytEWhR6t7BZzNicgm5ENER4uU++wbWxgRh/pSEYgdI3MDcvg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.32.tgz", + "integrity": "sha512-FxT2dTHUs1Hki8Ui/B1Hu339mx4H5kRJooqrNM32tGUHBPStJxwMzLIRbeGO/B1NMplU4Pg9fwOqrJtrOzkdfA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.32.tgz", + "integrity": "sha512-Xz9G+ZViRyPFQtRBCPFkhMzKn454ihCPMKUiacNaUhuTIXvyfkAq8l89IZ/kegFVyw/7KkJGRGqYdEZrf27Xsg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.32", + "@vue/runtime-core": "3.4.32", + "@vue/shared": "3.4.32", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.32.tgz", + "integrity": "sha512-3c4rd0522Ao8hKjzgmUAbcjv2mBnvnw0Ld2f8HOMCuWJZjYie/p8cpIoYJbeP0VV2JYmrJJMwGQDO5RH4iQ30A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.4.32", + "@vue/shared": "3.4.32" + }, + "peerDependencies": { + "vue": "3.4.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.32.tgz", + "integrity": "sha512-ep4mF1IVnX/pYaNwxwOpJHyBtOMKWoKZMbnUyd+z0udqIxLUh7YCCd/JfDna8aUrmnG9SFORyIq2HzEATRrQsg==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", + "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/codemirror": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.27.0.tgz", + "integrity": "sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.0", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-all2": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.2.2.tgz", + "integrity": "sha512-Q+alQAGIW7ZhKcxLt8GcSi3h3ryheD6xnmXahkMRVM5LYmajcUrSITm8h+OPC9RYWMV2GR0Q1ntTUCfxaNoOJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.3", + "memorystream": "^0.3.1", + "minimatch": "^9.0.0", + "pidtree": "^0.6.0", + "read-package-json-fast": "^3.0.2", + "shell-quote": "^1.7.3" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^14.18.0 || ^16.13.0 || >=18.0.0", + "npm": ">= 8" + } + }, + "node_modules/npm-run-all2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pinia": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": ">=0.14.5" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quasar": { + "version": "2.16.6", + "resolved": "https://registry.npmjs.org/quasar/-/quasar-2.16.6.tgz", + "integrity": "sha512-nFFS/WniZy052wUNr0UHxc46KVB0hVg7IlBpVScxQAANQxL5uJVqaiw0z2CEM8IM+MCObXANqxHX/m7woG7zIw==", + "license": "MIT", + "engines": { + "node": ">= 10.18.1", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sass": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", + "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.32.tgz", + "integrity": "sha512-9mCGIAi/CAq7GtaLLLp2J92pEic+HArstG+pq6F+H7+/jB9a0Z7576n4Bh4k79/50L1cKMIhZC3MC0iGpl+1IA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.32", + "@vue/compiler-sfc": "3.4.32", + "@vue/runtime-dom": "3.4.32", + "@vue/server-renderer": "3.4.32", + "@vue/shared": "3.4.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-codemirror": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz", + "integrity": "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==", + "license": "MIT", + "dependencies": { + "@codemirror/commands": "6.x", + "@codemirror/language": "6.x", + "@codemirror/state": "6.x", + "@codemirror/view": "6.x" + }, + "peerDependencies": { + "codemirror": "6.x", + "vue": "3.x" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.0.tgz", + "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yaml": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/frontend/package.json b/src/frontend/package.json index c878beee3..cf859fc84 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -25,7 +25,8 @@ "quasar": "^2.14.2", "vue": "^3.3.11", "vue-codemirror": "^6.1.1", - "vue-router": "^4.2.5" + "vue-router": "^4.2.5", + "yaml": "^2.5.0" }, "devDependencies": { "@quasar/vite-plugin": "^1.6.0", diff --git a/src/frontend/src/App.vue b/src/frontend/src/App.vue index 5a83887fe..ca1e8a32f 100644 --- a/src/frontend/src/App.vue +++ b/src/frontend/src/App.vue @@ -20,7 +20,12 @@ const isMobile = computed(() => { return $q.screen.sm || $q.screen.xs }) + + const isMedium = computed(() => { + return $q.screen.md || $q.screen.sm || $q.screen.xs + }) provide('isMobile', isMobile) + provide('isMedium', isMedium) \ No newline at end of file diff --git a/src/frontend/src/assets/main.css b/src/frontend/src/assets/main.css index 0c3a6cc25..d33396368 100644 --- a/src/frontend/src/assets/main.css +++ b/src/frontend/src/assets/main.css @@ -38,12 +38,36 @@ p { font-size: 1.2em } -.darkLink { - color: #579aca +.body--dark a { + color: #51bef4; + font-weight: 500; } -a:hover { - color: #ee9040 +.body--dark { + color: #cecece !important; +} + +.body--dark .q-field__messages [role="alert"] { + color: #ff5353 !important; + font-weight: 500; +} + +.q-notification__message { + color: white; +} + +.body--dark .q-tab { + color: #e4e4e4; +} + +.body--dark .q-card, +.body--dark .q-table { + color: #cecece; +} + +a:hover, +a.q-breadcrumbs__el:hover { + color: #f27e19 !important; } .q-tab:hover { @@ -79,12 +103,13 @@ a:hover { clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */ clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */ clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/ - white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */ + white-space: nowrap; /* added line to stop words getting smushed together (as they go onto separate lines and some screen readers do not understand line feeds as a space */ } h1 { font-size: clamp(1rem, 10vw, 4rem) !important; - line-height: 1 !important; + line-height: 1 !important; + font-weight: 400 !important; } h2 { @@ -93,25 +118,14 @@ h2 { margin-bottom: 0; } -.form-title { - font-size: clamp(1rem, 10vw, 3rem) !important; - font-weight: bold; -} - .field-label { width: 100px; font-size: 1rem; color: black; } -.field-label-short { - width: 100px; - font-size: 1rem; - color: black; -} - .body--dark .field-label { - color: white; + color: #cecece; } legend { diff --git a/src/frontend/src/components/CodeEditor.vue b/src/frontend/src/components/CodeEditor.vue index b49bad032..b5546c4e2 100644 --- a/src/frontend/src/components/CodeEditor.vue +++ b/src/frontend/src/components/CodeEditor.vue @@ -8,17 +8,14 @@ :tab-size="2" :extensions="extensions" @ready="handleReady" - @change="console.log('change', $event)" - @focus="console.log('focus', $event)" - @blur="console.log('blur', $event)" + @update="highlightPlaceholder" :style="{ 'min-height': '250px', 'max-height': '70vh', 'border': `${showError ? '2px solid red' : '2px solid black'}` }" /> {{ showError || '...' }} @@ -26,7 +23,7 @@ \ No newline at end of file diff --git a/src/frontend/src/components/LoggedInForm.vue b/src/frontend/src/components/LoggedInForm.vue index a7cf9f469..a03e55599 100644 --- a/src/frontend/src/components/LoggedInForm.vue +++ b/src/frontend/src/components/LoggedInForm.vue @@ -1,7 +1,7 @@