diff --git a/pyproject.toml b/pyproject.toml index 17816432..e8f6d099 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,13 +55,12 @@ dependencies = [ [project.optional-dependencies] server = [ - "Flask>=2.0", - "Werkzeug==2.0.3", + "Flask>=3.0", "flask-caching>=1.10", "flask-compress>=1.12", "flask-cors>=3", "flask-mail~=0.9.1", - "flask-restx==0.5", + "flask-restx>=1.0.0", "python-magic~=0.4", "simplejson~=3.0", ] diff --git a/src/simdb/remote/apis/__init__.py b/src/simdb/remote/apis/__init__.py index 72f2716d..ca03561e 100644 --- a/src/simdb/remote/apis/__init__.py +++ b/src/simdb/remote/apis/__init__.py @@ -1,9 +1,10 @@ import datetime +import threading from pathlib import Path import appdirs import jwt -from flask import Blueprint, Response, _app_ctx_stack, jsonify, request +from flask import Blueprint, Response, jsonify, request from flask_restx import Resource from simdb import __version__ @@ -47,7 +48,7 @@ def setup_db(setup_state): args = config.get_section("database") setup_state.app.db = Database( Database.DBMS.POSTGRESQL, - scopefunc=_app_ctx_stack.__ident_func__, + scopefunc=lambda: threading.get_ident(), **args, ) elif db_type == "sqlite": @@ -57,7 +58,7 @@ def setup_db(setup_state): ) file.parent.mkdir(parents=True, exist_ok=True) setup_state.app.db = Database( - Database.DBMS.SQLITE, scopefunc=_app_ctx_stack.__ident_func__, file=file + Database.DBMS.SQLITE, scopefunc=lambda: threading.get_ident(), file=file ) else: raise RuntimeError(f"Unknown database type in configuration: {db_type}.") diff --git a/src/simdb/remote/apis/files.py b/src/simdb/remote/apis/files.py index e846fa57..e18a940e 100644 --- a/src/simdb/remote/apis/files.py +++ b/src/simdb/remote/apis/files.py @@ -1,11 +1,10 @@ import gzip -import json import uuid from pathlib import Path from typing import Dict, Iterable, List, Optional import magic -from flask import Response, jsonify, request, send_file, stream_with_context +from flask import Response, jsonify, request, send_file from flask_restx import Namespace, Resource from werkzeug.datastructures import FileStorage @@ -14,13 +13,18 @@ from simdb.database import DatabaseError, models from simdb.imas.checksum import checksum as imas_checksum from simdb.imas.utils import imas_files -from simdb.json import CustomDecoder from simdb.remote.core.auth import User, requires_auth from simdb.remote.core.errors import error from simdb.remote.core.path import find_common_root, secure_path from simdb.remote.core.pydantic_utils import pydantic_validate from simdb.remote.core.typing import current_app -from simdb.remote.models import FileDataList, FileGetDataResponse +from simdb.remote.models import ( + ChunkInfo, + FileDataList, + FileGetDataResponse, + FileRegistrationData, + FileUploadData, +) from simdb.uri import URI api = Namespace("files", path="/") @@ -68,10 +72,10 @@ def _verify_file( def _save_chunked_file( - file: FileStorage, chunk_info: Dict, path: Path, compressed: bool = True + file: FileStorage, chunk_info: ChunkInfo, path: Path, compressed: bool = True ): with path.open("r+b" if path.exists() else "wb") as file_out: - file_out.seek(chunk_info["chunk_size"] * chunk_info["chunk"]) + file_out.seek(chunk_info.chunk_size * chunk_info.chunk) if compressed: with gzip.GzipFile(fileobj=file.stream, mode="rb") as gz_file: file_out.write(gz_file.read()) @@ -81,7 +85,7 @@ def _save_chunked_file( def _stage_file_from_chunks( files: Iterable[FileStorage], - chunk_info: Dict, + chunk_info: Dict[str, ChunkInfo], sim_uuid: uuid.UUID, sim_files: List[models.File], common_root: Optional[Path], @@ -107,7 +111,7 @@ def _stage_file_from_chunks( path = secure_path(sim_file.uri.path, common_root, staging_dir) path.parent.mkdir(parents=True, exist_ok=True) file_chunk_info = chunk_info.get( - sim_file.uuid.hex, {"chunk_size": 0, "chunk": 0, "num_chunks": 1} + sim_file.uuid.hex, ChunkInfo(chunk_size=0, chunk=0, num_chunks=1) ) _save_chunked_file(file, file_chunk_info, path) @@ -122,39 +126,33 @@ def _check_file_is_in_simulation( return sim_file -def _process_simulation_data(data: dict) -> Response: - simulation = models.Simulation.from_data(data["simulation"]) +def _process_simulation_data(body: FileRegistrationData) -> Response: + simulation = models.Simulation.from_data_model(body.simulation) sim_file_paths = simulation.file_paths() common_root = find_common_root(sim_file_paths) - if DataObject.Type(data["obj_type"]) == DataObject.Type.FILE: - for file in data["files"]: + if body.obj_type == DataObject.Type.FILE: + for file in body.files: sim_file = _check_file_is_in_simulation( - simulation, uuid.UUID(file["file_uuid"]), file["file_type"] + simulation, file.file_uuid, file.file_type ) _verify_file(simulation.uuid, sim_file, common_root) - elif DataObject.Type(data["obj_type"]) == DataObject.Type.IMAS: - file = data["files"][0] + elif body.obj_type == DataObject.Type.IMAS: + file = body.files[0] sim_files = ( - simulation.inputs if file["file_type"] == "input" else simulation.outputs + simulation.inputs if file.file_type == "input" else simulation.outputs ) - sim_file = next(f for f in sim_files if f.uuid == uuid.UUID(file["file_uuid"])) - _verify_file(simulation.uuid, sim_file, common_root, file["ids_list"]) + sim_file = next(f for f in sim_files if f.uuid == file.file_uuid) + _verify_file(simulation.uuid, sim_file, common_root, file.ids_list) else: - raise ValueError("Unsupported object type {}".format(data["obj_type"])) + raise ValueError(f"Unsupported object type {body.obj_type}") return jsonify({}) def _handle_file_upload() -> Response: - data: dict = json.load(request.files["data"].stream, cls=CustomDecoder) + body = FileUploadData.model_validate_json(request.files["data"].stream.read()) - if "simulation" not in data: - return error("Simulation data not provided") - - simulation = models.Simulation.from_data(data["simulation"]) - - chunk_info = data.get("chunk_info", {}) - file_type = data["file_type"] + simulation = models.Simulation.from_data_model(body.simulation) files = request.files.getlist("files") if not files: @@ -163,8 +161,10 @@ def _handle_file_upload() -> Response: sim_file_paths = simulation.file_paths() common_root = find_common_root(sim_file_paths) - sim_files = simulation.inputs if file_type == "input" else simulation.outputs - _stage_file_from_chunks(files, chunk_info, simulation.uuid, sim_files, common_root) + sim_files = simulation.inputs if body.file_type == "input" else simulation.outputs + _stage_file_from_chunks( + files, body.chunk_info or {}, simulation.uuid, sim_files, common_root + ) return jsonify({}) @@ -180,9 +180,9 @@ def get(self, user: User) -> FileDataList: @requires_auth() def post(self, user: User): try: - data = request.get_json() - if data: - return _process_simulation_data(data) + if request.is_json: + body = FileRegistrationData.model_validate_json(request.get_data()) + return _process_simulation_data(body) return _handle_file_upload() except ValueError as err: @@ -209,11 +209,7 @@ def get(self, file_uuid: str, user: Optional[User] = None): if file.uri.path is None: return error("File path is not set") mimetype = magic.from_file(file.uri.path, mime=True) - response = send_file(file.uri.path, mimetype=mimetype) - return Response( - stream_with_context(response.iter_content()), - content_type=response.headers["content-type"], - ) + return send_file(file.uri.path, mimetype=mimetype) except DatabaseError as err: return error(str(err)) diff --git a/src/simdb/remote/app.py b/src/simdb/remote/app.py index 1509953e..f436165d 100644 --- a/src/simdb/remote/app.py +++ b/src/simdb/remote/app.py @@ -8,7 +8,6 @@ from simdb.config import Config from simdb.database.database import check_migrations, run_migrations -from simdb.json import CustomDecoder, CustomEncoder from .apis import blueprints from .core.auth._authenticator import Authenticator @@ -33,8 +32,6 @@ def create_app( app.config["DEBUG"] = debug app.config["RESTX_INCLUDE_ALL_MODELS"] = True app.config["PROFILE"] = profile - app.json_encoder = CustomEncoder # ty: ignore[invalid-assignment] - app.json_decoder = CustomDecoder # ty: ignore[invalid-assignment] app.config.from_mapping(flask_options) app.simdb_config = config cache.init_app(app) diff --git a/tests/remote/api/conftest.py b/tests/remote/api/conftest.py index 6fbe2e3e..17c8ab01 100644 --- a/tests/remote/api/conftest.py +++ b/tests/remote/api/conftest.py @@ -32,7 +32,7 @@ SIMULATIONS.append(Simulation(Manifest())) -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def client(): if not has_flask: pytest.skip("Flask not installed") # type: ignore @@ -50,14 +50,13 @@ def client(): app = create_app(config=config, testing=True, debug=True) app.testing = True - with app.test_client() as client: - # with app.app_context(): - for sim in SIMULATIONS: - app.db.insert_simulation(sim) + test_sims = [Simulation(Manifest()) for _ in range(100)] - app.db.session.commit() - app.db.session.close() + with app.app_context(): + for sim in test_sims: + app.db.insert_simulation(sim) + with app.test_client() as client: yield client os.close(db_fd) @@ -65,7 +64,7 @@ def client(): shutil.rmtree(upload_dir) -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def client_copy_files(): if not has_flask: pytest.skip("Flask not installed") # type: ignore @@ -83,14 +82,11 @@ def client_copy_files(): app = create_app(config=config, testing=True, debug=True) app.testing = True - with app.test_client() as client: - # with app.app_context(): + with app.app_context(): for sim in SIMULATIONS: app.db.insert_simulation(sim) - app.db.session.commit() - app.db.session.close() - + with app.test_client() as client: yield client os.close(db_fd) diff --git a/uv.lock b/uv.lock index 4a21152b..3aca3c3b 100644 --- a/uv.lock +++ b/uv.lock @@ -1948,19 +1948,53 @@ wheels = [ [[package]] name = "flask" -version = "2.1.3" +version = "3.0.3" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", +] dependencies = [ - { name = "click" }, + { name = "blinker", version = "1.8.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "click", marker = "python_full_version < '3.9'" }, { name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "itsdangerous", marker = "python_full_version < '3.9'" }, + { name = "jinja2", marker = "python_full_version < '3.9'" }, + { name = "werkzeug", version = "3.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/e1/d104c83026f8d35dfd2c261df7d64738341067526406b40190bc063e829a/flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842", size = 676315, upload-time = "2024-04-07T19:26:11.035Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/80/ffe1da13ad9300f87c93af113edd0638c75138c42a0994becfacac078c06/flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3", size = 101735, upload-time = "2024-04-07T19:26:08.569Z" }, +] + +[[package]] +name = "flask" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version >= '3.13' and platform_machine != 'ARM64') or (python_full_version >= '3.13' and sys_platform != 'win32')", + "python_full_version == '3.12.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.12.*' and platform_machine != 'ARM64') or (python_full_version == '3.12.*' and sys_platform != 'win32')", + "python_full_version == '3.11.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.11.*' and platform_machine != 'ARM64') or (python_full_version == '3.11.*' and sys_platform != 'win32')", + "python_full_version == '3.10.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.10.*' and platform_machine != 'ARM64') or (python_full_version == '3.10.*' and sys_platform != 'win32')", + "python_full_version > '3.9' and python_full_version < '3.10'", + "python_full_version == '3.9'", +] +dependencies = [ + { name = "blinker", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "click", marker = "python_full_version >= '3.9'" }, { name = "importlib-metadata", version = "8.7.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "itsdangerous" }, - { name = "jinja2" }, - { name = "werkzeug" }, + { name = "itsdangerous", marker = "python_full_version >= '3.9'" }, + { name = "jinja2", marker = "python_full_version >= '3.9'" }, + { name = "markupsafe", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "werkzeug", version = "3.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/77/3accd62b8771954e9584beb03f080385b32ddcad30009d2a4fe4068a05d9/Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb", size = 630206, upload-time = "2022-07-13T20:56:00.126Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/00/35d85dcce6c57fdc871f3867d465d780f302a175ea360f62533f12b27e2b/flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", size = 759004, upload-time = "2026-02-19T05:00:57.678Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/6a/00d144ac1626fbb44c4ff36519712e258128985a5d0ae43344778ae5cbb9/Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c", size = 95556, upload-time = "2022-07-13T20:55:57.512Z" }, + { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, ] [[package]] @@ -1975,7 +2009,8 @@ resolution-markers = [ ] dependencies = [ { name = "cachelib", marker = "python_full_version < '3.10'" }, - { name = "flask", marker = "python_full_version < '3.10'" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e2/80/74846c8af58ed60972d64f23a6cd0c3ac0175677d7555dff9f51bf82c294/flask_caching-2.3.1.tar.gz", hash = "sha256:65d7fd1b4eebf810f844de7de6258254b3248296ee429bdcb3f741bcbf7b98c9", size = 67560, upload-time = "2025-02-23T01:34:40.207Z" } wheels = [ @@ -1998,7 +2033,7 @@ resolution-markers = [ ] dependencies = [ { name = "cachelib", marker = "python_full_version >= '3.10'" }, - { name = "flask", marker = "python_full_version >= '3.10'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/53/5c46b6a80adc13ed9179879a93cfc2c1f190c64c48ba732b4f5819df520e/flask_caching-2.4.0.tar.gz", hash = "sha256:a7f14e43617cd0612a57bec2f80516d6d2ec888bfc50a807b1e4e41ca345a3b5", size = 153673, upload-time = "2026-04-17T20:27:24.318Z" } wheels = [ @@ -2016,7 +2051,7 @@ resolution-markers = [ dependencies = [ { name = "brotli", marker = "python_full_version < '3.9' and platform_python_implementation != 'PyPy'" }, { name = "brotlicffi", marker = "python_full_version < '3.9' and platform_python_implementation == 'PyPy'" }, - { name = "flask", marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "zstandard", marker = "python_full_version < '3.9'" }, { name = "zstandard", extra = ["cffi"], marker = "python_full_version < '3.9' and platform_python_implementation == 'PyPy'" }, ] @@ -2046,7 +2081,7 @@ dependencies = [ { name = "backports-zstd", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and python_full_version < '3.14'" }, { name = "brotli", marker = "python_full_version >= '3.9' and platform_python_implementation != 'PyPy'" }, { name = "brotlicffi", marker = "python_full_version >= '3.9' and platform_python_implementation == 'PyPy'" }, - { name = "flask", marker = "python_full_version >= '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c2/de/2ae0118051b38ab53437328074a696f3ee7d61e15bf7454b78a3088e5bc3/flask_compress-1.24.tar.gz", hash = "sha256:14097cefe59ecb3e466d52a6aeb62f34f125a9f7dadf1f33a53e430ce4a50f31", size = 21089, upload-time = "2026-03-31T15:01:39.005Z" } wheels = [ @@ -2062,7 +2097,7 @@ resolution-markers = [ "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", ] dependencies = [ - { name = "flask", marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4f/d0/d9e52b154e603b0faccc0b7c2ad36a764d8755ef4036acbf1582a67fb86b/flask_cors-5.0.0.tar.gz", hash = "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef", size = 30954, upload-time = "2024-08-31T00:44:26.395Z" } wheels = [ @@ -2086,9 +2121,9 @@ resolution-markers = [ "python_full_version == '3.9'", ] dependencies = [ - { name = "flask", marker = "python_full_version >= '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "werkzeug", marker = "python_full_version >= '3.9'" }, + { name = "werkzeug", version = "3.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/54/99/6c69b758eeb129fff6693a668293a192e54bb3bae256eee099a9e3019815/flask_cors-6.0.4.tar.gz", hash = "sha256:cf3db91a0874aecde0a276565bf4adf4a458edcfd42e668fb0a260549f129317", size = 100100, upload-time = "2026-06-07T22:00:03.712Z" } wheels = [ @@ -2102,27 +2137,62 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blinker", version = "1.8.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "blinker", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "flask" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/05/2f/6a545452040c2556559779db87148d2a85e78a26f90326647b51dc5e81e9/Flask-Mail-0.9.1.tar.gz", hash = "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41", size = 45654, upload-time = "2014-09-28T23:35:22.329Z" } [[package]] name = "flask-restx" -version = "0.5.0" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", +] dependencies = [ - { name = "aniso8601" }, - { name = "flask" }, + { name = "aniso8601", marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "importlib-resources", version = "6.4.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "jsonschema", version = "4.23.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytz", marker = "python_full_version < '3.9'" }, + { name = "werkzeug", version = "3.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/4c/2e7d84e2b406b47cf3bf730f521efe474977b404ee170d8ea68dc37e6733/flask-restx-1.3.0.tar.gz", hash = "sha256:4f3d3fa7b6191fcc715b18c201a12cd875176f92ba4acc61626ccfd571ee1728", size = 2814072, upload-time = "2023-12-10T14:48:55.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/bf/1907369f2a7ee614dde5152ff8f811159d357e77962aa3f8c2e937f63731/flask_restx-1.3.0-py2.py3-none-any.whl", hash = "sha256:636c56c3fb3f2c1df979e748019f084a938c4da2035a3e535a4673e4fc177691", size = 2798683, upload-time = "2023-12-10T14:48:53.293Z" }, +] + +[[package]] +name = "flask-restx" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version >= '3.13' and platform_machine != 'ARM64') or (python_full_version >= '3.13' and sys_platform != 'win32')", + "python_full_version == '3.12.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.12.*' and platform_machine != 'ARM64') or (python_full_version == '3.12.*' and sys_platform != 'win32')", + "python_full_version == '3.11.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.11.*' and platform_machine != 'ARM64') or (python_full_version == '3.11.*' and sys_platform != 'win32')", + "python_full_version == '3.10.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.10.*' and platform_machine != 'ARM64') or (python_full_version == '3.10.*' and sys_platform != 'win32')", + "python_full_version > '3.9' and python_full_version < '3.10'", + "python_full_version == '3.9'", +] +dependencies = [ + { name = "aniso8601", marker = "python_full_version >= '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "importlib-resources", version = "6.5.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "importlib-resources", version = "7.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "jsonschema", version = "4.25.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, { name = "jsonschema", version = "4.26.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pytz" }, - { name = "six" }, - { name = "werkzeug" }, + { name = "referencing", version = "0.36.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "referencing", version = "0.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "werkzeug", version = "3.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/06/3745812225fe5c34456d9e874c55219aec8e44dd2053117d4e600761db62/flask-restx-0.5.0.tar.gz", hash = "sha256:7e9f7cd5e843dd653a71fafb7c8ce9d7b4fef29f982a2254b1e0ebb3fac1fe12", size = 5314490, upload-time = "2021-07-19T13:07:15.224Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/89/9b9ca58cbb8e9ec46f4a510ba93878e0c88d518bf03c350e3b1b7ad85cbe/flask-restx-1.3.2.tar.gz", hash = "sha256:0ae13d77e7d7e4dce513970cfa9db45364aef210e99022de26d2b73eb4dbced5", size = 2814719, upload-time = "2025-09-23T20:34:25.21Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/f4/d0c58c90297b4be184f3dd61209132aca40617f818618fa99bc33cf1fb5a/flask_restx-0.5.0-py2.py3-none-any.whl", hash = "sha256:c3c2b724e688c0a50ee5e78f2a508b7f0c34644f00f64170fa8a3d0cdc34f67a", size = 5359772, upload-time = "2021-07-19T13:07:12.61Z" }, + { url = "https://files.pythonhosted.org/packages/7a/3f/b82cd8e733a355db1abb8297afbf59ec972c00ef90bf8d4eed287958b204/flask_restx-1.3.2-py2.py3-none-any.whl", hash = "sha256:6e035496e8223668044fc45bf769e526352fd648d9e159bd631d94fd645a687b", size = 2799859, upload-time = "2025-09-23T20:34:23.055Z" }, ] [[package]] @@ -2681,7 +2751,8 @@ dependencies = [ [package.optional-dependencies] all = [ - { name = "flask" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "flask-caching", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "flask-caching", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "flask-compress", version = "1.15", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, @@ -2689,13 +2760,13 @@ all = [ { name = "flask-cors", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "flask-cors", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "flask-mail" }, - { name = "flask-restx" }, + { name = "flask-restx", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask-restx", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "imas-validator" }, { name = "psycopg2-binary", version = "2.9.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "psycopg2-binary", version = "2.9.12", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "python-magic" }, { name = "simplejson" }, - { name = "werkzeug" }, ] auth = [ { name = "easyad" }, @@ -2734,7 +2805,9 @@ build-docs = [ { name = "sphinx-autodoc-typehints", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx-autodoc-typehints", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx-autodoc-typehints", version = "3.10.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "sphinx-rtd-theme" }, + { name = "sphinx-immaterial", version = "0.11.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "sphinx-immaterial", version = "0.12.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "sphinx-immaterial", version = "0.13.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] imas-validator = [ { name = "imas-validator" }, @@ -2744,7 +2817,8 @@ postgres = [ { name = "psycopg2-binary", version = "2.9.12", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] server = [ - { name = "flask" }, + { name = "flask", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask", version = "3.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "flask-caching", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "flask-caching", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "flask-compress", version = "1.15", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, @@ -2752,10 +2826,10 @@ server = [ { name = "flask-cors", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "flask-cors", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "flask-mail" }, - { name = "flask-restx" }, + { name = "flask-restx", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "flask-restx", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "python-magic" }, { name = "simplejson" }, - { name = "werkzeug" }, ] [package.dev-dependencies] @@ -2783,12 +2857,12 @@ requires-dist = [ { name = "docutils", marker = "extra == 'build-docs'", specifier = ">=0.17" }, { name = "easyad", marker = "extra == 'auth-ad'", specifier = ">=1.0" }, { name = "email-validator", specifier = ">=1.1" }, - { name = "flask", marker = "extra == 'server'", specifier = ">=2.0" }, + { name = "flask", marker = "extra == 'server'", specifier = ">=3.0" }, { name = "flask-caching", marker = "extra == 'server'", specifier = ">=1.10" }, { name = "flask-compress", marker = "extra == 'server'", specifier = ">=1.12" }, { name = "flask-cors", marker = "extra == 'server'", specifier = ">=3" }, { name = "flask-mail", marker = "extra == 'server'", specifier = "~=0.9.1" }, - { name = "flask-restx", marker = "extra == 'server'", specifier = "==0.5" }, + { name = "flask-restx", marker = "extra == 'server'", specifier = ">=1.0.0" }, { name = "imas-python" }, { name = "imas-simdb", extras = ["auth-ad", "auth-keycloak", "auth-ldap"], marker = "extra == 'auth'" }, { name = "imas-simdb", extras = ["imas-validator", "postgres", "server"], marker = "extra == 'all'" }, @@ -2811,10 +2885,9 @@ requires-dist = [ { name = "simplejson", marker = "extra == 'server'", specifier = "~=3.0" }, { name = "sphinx", marker = "extra == 'build-docs'", specifier = ">=4.5" }, { name = "sphinx-autodoc-typehints", marker = "extra == 'build-docs'", specifier = ">=1.12.0" }, - { name = "sphinx-rtd-theme", marker = "extra == 'build-docs'", specifier = ">=1.0.0" }, + { name = "sphinx-immaterial", marker = "extra == 'build-docs'", specifier = ">=0.11.14" }, { name = "sqlalchemy", specifier = ">=1.2.12,<2.0" }, { name = "urllib3", specifier = ">=1.26" }, - { name = "werkzeug", marker = "extra == 'server'", specifier = "==2.0.3" }, ] provides-extras = ["server", "auth-ad", "auth-keycloak", "auth-ldap", "auth", "imas-validator", "build-docs", "postgres", "all"] @@ -4765,6 +4838,48 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, ] +[[package]] +name = "pydantic-extra-types" +version = "2.10.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", +] +dependencies = [ + { name = "pydantic", version = "2.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/10/fb64987804cde41bcc39d9cd757cd5f2bb5d97b389d81aa70238b14b8a7e/pydantic_extra_types-2.10.6.tar.gz", hash = "sha256:c63d70bf684366e6bbe1f4ee3957952ebe6973d41e7802aea0b770d06b116aeb", size = 141858, upload-time = "2025-10-08T13:47:49.483Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl", hash = "sha256:6106c448316d30abf721b5b9fecc65e983ef2614399a24142d689c7546cc246a", size = 40949, upload-time = "2025-10-08T13:47:48.268Z" }, +] + +[[package]] +name = "pydantic-extra-types" +version = "2.11.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version >= '3.13' and platform_machine != 'ARM64') or (python_full_version >= '3.13' and sys_platform != 'win32')", + "python_full_version == '3.12.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.12.*' and platform_machine != 'ARM64') or (python_full_version == '3.12.*' and sys_platform != 'win32')", + "python_full_version == '3.11.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.11.*' and platform_machine != 'ARM64') or (python_full_version == '3.11.*' and sys_platform != 'win32')", + "python_full_version == '3.10.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.10.*' and platform_machine != 'ARM64') or (python_full_version == '3.10.*' and sys_platform != 'win32')", + "python_full_version > '3.9' and python_full_version < '3.10'", + "python_full_version == '3.9'", +] +dependencies = [ + { name = "pydantic", version = "2.13.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/71/dba38ee2651f84f7842206adbd2233d8bbdb59fb85e9fa14232486a8c471/pydantic_extra_types-2.11.1.tar.gz", hash = "sha256:46792d2307383859e923d8fcefa82108b1a141f8a9c0198982b3832ab5ef1049", size = 172002, upload-time = "2026-03-16T08:08:03.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/c1/3226e6d7f5a4f736f38ac11a6fbb262d701889802595cdb0f53a885ac2e0/pydantic_extra_types-2.11.1-py3-none-any.whl", hash = "sha256:1722ea2bddae5628ace25f2aa685b69978ef533123e5638cfbddb999e0100ec1", size = 79526, upload-time = "2026-03-16T08:08:02.533Z" }, +] + [[package]] name = "pygments" version = "2.19.2" @@ -6719,23 +6834,76 @@ wheels = [ ] [[package]] -name = "sphinx-rtd-theme" -version = "3.1.0" +name = "sphinx-immaterial" +version = "0.11.14" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", +] dependencies = [ - { name = "docutils", version = "0.20.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "appdirs", marker = "python_full_version < '3.9'" }, + { name = "markupsafe", version = "2.1.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pydantic", version = "2.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pydantic-extra-types", version = "2.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "requests", version = "2.32.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, { name = "sphinx", version = "7.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/1f/5403cb6bd08f2f13c86d9b5367e56078dbe17d11c0bd91becdf34d454976/sphinx_immaterial-0.11.14.tar.gz", hash = "sha256:e1e8ba93c78a3e007743fede01a3be43f5ae97c5cc19b8e2a4d2aa058abead61", size = 8330984, upload-time = "2024-07-03T20:09:35.091Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/fa/db6916f719970ebdd433c5606bea98bbf899d71f255efced93992f944f1a/sphinx_immaterial-0.11.14-py3-none-any.whl", hash = "sha256:dd1a30614c8ecaa931155189e7d54f211232e31cf3e5c6d28ba9f04a4817f0a3", size = 10872122, upload-time = "2024-07-03T20:09:31.945Z" }, +] + +[[package]] +name = "sphinx-immaterial" +version = "0.12.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version > '3.9' and python_full_version < '3.10'", + "python_full_version == '3.9'", +] +dependencies = [ + { name = "appdirs", marker = "python_full_version == '3.9.*'" }, + { name = "markupsafe", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "pydantic", version = "2.13.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "pydantic-extra-types", version = "2.11.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/e8/c0ac85c8864b4aada1aa71c0c7a326cce1d8581689c18cb05348ce30bf24/sphinx_immaterial-0.12.5.tar.gz", hash = "sha256:a7c0c4be3dcb4960eb7b299dfee07cdf8a02bf56821f5d0d62e5d31b7b7b5ec5", size = 8349000, upload-time = "2025-01-30T22:51:51.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/99/90471644a1dfa18fb801544c9eb3663893801cec049defe077e0e6026c1e/sphinx_immaterial-0.12.5-py3-none-any.whl", hash = "sha256:4173b22ad343fd9c75b51baf305851d89b98b94603c474b428e30e8c8476673b", size = 10885262, upload-time = "2025-01-30T22:51:47.207Z" }, +] + +[[package]] +name = "sphinx-immaterial" +version = "0.13.9" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version >= '3.13' and platform_machine != 'ARM64') or (python_full_version >= '3.13' and sys_platform != 'win32')", + "python_full_version == '3.12.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.12.*' and platform_machine != 'ARM64') or (python_full_version == '3.12.*' and sys_platform != 'win32')", + "python_full_version == '3.11.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.11.*' and platform_machine != 'ARM64') or (python_full_version == '3.11.*' and sys_platform != 'win32')", + "python_full_version == '3.10.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.10.*' and platform_machine != 'ARM64') or (python_full_version == '3.10.*' and sys_platform != 'win32')", +] +dependencies = [ + { name = "appdirs", marker = "python_full_version >= '3.10'" }, + { name = "markupsafe", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic", version = "2.13.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-extra-types", version = "2.11.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "requests", version = "2.34.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-jquery" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/84/68/a1bfbf38c0f7bccc9b10bbf76b94606f64acb1552ae394f0b8285bfaea25/sphinx_rtd_theme-3.1.0.tar.gz", hash = "sha256:b44276f2c276e909239a4f6c955aa667aaafeb78597923b1c60babc76db78e4c", size = 7620915, upload-time = "2026-01-12T16:03:31.17Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/c7/b5c8015d823bfda1a346adb2c634a2101d50bb75d421eb6dcb31acd25ebc/sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl", hash = "sha256:1785824ae8e6632060490f67cf3a72d404a85d2d9fc26bce3619944de5682b89", size = 7655617, upload-time = "2026-01-12T16:03:28.101Z" }, + { url = "https://files.pythonhosted.org/packages/3d/42/6e958fc5d80ccd18c87d1b7d7c0e17fed04c0ed8a72933dd41c8643622d4/sphinx_immaterial-0.13.9-py3-none-any.whl", hash = "sha256:5ea92d2ddc6befcd0fedbd3e6766ea4746e94d9a8a5cc0ab092a946e1fde4254", size = 13742592, upload-time = "2026-02-06T16:53:11.262Z" }, ] [[package]] @@ -6840,22 +7008,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, ] -[[package]] -name = "sphinxcontrib-jquery" -version = "4.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx", version = "7.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331, upload-time = "2023-03-14T15:01:01.944Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104, upload-time = "2023-03-14T15:01:00.356Z" }, -] - [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" @@ -7296,11 +7448,42 @@ wheels = [ [[package]] name = "werkzeug" -version = "2.0.3" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/a8/60514fade2318e277453c9588545d0c335ea3ea6440ce5cdabfca7f73117/Werkzeug-2.0.3.tar.gz", hash = "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c", size = 895551, upload-time = "2022-02-07T21:04:39.14Z" } +resolution-markers = [ + "python_full_version < '3.9' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.9' and platform_python_implementation == 'PyPy'", +] +dependencies = [ + { name = "markupsafe", version = "2.1.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/f9/0ba83eaa0df9b9e9d1efeb2ea351d0677c37d41ee5d0f91e98423c7281c9/werkzeug-3.0.6.tar.gz", hash = "sha256:a8dd59d4de28ca70471a34cba79bed5f7ef2e036a76b3ab0835474246eb41f8d", size = 805170, upload-time = "2024-10-25T18:52:31.688Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/69/05837f91dfe42109203ffa3e488214ff86a6d68b2ed6c167da6cdc42349b/werkzeug-3.0.6-py3-none-any.whl", hash = "sha256:1bc0c2310d2fbb07b1dd1105eba2f7af72f322e1e455f2f93c993bee8c8a5f17", size = 227979, upload-time = "2024-10-25T18:52:30.129Z" }, +] + +[[package]] +name = "werkzeug" +version = "3.1.8" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version >= '3.13' and platform_machine != 'ARM64') or (python_full_version >= '3.13' and sys_platform != 'win32')", + "python_full_version == '3.12.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.12.*' and platform_machine != 'ARM64') or (python_full_version == '3.12.*' and sys_platform != 'win32')", + "python_full_version == '3.11.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.11.*' and platform_machine != 'ARM64') or (python_full_version == '3.11.*' and sys_platform != 'win32')", + "python_full_version == '3.10.*' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "(python_full_version == '3.10.*' and platform_machine != 'ARM64') or (python_full_version == '3.10.*' and sys_platform != 'win32')", + "python_full_version > '3.9' and python_full_version < '3.10'", + "python_full_version == '3.9'", +] +dependencies = [ + { name = "markupsafe", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/b2/381be8cfdee792dd117872481b6e378f85c957dd7c5bca38897b08f765fd/werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44", size = 875852, upload-time = "2026-04-02T18:49:14.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/f3/22afbdb20cc4654b10c98043414a14057cd27fdba9d4ae61cea596000ba2/Werkzeug-2.0.3-py3-none-any.whl", hash = "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8", size = 289232, upload-time = "2022-02-07T21:04:36.336Z" }, + { url = "https://files.pythonhosted.org/packages/93/8c/2e650f2afeb7ee576912636c23ddb621c91ac6a98e66dc8d29c3c69446e1/werkzeug-3.1.8-py3-none-any.whl", hash = "sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50", size = 226459, upload-time = "2026-04-02T18:49:12.72Z" }, ] [[package]]