diff --git a/.eslintignore b/.eslintignore index 4a8b0ed..9c27bc4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,2 @@ *.css -registerServiceWorker.js \ No newline at end of file +registerServiceWorker.js diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index a63eeee..3651b0e 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -53,4 +53,4 @@ jobs: if: ${{ always() }} - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 \ No newline at end of file + uses: codecov/codecov-action@v1 diff --git a/.gitignore b/.gitignore index 7d3a87d..5712abb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ dist/ downloads/ eggs/ .eggs/ -lib/ lib64/ parts/ sdist/ @@ -134,4 +133,12 @@ dash_extensions/* inst/* **/file_system_backend/* man/* -R/* \ No newline at end of file +R/* + +.idea/* +pc_ex1/* +page_components/* +NAMESPACE +DESCRIPTION +jsconfig.json +tmp**.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..48a8ac1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +# default_language_version: +# python: python3.9 + +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.5 + hooks: + - id: ruff + - id: ruff-format + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + # - id: check-yaml + - id: check-toml + - id: check-added-large-files + - id: check-merge-conflict + additional_dependencies: ["flake8-docstrings", "darglint"] diff --git a/.vscode/settings.json b/.vscode/settings.json index bf17c58..58926aa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,4 +7,4 @@ ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 434fe77..7f8eaf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. +## [1.0.16] - 05-28-24 + +### Added + +- Add new `SSE` component, which can receive (and buffer) server sent events such the output from an LLM. +- Add new `LoadingTransform`, which makes it easy to re-use a single (full screen) loading component across the app. +- Add new `BaseModelTransform`, which automates serialization/deserialization of Pydantic `BaseModel` objects. + ## [1.0.15] - 05-04-24 ### Added @@ -160,7 +168,7 @@ All notable changes to this project will be documented in this file. ### Changed -- Reimplementation of the `BeforeAfter` component by @AnnMarieW adding new features and improved mobile compatibility. NB: This is a **breaking** change, please consult the docs for an example using the new syntax +- Reimplementation of the `BeforeAfter` component by @AnnMarieW adding new features and improved mobile compatibility. NB: This is a **breaking** change, please consult the docs for an example using the new syntax - Improved support for the new `callback(background=True, ...)` syntax adding support for the `set_progress` keyword - Added syntax sugar for Celery task registration for use with the `CeleryManager` object - Added explicit raise of `NotImplementedError` for the (deprecated) `long_callback` syntax @@ -194,7 +202,7 @@ All notable changes to this project will be documented in this file. ### Changed -- Added info on pypi (has been missing after poetry migration) +- Added info on pypi (has been missing after poetry migration) - Added `CycleBreakerInput` component, which is to be used instead of the `break_cycle` keyword in 0.1.1 - Fixed introduced bug when mixing imports from `dash` and `dash_extensions.enrich` @@ -368,7 +376,7 @@ All notable changes to this project will be documented in this file. ### Change -- Bugfixes in `MultiplexerTransform`, both of dcc.Loading and of proxies firing unintentionally on load. +- Bugfixes in `MultiplexerTransform`, both of dcc.Loading and of proxies firing unintentionally on load. - Reintroduced the `TriggerTransform` based on community feedback. - Security fixes of underlying npm packages. @@ -383,7 +391,7 @@ All notable changes to this project will be documented in this file. - Updated `Burger` component; added new properties, added new example, slight changes to interface. - Updated `multipage_app.py` example; removed dependency on burger menu, removed burger helper function in `multipage.py`. -- Added a `hijack` function to the `DashProxy` object. It can be used to inject app state into other app objects, typically used in frameworks such as dataiku 9.0 where the `Dash` object is constructed outside of the user code context. +- Added a `hijack` function to the `DashProxy` object. It can be used to inject app state into other app objects, typically used in frameworks such as dataiku 9.0 where the `Dash` object is constructed outside of the user code context. ### Remove @@ -492,7 +500,7 @@ All notable changes to this project will be documented in this file. ### Added -- A new `enrich` module has been added. It exposes the functionality of previous callback blueprints (and more!) through a drop in replacement of (enriched) Dash components. +- A new `enrich` module has been added. It exposes the functionality of previous callback blueprints (and more!) through a drop in replacement of (enriched) Dash components. - Added folder of example code. ### Changed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc39028..356a7c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,3 @@ # CONTRIBUTING This project was generated by the [dash-component-boilerplate](https://github.com/plotly/dash-component-boilerplate) it contains the minimal set of code required to create your own custom Dash component. - diff --git a/TODO.md b/TODO.md index 667a039..5293d20 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,2 @@ * Go through component doc strings -* Add docs for dynamic components \ No newline at end of file +* Add docs for dynamic components diff --git a/_validate_init.py b/_validate_init.py index e21492e..7a2e2fb 100644 --- a/_validate_init.py +++ b/_validate_init.py @@ -2,12 +2,12 @@ DO NOT MODIFY This file is used to validate your publish settings. """ + from __future__ import print_function +import importlib import os import sys -import importlib - components_package = "dash_extensions" @@ -45,14 +45,16 @@ def check_manifest(filename): def check_file(dist, filename): if not check_dist(dist, filename): - print(missing_dist_msg.format(filename, components_package, "_js_dist"), file=sys.stderr) + print( + missing_dist_msg.format(filename, components_package, "_js_dist"), + file=sys.stderr, + ) if not check_manifest(filename): print(missing_manifest_msg.format(filename), file=sys.stderr) for cur, _, files in os.walk(components_package): for f in files: - if f.endswith("js"): # noinspection PyProtectedMember check_file(components_lib._js_dist, f) diff --git a/codecov.yml b/codecov.yml index 96bcafe..df5c62b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,2 +1,2 @@ ignore: - - "dash_extensions/snippets.py" \ No newline at end of file + - "dash_extensions/snippets.py" diff --git a/dash_extensions/__init__.py b/dash_extensions/__init__.py index 2aad93e..67859f8 100644 --- a/dash_extensions/__init__.py +++ b/dash_extensions/__init__.py @@ -1,13 +1,13 @@ from __future__ import print_function as _ +import json import os as _os import sys as _sys -import json import dash as _dash # noinspection PyUnresolvedReferences -from ._imports_ import * +from ._imports_ import * # noqa: F401, F403 from ._imports_ import __all__ if not hasattr(_dash, "__plotly_dash") and not hasattr(_dash, "development"): diff --git a/dash_extensions/_imports_.py b/dash_extensions/_imports_.py index ad5c62d..1eae1e8 100644 --- a/dash_extensions/_imports_.py +++ b/dash_extensions/_imports_.py @@ -8,6 +8,7 @@ from .Lottie import Lottie from .Mermaid import Mermaid from .Purify import Purify +from .SSE import SSE from .WebSocket import WebSocket __all__ = [ @@ -21,5 +22,6 @@ "Lottie", "Mermaid", "Purify", + "SSE", "WebSocket" ] \ No newline at end of file diff --git a/dash_extensions/dataiku.py b/dash_extensions/dataiku.py index b616ac2..c12b588 100644 --- a/dash_extensions/dataiku.py +++ b/dash_extensions/dataiku.py @@ -1,15 +1,15 @@ import os import re +from distutils.dir_util import copy_tree from dash import Dash -from distutils.dir_util import copy_tree """ -The purpose of this module is to ease the integration of Dash with Dataiku. +The purpose of this module is to ease the integration of Dash with Dataiku. """ -def bind_assets_folder(app: Dash, app_id: str, assets_folder: str): +def bind_assets_folder(app: Dash, app_id: str, assets_folder: str): # noqa: C901 """ Dataiku 10 doesn't support separate asset folders for each Dash app. This function targets fixing this issue by (1) creating a new asset sub folder for each app, and (2) limiting asset loading to this folder. diff --git a/dash_extensions/enrich.py b/dash_extensions/enrich.py index df676c7..92f3518 100644 --- a/dash_extensions/enrich.py +++ b/dash_extensions/enrich.py @@ -11,47 +11,47 @@ import sys import threading import uuid -import plotly +from collections import defaultdict +from datetime import datetime +from itertools import compress +from typing import Any, Callable, Dict, Generic, List, Optional, Tuple, TypeVar, Union + import dash +import plotly # Enable enrich as drop-in replacement for dash # noinspection PyUnresolvedReferences -from dash import ( # lgtm [py/unused-import] - no_update, - Output, - State, - Input, - ClientsideFunction, - MATCH, +from dash import ( # lgtm [py/unused-import]; noqa: F401 ALL, ALLSMALLER, - development, - exceptions, - resources, + MATCH, + ClientsideFunction, + Input, + Output, + State, + callback_context, # noqa: F401 + ctx, # noqa: F401 + dash_table, # noqa: F401 dcc, + development, # noqa: F401 + exceptions, # noqa: F401 html, - dash_table, - callback_context, - callback, - clientside_callback, - page_container, - page_registry, - register_page, - ctx + no_update, + page_container, # noqa: F401 + page_registry, # noqa: F401 + register_page, # noqa: F401 + resources, # noqa: F401 ) from dash._callback_context import context_value from dash._utils import patch_collections_abc -from dash.dependencies import _Wildcard, DashDependency # lgtm [py/unused-import] +from dash.dependencies import DashDependency, _Wildcard # lgtm [py/unused-import] from dash.development.base_component import Component +from dataclass_wizard import asdict, fromdict from flask import session from flask_caching.backends import FileSystemCache, RedisCache -from itertools import compress -from more_itertools import flatten -from collections import defaultdict -from typing import Dict, Callable, List, Union, Any, Tuple, Optional, Generic, TypeVar -from datetime import datetime +from pydantic import BaseModel # type: ignore + from dash_extensions import CycleBreaker -from dataclass_wizard import fromdict, asdict T = TypeVar("T") @@ -63,6 +63,7 @@ # region DependencyCollection + def build_index(structure, entry, index): if isinstance(structure, list): for i, s in enumerate(structure): @@ -78,7 +79,7 @@ def build_index(structure, entry, index): raise ValueError(f"Unsupported structure {str(structure)}") -def validate_structure(structure, level=0): +def validate_structure(structure, level=0): # noqa: C901 if isinstance(structure, DashDependency): if level == 0: return [structure] @@ -107,12 +108,18 @@ def __init__(self, structure, keyword=None): self._re_index() def __getitem__(self, key: int): + if self._index is None: + raise ValueError("Index not built.") return self.get(self._index[key]) def __setitem__(self, key: int, value): + if self._index is None: + raise ValueError("Index not built.") return self.set(self._index[key], value) def __len__(self): + if self._index is None: + raise ValueError("Index not built.") return len(self._index) def __iter__(self): @@ -128,16 +135,18 @@ def index(self, value): def get(self, multi_index): e = self.structure for j in multi_index: - e = e[j] + e = e[j] # type: ignore return e def set(self, multi_index, value): e = self.structure for i, j in enumerate(multi_index): if i == len(multi_index) - 1: - e[j] = value + e[j] = value # type: ignore def append(self, value, flex_key=None, index=None): + if self._index is None: + raise ValueError("Index not built.") i = len(self._index) if isinstance(self.structure, list): if index is not None: @@ -162,6 +171,7 @@ def _re_index(self): # region Dash blueprint + def collect_args(args: Union[Tuple[Any], List[Any]], inputs, outputs): for arg in args: if isinstance(arg, (list, tuple)): @@ -201,12 +211,16 @@ def __init__(self, *args, **kwargs): # Collect dummy elements. if kwargs.get("background", False) and "progress" in kwargs: # This element represents the set_progress function. - self.inputs.append(DummyDependency("function", "set_progress"), index=0, flex_key="set_progress") + self.inputs.append( + DummyDependency("function", "set_progress"), + index=0, + flex_key="set_progress", + ) # Collect the rest. self.kwargs: Dict[str, Any] = kwargs self.f = None - def register(self, app: dash.Dash): + def register(self, app: dash.Dash): # noqa: C901 # Collect dependencies. dep_args, dep_kwargs = [], {} for dep_col in [self.outputs, self.inputs]: @@ -250,7 +264,11 @@ def multi_output(self) -> bool: class DashBlueprint: - def __init__(self, transforms: List[DashTransform] = None, include_global_callbacks: bool = False): + def __init__( + self, + transforms: List[DashTransform] = None, + include_global_callbacks: bool = False, + ): self.callbacks: List[CallbackBlueprint] = [] self.clientside_callbacks: List[CallbackBlueprint] = [] self.transforms = _resolve_transforms(transforms) @@ -293,7 +311,9 @@ def register_callbacks(self, app: Union[dash.Dash, DashBlueprint]): for cbp in callbacks + clientside_callbacks: cbp.register(app) - def _resolve_callbacks(self) -> Tuple[List[CallbackBlueprint], List[CallbackBlueprint]]: + def _resolve_callbacks( + self, + ) -> Tuple[List[CallbackBlueprint], List[CallbackBlueprint]]: """ This method resolves the callbacks, i.e. it applies the callback injections. """ @@ -308,15 +328,21 @@ def _resolve_callbacks(self) -> Tuple[List[CallbackBlueprint], List[CallbackBlue return callbacks, clientside_callbacks # TODO: Include or not? The plugin still seems a bit immature. - def register(self, app: Union[dash.Dash, DashProxy], module, prefix: Union[str, PrefixIdTransform, None]=None, **kwargs): + def register( + self, + app: Union[dash.Dash, DashProxy], + module, + prefix: Union[str, PrefixIdTransform, None] = None, + **kwargs, + ): # Add prefix transform if supplied. if prefix is not None: prefix_transform = prefix if isinstance(prefix, PrefixIdTransform) else PrefixIdTransform(prefix) - self.transforms.append(prefix_transform) + self.transforms.append(prefix_transform) # Register the callbacks and page. self.register_callbacks(app) dash.register_page(module, layout=self._layout_value, **kwargs) - + def clear(self): self.callbacks = [] self.clientside_callbacks = [] @@ -328,7 +354,10 @@ def _layout_value(self, *args, **kwargs): layout = transform.layout(layout, self._layout_is_function) return layout - def embed(self, app: DashProxy): + def embed(self, app: Union[DashBlueprint, DashProxy]): + if isinstance(app, DashBlueprint): + self.register_callbacks(app) + return self._layout_value() if app.blueprint._layout_is_function and app._got_first_request["setup_server"]: return self._layout_value() self.register_callbacks(app) @@ -356,11 +385,21 @@ class DashProxy(dash.Dash): work (e.g. setting a secret key on the server), and exposes convenience functions such as 'hijack'. """ - def __init__(self, *args, transforms=None, include_global_callbacks=True, blueprint=None, - prevent_initial_callbacks="initial_duplicate", **kwargs): + def __init__( + self, + *args, + transforms=None, + include_global_callbacks=True, + blueprint=None, + prevent_initial_callbacks="initial_duplicate", + **kwargs, + ): super().__init__(*args, prevent_initial_callbacks=prevent_initial_callbacks, **kwargs) - self.blueprint = DashBlueprint(transforms, - include_global_callbacks=include_global_callbacks) if blueprint is None else blueprint + self.blueprint = ( + DashBlueprint(transforms, include_global_callbacks=include_global_callbacks) + if blueprint is None + else blueprint + ) self.setup_server_lock = threading.Lock() def callback(self, *args, **kwargs): @@ -371,7 +410,8 @@ def clientside_callback(self, clientside_function, *args, **kwargs): def long_callback(self, *_args, **_kwargs): raise NotImplementedError( - "The 'long_callback(..)' syntax is not supported, please use 'callback(background=True, ...)' instead.") + "The 'long_callback(..)' syntax is not supported, please use 'callback(background=True, ...)' instead." + ) def register_celery_tasks(self): if sys.argv[0].endswith("celery"): @@ -453,6 +493,7 @@ def _extract_list_from_kwargs(kwargs: dict, key: str) -> list: # region Dash transform + class DashTransform: def __init__(self): self.layout_initialized = False @@ -483,7 +524,6 @@ def sort_key(self): class StatefulDashTransform(DashTransform): - def __init__(self): super().__init__() self.blueprint = DashBlueprint() @@ -536,14 +576,16 @@ def apply_serverside(self, callbacks): end_client_id = f"{callback_id}_end_client" start_blocked_id = f"{callback_id}_start_blocked" end_blocked_id = f"{callback_id}_end_blocked" - self.components.extend([ - dcc.Store(id=start_client_id), - dcc.Store(id=end_server_id), - dcc.Store(id=end_client_id), - dcc.Store(id=start_blocked_id), - dcc.Store(id=start_client_ctx), - CycleBreaker(id=end_blocked_id) - ]) + self.components.extend( + [ + dcc.Store(id=start_client_id), + dcc.Store(id=end_server_id), + dcc.Store(id=end_client_id), + dcc.Store(id=start_blocked_id), + dcc.Store(id=start_client_ctx), + CycleBreaker(id=end_blocked_id), + ] + ) # Bind start signal callback. start_callback = f"""function() {{ @@ -552,7 +594,7 @@ def apply_serverside(self, callbacks): let ctx = arguments[arguments.length-1]; const now = new Date().getTime(); const trigger = dash_clientside.callback_context.triggered[0]; - const no = window.dash_clientside.no_update + const no = window.dash_clientside.no_update // Update context. if(trigger !== undefined){{ if(!trigger.prop_id.startsWith('{end_blocked_id}')){{ @@ -561,7 +603,7 @@ def apply_serverside(self, callbacks): for (let i = 0; i < keys.length; i++) {{ let key = keys[i]; ctx[key] = dash_clientside.callback_context[key]; - }} + }} }} }} // First run => INVOKE. @@ -585,9 +627,17 @@ def apply_serverside(self, callbacks): }}""" self.blueprint.clientside_callback( start_callback, - [Output(start_client_id, "data"), Output(start_blocked_id, "data"), Output(start_client_ctx, "data")], + [ + Output(start_client_id, "data"), + Output(start_blocked_id, "data"), + Output(start_client_ctx, "data"), + ], [Input(end_blocked_id, "dst")] + list(callback.inputs), - [State(start_client_id, "data"), State(end_client_id, "data"), State(start_client_ctx, "data")], + [ + State(start_client_id, "data"), + State(end_client_id, "data"), + State(start_client_ctx, "data"), + ], ) # Bind end signal callback. end_callback = """function(endServerId, startBlockedId) @@ -602,7 +652,7 @@ def apply_serverside(self, callbacks): end_callback, [Output(end_client_id, "data"), Output(end_blocked_id, "src")], Input(end_server_id, "data"), - State(start_blocked_id, "data") + State(start_blocked_id, "data"), ) # Modify the original callback to send finished signal. num_outputs = len(callback.outputs) @@ -628,15 +678,15 @@ def decorated_function(*args, **kwargs): cached_ctx = fltr[1] single_output = num_outputs <= 1 if cached_ctx is not None and "triggered" in cached_ctx: - ctx = context_value.get() - ctx["triggered_inputs"] = cached_ctx["triggered"] - context_value.set(ctx) + local_ctx = context_value.get() + local_ctx["triggered_inputs"] = cached_ctx["triggered"] + context_value.set(local_ctx) try: outputs = f(*args, **kwargs) except Exception: logging.exception(f"Exception raised in blocking callback [{f.__name__}]") - outputs = no_update if single_output else [no_update] * num_outputs - + outputs = no_update if single_output else [no_update] * num_outputs + return _append_output(outputs, datetime.utcnow().timestamp(), single_output, out_flex_key) return decorated_function @@ -650,8 +700,12 @@ def decorated_function(*args, **kwargs): class LogConfig: - def __init__(self, log_output, log_writer_map: Dict[int, Callable], - layout_transform: Callable[[List[Component]], List[Component]]): + def __init__( + self, + log_output, + log_writer_map: Dict[int, Callable], + layout_transform: Callable[[List[Component]], List[Component]], + ): self.log_output = log_output self.log_writer_map = log_writer_map self.layout_transform = layout_transform @@ -665,7 +719,11 @@ def notification_layout_transform(layout: List[Component]): import dash_mantine_components as dmc layout.append(html.Div(id=log_id)) - return [dmc.NotificationProvider(layout)] + if dmc.__version__ < "0.14.0": + layout.append(dmc.NotificationsProvider()) + layout.append(dmc.NotificationProvider(zIndex=2000)) + + return layout return LogConfig(log_output, get_notification_log_writers(), notification_layout_transform) @@ -693,7 +751,14 @@ def get_notification_log_writers(): import dash_mantine_components as dmc def _default_kwargs(color, title, message): - return dict(color=color, title=title, message=message, id=str(uuid.uuid4()), action="show", autoClose=False) + return dict( + color=color, + title=title, + message=message, + id=str(uuid.uuid4()), + action="show", + autoClose=False, + ) def log_info(message, **kwargs): return dmc.Notification(**{**_default_kwargs("blue", "Info", message), **kwargs}) @@ -704,7 +769,11 @@ def log_warning(message, **kwargs): def log_error(message, **kwargs): return dmc.Notification(**{**_default_kwargs("red", "Error", message), **kwargs}) - return {logging.INFO: log_info, logging.WARNING: log_warning, logging.ERROR: log_error} + return { + logging.INFO: log_info, + logging.WARNING: log_warning, + logging.ERROR: log_error, + } class DashLogger: @@ -785,12 +854,77 @@ def decorated_function(*args, **kwargs): return wrapper +# endregion + +# region Loading transform + + +class LoadingTransform(DashTransform): + """ + The loading transform makes it easy to trigger a single loading component from multiple callbacks. + """ + + def __init__(self, **kwargs): + super().__init__() + kwargs_defaults = { + "overlay_style": { + "opacity": 0.5, + "backgroundColor": "white", + "width": "100vw", + "height": "100vh", + "position": "fixed", + "left": 0, + "top": 0, + "zIndex": 1000, + "visibility": "visible", + }, + "delay_show": 500, + "delay_hide": 1000, + "fullscreen": True, + "id": "loading_id", + } + self.kwargs = {**kwargs_defaults, **kwargs} + + def transform_layout(self, layout): + loading = dcc.Loading(html.Div(""), **self.kwargs) + layout.children = _as_list(layout.children) + [loading] + + def apply(self, callbacks, clientside_callbacks): + callbacks = self.apply_serverside(callbacks) + return callbacks, clientside_callbacks + + def apply_serverside(self, callbacks): + for callback in callbacks: + if not callback.kwargs.get("loading", None): + continue + # Add the log component as output. + single_output = len(callback.outputs) <= 1 + out_flex_key = callback.outputs.append(Output(self.kwargs["id"], "children", allow_duplicate=True)) + # Modify the callback function accordingly. + f = callback.f + callback.f = bind_loading(single_output, out_flex_key)(f) + + return callbacks + + +def bind_loading(single_output, out_flex_key): + def wrapper(f): + @functools.wraps(f) + def decorated_function(*args, **kwargs): + outputs = f(*args, **kwargs) + return _append_output(outputs, dash.no_update, single_output, out_flex_key) + + return decorated_function + + return wrapper + + # endregion # region Cycle breaker transform -class CycleBreakerTransform(StatefulDashTransform): +class CycleBreakerTransform(StatefulDashTransform): def __init__(self): super().__init__() @@ -861,24 +995,24 @@ def register(blueprint: DashBlueprint, name: str, prefix=None, **kwargs): class PrefixIdTransform(DashTransform): def __init__(self, prefix, prefix_func=None, escape=None): """ - The PrefixIdTransform adds a prefix to all component ids of the DashBlueprint, including - their references in callbacks. It is typically used to avoid ID collisions between + The PrefixIdTransform adds a prefix to all component ids of the DashBlueprint, including + their references in callbacks. It is typically used to avoid ID collisions between blueprints when they are registered on or embedded in the main Dash application. Args: prefix (str): The prefix that will be added to the component_ids. prefix_func (callable(str, Component, callable(str)): A function used to modify - the ID of the components. This function must accept three arguments: the + the ID of the components. This function must accept three arguments: the prefix string, a Dash component, and the escape function. If not provided, - the `prefix_component()` function is used, which relies on `apply_prefix()` + the `prefix_component()` function is used, which relies on `apply_prefix()` to calculate the new ID. - escape (callable(str)): A function that will be called by `apply_prefix()` to + escape (callable(str)): A function that will be called by `apply_prefix()` to determine whether the component's ID should remain unaltered (escaped). The - function should accept a string (the component_id) and return a boolean. - By default, `default_prefix_escape()` is used, which avoids modifying + function should accept a string (the component_id) and return a boolean. + By default, `default_prefix_escape()` is used, which avoids modifying certain IDs that start with "a-" or "anchor-". - Note: `PrefixIdTransform` is automatically registered as `transforms` by + Note: `PrefixIdTransform` is automatically registered as `transforms` by the `DashBlueprint.register()` method when the `prefix` parameter is specified. """ super().__init__() @@ -919,7 +1053,7 @@ def apply_prefix(prefix, component_id, escape): if isinstance(component_id, dict): for key in component_id: # This branch handles the IDs. TODO: Can we always assume use of ints? - if type(component_id[key]) == int: + if isinstance(component_id[key], int): continue # This branch handles the wildcard callbacks. if isinstance(component_id[key], _Wildcard): @@ -957,7 +1091,12 @@ def dynamic_prefix(app: Union[DashBlueprint, DashProxy], component: Component): if len(prefix_transforms) == 0: return prefix_transform: PrefixIdTransform = prefix_transforms[0] - prefix_recursively(component, prefix_transform.prefix, prefix_transform.prefix_func, prefix_transform.escape) + prefix_recursively( + component, + prefix_transform.prefix, + prefix_transform.prefix_func, + prefix_transform.escape, + ) # endregion @@ -975,7 +1114,6 @@ def __init__(self, component_id, component_property): class TriggerTransform(DashTransform): - def apply_serverside(self, callbacks): for callback in callbacks: is_trigger = [isinstance(item, Trigger) for item in callback.inputs] @@ -1010,7 +1148,7 @@ def filter_args(args_filter): def wrapper(f): @functools.wraps(f) def decorated_function(*args): - post_args = list(args[len(args_filter):]) + post_args = list(args[len(args_filter) :]) args = list(args[: len(args_filter)]) filtered_args = [arg for j, arg in enumerate(args) if not args_filter[j]] + post_args return f(*filtered_args) @@ -1030,6 +1168,7 @@ def trigger_filter(args): # region Multiplexer transform + class MultiplexerTransform(DashTransform): """ The MultiplexerTransform was previously used to make it possible to target an output by multiple callbacks, but as @@ -1069,8 +1208,8 @@ def _output_id_without_wildcards(output: Output) -> str: # region SerializationTransform -class SerializationTransform(DashTransform): +class SerializationTransform(DashTransform): def apply_serverside(self, callbacks): for callback in callbacks: f = callback.f @@ -1083,7 +1222,7 @@ def _try_load(self, data: Any, ann=None): def _try_dump(self, obj: Any): raise NotImplementedError - def _unpack_pack_callback(self, callback): + def _unpack_pack_callback(self, callback): # noqa: C901 full_arg_spec = inspect.getfullargspec(callback.f) def unpack_pack_args(f): @@ -1119,12 +1258,13 @@ def decorated_function(*args, **kwargs): def sort_key(self): return 0 + # endregion # region DataclassTransform -class DataclassTransform(SerializationTransform): +class DataclassTransform(SerializationTransform): def _try_load(self, data: Any, ann=None) -> Any: if not dataclasses.is_dataclass(ann): return data @@ -1136,6 +1276,24 @@ def _try_dump(self, obj: Any) -> Any: return asdict(obj) +# endregion + + +# region PydanticTransform + + +class BaseModelTransform(SerializationTransform): + def _try_load(self, data: Any, ann=None) -> Any: + if not isinstance(ann, type(BaseModel)): + return data + return ann.model_validate_json(data) + + def _try_dump(self, obj: Any) -> Any: + if not isinstance(obj, BaseModel): + return obj + return obj.model_dump_json() + + # endregion # region Server side output transform @@ -1211,8 +1369,15 @@ class EnrichedOutput(Output): Like a normal Output, includes additional properties related to storing the data. """ - def __init__(self, component_id, component_property, allow_duplicate=False, backend=None, session_check=None, - arg_check=True): + def __init__( + self, + component_id, + component_property, + allow_duplicate=False, + backend=None, + session_check=None, + arg_check=True, + ): super().__init__(component_id, component_property, allow_duplicate) self.backend = backend self.session_check = session_check @@ -1222,9 +1387,11 @@ def __init__(self, component_id, component_property, allow_duplicate=False, back class ServersideOutputTransform(SerializationTransform): prefix: str = "SERVERSIDE_" - def __init__(self, - backends: Optional[List[ServersideBackend]] = None, - default_backend: Optional[ServersideBackend] = None): + def __init__( + self, + backends: Optional[List[ServersideBackend]] = None, + default_backend: Optional[ServersideBackend] = None, + ): super().__init__() # Per default, use file system backend. if backends is None: @@ -1238,7 +1405,7 @@ def _try_load(self, data: Any, ann=None) -> Any: return data if not data.startswith(self.prefix): return data - obj = json.loads(data[len(self.prefix):]) + obj = json.loads(data[len(self.prefix) :]) backend = self._backend_registry[obj["backend_uid"]] value = backend.get(obj["key"], ignore_expired=True) return value @@ -1259,8 +1426,12 @@ def _try_dump(self, obj: Any) -> Any: class Serverside(Generic[T]): - - def __init__(self, value: T, key: str = None, backend: Union[ServersideBackend, str, None] = None): + def __init__( + self, + value: T, + key: str = None, + backend: Union[ServersideBackend, str, None] = None, + ): self.value = value self.key: str = str(uuid.uuid4()) if key is None else key self.backend_uid: str = backend.uid if isinstance(backend, ServersideBackend) else backend @@ -1321,6 +1492,7 @@ def __init__(self, *args, **kwargs): # region Utils + def _as_list(item): if item is None: return [] @@ -1378,4 +1550,5 @@ def _check_multi(item): def plotly_jsonify(data): return json.loads(json.dumps(data, cls=plotly.utils.PlotlyJSONEncoder)) + # endregion diff --git a/dash_extensions/javascript.py b/dash_extensions/javascript.py index 4c3c648..01eea8d 100644 --- a/dash_extensions/javascript.py +++ b/dash_extensions/javascript.py @@ -1,4 +1,5 @@ import os + import jsbeautifier # region Templates @@ -6,7 +7,7 @@ _template = """window.{namespace} = Object.assign({{}}, window.{namespace}, {{ {content} }});""" -_ns_template = """{namespace}: {{ +_ns_template = """{namespace}: {{ {content} }}""" _func_template = """{name}: {function}""" diff --git a/dash_extensions/pages.py b/dash_extensions/pages.py index 6407054..78ad575 100644 --- a/dash_extensions/pages.py +++ b/dash_extensions/pages.py @@ -1,8 +1,9 @@ import json -import dash from collections import OrderedDict -from typing import Optional, Any -from dash import html, Input, Output, State, clientside_callback, page_container +from typing import Any, Optional + +import dash +from dash import Input, Output, State, clientside_callback, html, page_container from dash.development.base_component import Component """ @@ -23,17 +24,17 @@ def _register_page(*args, page_components=None, page_properties=None, **kwargs): _original_register_page(*args, **kwargs) # Resolve page. - module = kwargs['module'] if 'module' in kwargs else args[0] + module = kwargs["module"] if "module" in kwargs else args[0] page = dash.page_registry[module] # Register callbacks for page props. if page_properties is not None: for component in page_properties: - _set_props(component, page['path'], page_properties[component]) + _set_props(component, page["path"], page_properties[component]) # Resolve any page components. if page_components is None: return for component in page_components: - _set_visible(component, page['path']) + _set_visible(component, page["path"]) dash.register_page = _register_page @@ -43,6 +44,7 @@ def _register_page(*args, page_components=None, page_properties=None, **kwargs): # region Public interface + def set_page_container_style_display_contents(): """ Changes the style of the page container (and the page content container) so that their children are rendered @@ -62,6 +64,7 @@ def set_default_container(container: Component): :param container: the container into which page components will be rendered by default :return: None """ + global _COMPONENT_CONTAINER _COMPONENT_CONTAINER = container @@ -114,6 +117,7 @@ def setup_page_components() -> html.Div: # region Utils + def _prepare_container(container: Optional[Component] = None): container = _COMPONENT_CONTAINER if container is None else container # Make sure children is a list. @@ -132,7 +136,12 @@ def _setup_callbacks(): for component in components: # Wrap in div container, so we can hide it. cid = component._set_random_id() - wrapper = html.Div(component, disable_n_clicks=True, style=dict(display="none"), id=f"{cid}_wrapper") + wrapper = html.Div( + component, + disable_n_clicks=True, + style=dict(display="none"), + id=f"{cid}_wrapper", + ) # Add to container. container = _prepare_container(_CONTAINER_REGISTRY.get(component, _COMPONENT_CONTAINER)) container.children.append(wrapper) @@ -144,10 +153,13 @@ def _setup_callbacks(): }} return {{display: "none"}}; }}""" - clientside_callback(f, Output(wrapper, "style", allow_duplicate=True), - Input(store, "data"), - State(location, "pathname"), - prevent_initial_call='initial_duplicate') + clientside_callback( + f, + Output(wrapper, "style", allow_duplicate=True), + Input(store, "data"), + State(location, "pathname"), + prevent_initial_call="initial_duplicate", + ) # Setup callbacks for page props. components = list(_PROP_PATH_REGISTRY.keys()) for component in components: @@ -156,15 +168,19 @@ def _setup_callbacks(): default = getattr(component, prop, None) # Setup callback. f = f"""function(y, x){{ - const path_map = JSON.parse(\'{json.dumps(path_map)}\'); + const path_map = JSON.parse(\'{json.dumps(path_map)}\'); if (x in path_map){{ return path_map[x]; }} - return JSON.parse(\'{json.dumps(default)}\'); + return JSON.parse(\'{json.dumps(default)}\'); }}""" - clientside_callback(f, Output(component, prop, allow_duplicate=True), - Input(store, "data"), - State(location, "pathname"), - prevent_initial_call='initial_duplicate') + clientside_callback( + f, + Output(component, prop, allow_duplicate=True), + Input(store, "data"), + State(location, "pathname"), + prevent_initial_call="initial_duplicate", + ) + # endregion diff --git a/dash_extensions/snippets.py b/dash_extensions/snippets.py index 1519b8f..c2d42b1 100644 --- a/dash_extensions/snippets.py +++ b/dash_extensions/snippets.py @@ -1,9 +1,8 @@ import json - -from dash import html, Output, Input, callback_context -from dash.development.base_component import Component from typing import List, Union +from dash import Input, Output, callback_context, html +from dash.development.base_component import Component # region Get triggered @@ -15,7 +14,7 @@ def __init__(self, id, **kwargs): setattr(self, key, kwargs[key]) -def get_triggered() -> Triggered: +def get_triggered() -> Triggered: # noqa: C901 triggered = callback_context.triggered if not triggered: return Triggered(None) @@ -96,9 +95,7 @@ def fix_page_load_anchor_issue(app, delay, input_id=None, output_id=None): match.scrollIntoView(); }}, {}); }} - """.format( - delay - ), + """.format(delay), Output(output_id, "children"), [Input(input_id, "children")], prevent_initial_call=False, diff --git a/dash_extensions/streaming.py b/dash_extensions/streaming.py new file mode 100644 index 0000000..ecd19ee --- /dev/null +++ b/dash_extensions/streaming.py @@ -0,0 +1,25 @@ +from typing import Union + +from pydantic import BaseModel + + +def sse_message(data: str = "[DONE]") -> str: + """ + Given a string, formats it as an SSE event. + """ + return f"data: {data}\n\n" + + +def sse_options(payload: Union[str, BaseModel], **kwargs): + """ + Given a string or Pydantic base model, returns a dictionary that can be used as options for StreamingBuffer. + """ + options = {"payload": payload} + # For Pydantic models, convert to JSON and set the content type. + if isinstance(payload, BaseModel): + options = { + "payload": payload.model_dump_json(), + "headers": {"Content-Type": "application/json"}, + } + # Merge with additional options. + return {**options, **kwargs} diff --git a/dash_extensions/validate.py b/dash_extensions/validate.py index df5cc5b..2a6fa6f 100644 --- a/dash_extensions/validate.py +++ b/dash_extensions/validate.py @@ -24,6 +24,8 @@ def assert_no_random_ids(): if _components_with_random_ids: return raise AssertionError( - f"The following components have random ids: {', '.join([str(c) for c in _components_with_random_ids])}") + f"The following components have random ids: {', '.join([str(c) for c in _components_with_random_ids])}" + ) + # endregion diff --git a/lgtm.yml b/lgtm.yml index 86992bf..c0f2ac1 100644 --- a/lgtm.yml +++ b/lgtm.yml @@ -2,4 +2,4 @@ path_classifiers: docs: - examples/* queries: - - exclude: py/procedure-return-value-used \ No newline at end of file + - exclude: py/procedure-return-value-used diff --git a/package-lock.json b/package-lock.json index 42dce3c..019042f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-extensions", - "version": "1.0.14", + "version": "1.0.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dash-extensions", - "version": "1.0.5", + "version": "1.0.16rc5", "license": "MIT", "dependencies": { "@img-comparison-slider/react": "^7.7.0", @@ -20,6 +20,7 @@ "ramda": "^0.26.1", "react-loadable": "^5.5.0", "react-lottie": "^1.2.3", + "sse.js": "^2.4.1", "ssri": "^9.0.0" }, "devDependencies": { @@ -119,9 +120,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -200,9 +201,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -265,9 +266,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1663,9 +1664,9 @@ } }, "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -2450,7 +2451,7 @@ "node_modules/babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==", "dev": true, "dependencies": { "babel-helper-get-function-arity": "^6.24.1", @@ -2536,9 +2537,9 @@ } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -2578,7 +2579,7 @@ "node_modules/babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "integrity": "sha512-n4jtBA3OYBdvG5PRMKsMXJXHfLYw/ZOmtxCLOOwz6Ro5XlrColkStLnz1AS1L2yfPA9BKJ1ZNlmVCLjAL9DSIg==", "dev": true, "dependencies": { "babel-helper-function-name": "^6.24.1", @@ -2604,7 +2605,7 @@ "node_modules/babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", "dev": true, "dependencies": { "babel-runtime": "^6.26.0", @@ -2617,7 +2618,7 @@ "node_modules/babel-traverse": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", "dev": true, "dependencies": { "babel-code-frame": "^6.26.0", @@ -2850,9 +2851,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", - "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -2861,14 +2862,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -3048,9 +3052,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001335", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", - "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==", + "version": "1.0.30001624", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001624.tgz", + "integrity": "sha512-0dWnQG87UevOCPYaOR49CBcLBwoZLpws+k6W37nLjWUhumP1Isusj0p2u+3KhjNloRWK9OKMgjBBzPujQHw4nA==", "funding": [ { "type": "opencollective", @@ -3059,6 +3063,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -3294,28 +3302,18 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.3.tgz", - "integrity": "sha512-wliMbvPI2idgFWpFe7UEyHMvu6HWgW8WA+HnDRtgzoSDYvXFMpoGX1H3tPDDXrcfUSyXafCLDd7hOeMQHEZxGw==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, "dependencies": { - "browserslist": "^4.20.3", - "semver": "7.0.0" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -3459,13 +3457,10 @@ } }, "node_modules/css-loader/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -3983,9 +3978,9 @@ "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.129", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.129.tgz", - "integrity": "sha512-GgtN6bsDtHdtXJtlMYZWGB/uOyjZWjmRDumXTas7dGBaB9zUyCjzHet1DY2KhyHN8R0GLbzZWqm4efeddqqyRQ==" + "version": "1.4.783", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", + "integrity": "sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -4161,9 +4156,9 @@ "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -4404,9 +4399,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4462,9 +4457,9 @@ } }, "node_modules/eslint/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -5897,18 +5892,6 @@ "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.7.12.tgz", "integrity": "sha512-aW1gdxDzcwXmlYnYJ4SdtH0ujmHzNnAXf+noyE0otUTCLtwMIkOL/CCXmjNj+pZmEeu9GrrHDOt/pTPWOCzBRQ==" }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -5925,9 +5908,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -6226,9 +6209,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", - "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/noms": { "version": "0.0.0", @@ -6246,15 +6229,17 @@ "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" }, "node_modules/npm": { - "version": "9.6.6", - "resolved": "https://registry.npmjs.org/npm/-/npm-9.6.6.tgz", - "integrity": "sha512-GIe+nCIw8EJIv52IXDVETSGnx7p9Ttg4VsaXNIeT4eaKZpIZ635rKC/uzQ6nnc4ibCUmESoK3PrXG0/puoqNcg==", + "version": "9.9.3", + "resolved": "https://registry.npmjs.org/npm/-/npm-9.9.3.tgz", + "integrity": "sha512-Z1l+rcQ5kYb17F3hHtO601arEpvdRYnCLtg8xo3AGtyj3IthwaraEOexI9903uANkifFbqHC8hT53KIrozWg8A==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", "@npmcli/config", + "@npmcli/fs", "@npmcli/map-workspaces", "@npmcli/package-json", + "@npmcli/promise-spawn", "@npmcli/run-script", "abbrev", "archy", @@ -6291,6 +6276,7 @@ "ms", "node-gyp", "nopt", + "normalize-package-data", "npm-audit-report", "npm-install-checks", "npm-package-arg", @@ -6305,10 +6291,11 @@ "proc-log", "qrcode-terminal", "read", - "read-package-json", - "read-package-json-fast", "semver", + "sigstore", + "spdx-expression-parse", "ssri", + "supports-color", "tar", "text-table", "tiny-relative-date", @@ -6320,65 +6307,69 @@ "dev": true, "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^6.2.9", - "@npmcli/config": "^6.1.6", + "@npmcli/arborist": "^6.5.0", + "@npmcli/config": "^6.4.0", + "@npmcli/fs": "^3.1.0", "@npmcli/map-workspaces": "^3.0.4", - "@npmcli/package-json": "^3.0.0", - "@npmcli/run-script": "^6.0.1", + "@npmcli/package-json": "^4.0.1", + "@npmcli/promise-spawn": "^6.0.2", + "@npmcli/run-script": "^6.0.2", "abbrev": "^2.0.0", "archy": "~1.0.0", - "cacache": "^17.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.8.0", + "cacache": "^17.1.4", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", "cli-columns": "^4.0.0", "cli-table3": "^0.6.3", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.2", - "glob": "^10.2.2", + "fs-minipass": "^3.0.3", + "glob": "^10.3.10", "graceful-fs": "^4.2.11", "hosted-git-info": "^6.1.1", - "ini": "^4.1.0", + "ini": "^4.1.1", "init-package-json": "^5.0.0", "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^3.0.0", + "json-parse-even-better-errors": "^3.0.1", "libnpmaccess": "^7.0.2", - "libnpmdiff": "^5.0.17", - "libnpmexec": "^5.0.17", - "libnpmfund": "^4.0.17", + "libnpmdiff": "^5.0.20", + "libnpmexec": "^6.0.4", + "libnpmfund": "^4.2.1", "libnpmhook": "^9.0.3", "libnpmorg": "^5.0.4", - "libnpmpack": "^5.0.17", - "libnpmpublish": "^7.1.4", + "libnpmpack": "^5.0.20", + "libnpmpublish": "^7.5.1", "libnpmsearch": "^6.0.2", "libnpmteam": "^5.0.3", "libnpmversion": "^4.0.2", "make-fetch-happen": "^11.1.1", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", + "minimatch": "^9.0.3", + "minipass": "^7.0.4", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^9.3.1", - "nopt": "^7.1.0", - "npm-audit-report": "^4.0.0", - "npm-install-checks": "^6.1.1", + "node-gyp": "^9.4.1", + "nopt": "^7.2.0", + "normalize-package-data": "^5.0.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", "npm-package-arg": "^10.1.0", - "npm-pick-manifest": "^8.0.1", + "npm-pick-manifest": "^8.0.2", "npm-profile": "^7.0.1", "npm-registry-fetch": "^14.0.5", "npm-user-validate": "^2.0.0", "npmlog": "^7.0.1", "p-map": "^4.0.0", - "pacote": "^15.1.3", + "pacote": "^15.2.0", "parse-conflict-json": "^3.0.1", "proc-log": "^3.0.0", "qrcode-terminal": "^0.12.0", "read": "^2.1.0", - "read-package-json": "^6.0.3", - "read-package-json-fast": "^3.0.2", - "semver": "^7.5.0", - "ssri": "^10.0.4", - "tar": "^6.1.14", + "semver": "^7.6.0", + "sigstore": "^1.9.0", + "spdx-expression-parse": "^3.0.1", + "ssri": "^10.0.5", + "supports-color": "^9.4.0", + "tar": "^6.2.0", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "treeverse": "^3.0.0", @@ -6463,7 +6454,7 @@ } }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.0.1", + "version": "7.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -6484,7 +6475,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "6.2.9", + "version": "6.5.1", "dev": true, "inBundle": true, "license": "ISC", @@ -6496,8 +6487,8 @@ "@npmcli/metavuln-calculator": "^5.0.0", "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^3.0.0", - "@npmcli/query": "^3.0.0", + "@npmcli/package-json": "^4.0.0", + "@npmcli/query": "^3.1.0", "@npmcli/run-script": "^6.0.0", "bin-links": "^4.0.1", "cacache": "^17.0.4", @@ -6507,7 +6498,7 @@ "json-stringify-nice": "^1.1.4", "minimatch": "^9.0.0", "nopt": "^7.0.0", - "npm-install-checks": "^6.0.0", + "npm-install-checks": "^6.2.0", "npm-package-arg": "^10.1.0", "npm-pick-manifest": "^8.0.1", "npm-registry-fetch": "^14.0.3", @@ -6531,12 +6522,13 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "6.1.6", + "version": "6.4.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", "ini": "^4.1.0", "nopt": "^7.0.0", "proc-log": "^3.0.0", @@ -6573,7 +6565,7 @@ } }, "node_modules/npm/node_modules/@npmcli/git": { - "version": "4.0.4", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -6669,12 +6661,18 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "3.0.0", + "version": "4.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "json-parse-even-better-errors": "^3.0.0" + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -6693,7 +6691,7 @@ } }, "node_modules/npm/node_modules/@npmcli/query": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -6705,7 +6703,7 @@ } }, "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -6730,11 +6728,50 @@ "node": ">=14" } }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.1.0", + "version": "0.2.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "1.0.0", "dev": true, "inBundle": true, "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -6779,18 +6816,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/abort-controller": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/npm/node_modules/agent-base": { "version": "6.0.2", "dev": true, @@ -6804,13 +6829,11 @@ } }, "node_modules/npm/node_modules/agentkeepalive": { - "version": "4.3.0", + "version": "4.5.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { @@ -6867,14 +6890,10 @@ "license": "MIT" }, "node_modules/npm/node_modules/are-we-there-yet": { - "version": "4.0.0", + "version": "4.0.2", "dev": true, "inBundle": true, "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^4.1.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -6885,28 +6904,8 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/base64-js": { - "version": "1.5.1", - "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" - } - ], - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/bin-links": { - "version": "4.0.1", + "version": "4.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -6938,30 +6937,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/npm/node_modules/buffer": { - "version": "6.0.3", - "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" - } - ], - "inBundle": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/npm/node_modules/builtins": { "version": "5.0.1", "dev": true, @@ -6972,7 +6947,7 @@ } }, "node_modules/npm/node_modules/cacache": { - "version": "17.1.0", + "version": "17.1.4", "dev": true, "inBundle": true, "license": "ISC", @@ -6981,7 +6956,7 @@ "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^7.7.1", - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", @@ -6995,16 +6970,12 @@ } }, "node_modules/npm/node_modules/chalk": { - "version": "4.1.2", + "version": "5.3.0", "dev": true, "inBundle": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -7020,7 +6991,7 @@ } }, "node_modules/npm/node_modules/ci-info": { - "version": "3.8.0", + "version": "4.0.0", "dev": true, "funding": [ { @@ -7093,7 +7064,7 @@ } }, "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -7241,17 +7212,8 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/depd": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/npm/node_modules/diff": { - "version": "5.1.0", + "version": "5.2.0", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -7296,23 +7258,11 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/event-target-shim": { - "version": "5.0.1", + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", "dev": true, "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/events": { - "version": "3.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } + "license": "Apache-2.0" }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -7340,12 +7290,12 @@ } }, "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.2", + "version": "3.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -7358,10 +7308,13 @@ "license": "ISC" }, "node_modules/npm/node_modules/function-bind": { - "version": "1.1.1", + "version": "1.1.2", "dev": true, "inBundle": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/npm/node_modules/gauge": { "version": "5.0.1", @@ -7383,19 +7336,19 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "10.2.2", + "version": "10.3.10", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.7.0" + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -7410,33 +7363,24 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/has": { - "version": "1.0.3", + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", "dev": true, "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } + "license": "ISC" }, - "node_modules/npm/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/npm/node_modules/hasown": { + "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/npm/node_modules/has-unicode": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, "node_modules/npm/node_modules/hosted-git-info": { "version": "6.1.1", "dev": true, @@ -7504,28 +7448,8 @@ "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/ieee754": { - "version": "1.2.1", - "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" - } - ], - "inBundle": true, - "license": "BSD-3-Clause" - }, "node_modules/npm/node_modules/ignore-walk": { - "version": "6.0.3", + "version": "6.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -7577,7 +7501,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/ini": { - "version": "4.1.0", + "version": "4.1.1", "dev": true, "inBundle": true, "license": "ISC", @@ -7603,11 +7527,24 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/ip": { - "version": "2.0.0", + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", "dev": true, "inBundle": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause" }, "node_modules/npm/node_modules/ip-regex": { "version": "4.3.0", @@ -7631,12 +7568,12 @@ } }, "node_modules/npm/node_modules/is-core-module": { - "version": "2.12.0", + "version": "2.13.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7664,7 +7601,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/jackspeak": { - "version": "2.2.0", + "version": "2.3.6", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -7681,8 +7618,14 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", + "version": "3.0.1", "dev": true, "inBundle": true, "license": "MIT", @@ -7721,7 +7664,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "7.0.2", + "version": "7.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -7734,12 +7677,12 @@ } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "5.0.17", + "version": "5.0.21", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^6.2.9", + "@npmcli/arborist": "^6.5.0", "@npmcli/disparity-colors": "^3.0.0", "@npmcli/installed-package-contents": "^2.0.2", "binary-extensions": "^2.2.0", @@ -7754,15 +7697,14 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "5.0.17", + "version": "6.0.5", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^6.2.9", + "@npmcli/arborist": "^6.5.0", "@npmcli/run-script": "^6.0.0", - "chalk": "^4.1.0", - "ci-info": "^3.7.1", + "ci-info": "^4.0.0", "npm-package-arg": "^10.1.0", "npmlog": "^7.0.1", "pacote": "^15.0.8", @@ -7777,19 +7719,19 @@ } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "4.0.17", + "version": "4.2.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^6.2.9" + "@npmcli/arborist": "^6.5.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmhook": { - "version": "9.0.3", + "version": "9.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -7802,7 +7744,7 @@ } }, "node_modules/npm/node_modules/libnpmorg": { - "version": "5.0.4", + "version": "5.0.5", "dev": true, "inBundle": true, "license": "ISC", @@ -7815,12 +7757,12 @@ } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "5.0.17", + "version": "5.0.21", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^6.2.9", + "@npmcli/arborist": "^6.5.0", "@npmcli/run-script": "^6.0.0", "npm-package-arg": "^10.1.0", "pacote": "^15.0.8" @@ -7830,12 +7772,12 @@ } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "7.1.4", + "version": "7.5.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "ci-info": "^3.6.1", + "ci-info": "^4.0.0", "normalize-package-data": "^5.0.0", "npm-package-arg": "^10.1.0", "npm-registry-fetch": "^14.0.3", @@ -7849,7 +7791,7 @@ } }, "node_modules/npm/node_modules/libnpmsearch": { - "version": "6.0.2", + "version": "6.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -7861,7 +7803,7 @@ } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "5.0.3", + "version": "5.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -7874,7 +7816,7 @@ } }, "node_modules/npm/node_modules/libnpmversion": { - "version": "4.0.2", + "version": "4.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -7924,8 +7866,17 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/minimatch": { - "version": "9.0.0", + "version": "9.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -7940,12 +7891,12 @@ } }, "node_modules/npm/node_modules/minipass": { - "version": "5.0.0", + "version": "7.0.4", "dev": true, "inBundle": true, "license": "ISC", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/npm/node_modules/minipass-collect": { @@ -7973,12 +7924,12 @@ } }, "node_modules/npm/node_modules/minipass-fetch": { - "version": "3.0.3", + "version": "3.0.4", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, @@ -8145,12 +8096,13 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "9.3.1", + "version": "9.4.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", @@ -8428,20 +8380,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { "version": "3.0.7", "dev": true, @@ -8500,7 +8438,7 @@ } }, "node_modules/npm/node_modules/nopt": { - "version": "7.1.0", + "version": "7.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -8530,13 +8468,10 @@ } }, "node_modules/npm/node_modules/npm-audit-report": { - "version": "4.0.0", + "version": "5.0.0", "dev": true, "inBundle": true, "license": "ISC", - "dependencies": { - "chalk": "^4.0.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -8554,7 +8489,7 @@ } }, "node_modules/npm/node_modules/npm-install-checks": { - "version": "6.1.1", + "version": "6.3.0", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -8602,7 +8537,7 @@ } }, "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "8.0.1", + "version": "8.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -8647,6 +8582,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/npm-user-validate": { "version": "2.0.0", "dev": true, @@ -8696,7 +8640,7 @@ } }, "node_modules/npm/node_modules/pacote": { - "version": "15.1.3", + "version": "15.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -8727,6 +8671,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/pacote/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/parse-conflict-json": { "version": "3.0.1", "dev": true, @@ -8760,13 +8713,13 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "1.7.0", + "version": "1.10.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -8776,7 +8729,7 @@ } }, "node_modules/npm/node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.1", + "version": "10.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -8785,7 +8738,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.0.12", + "version": "6.0.15", "dev": true, "inBundle": true, "license": "MIT", @@ -8806,15 +8759,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/process": { - "version": "0.11.10", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", "dev": true, @@ -8894,7 +8838,7 @@ } }, "node_modules/npm/node_modules/read-package-json": { - "version": "6.0.3", + "version": "6.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -8922,18 +8866,17 @@ } }, "node_modules/npm/node_modules/readable-stream": { - "version": "4.3.0", + "version": "3.6.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 6" } }, "node_modules/npm/node_modules/retry": { @@ -9003,8 +8946,22 @@ } }, "node_modules/npm/node_modules/safe-buffer": { - "version": "5.1.2", + "version": "5.2.1", "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" + } + ], "inBundle": true, "license": "MIT" }, @@ -9016,7 +8973,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.5.0", + "version": "7.6.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9070,7 +9027,7 @@ } }, "node_modules/npm/node_modules/signal-exit": { - "version": "4.0.1", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9082,14 +9039,16 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "1.4.0", + "version": "1.9.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.1.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" }, "bin": { "sigstore": "bin/sigstore.js" @@ -9109,16 +9068,16 @@ } }, "node_modules/npm/node_modules/socks": { - "version": "2.7.1", + "version": "2.8.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -9147,7 +9106,7 @@ } }, "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.3.0", + "version": "2.5.0", "dev": true, "inBundle": true, "license": "CC-BY-3.0" @@ -9163,30 +9122,30 @@ } }, "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.13", + "version": "3.0.17", "dev": true, "inBundle": true, "license": "CC0-1.0" }, "node_modules/npm/node_modules/ssri": { - "version": "10.0.4", + "version": "10.0.5", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm/node_modules/string_decoder": { - "version": "1.1.1", + "version": "1.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "node_modules/npm/node_modules/string-width": { @@ -9244,19 +9203,19 @@ } }, "node_modules/npm/node_modules/supports-color": { - "version": "7.2.0", + "version": "9.4.0", "dev": true, "inBundle": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/npm/node_modules/tar": { - "version": "6.1.14", + "version": "6.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9296,6 +9255,15 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -9318,13 +9286,14 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "1.1.5", + "version": "1.1.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@tufjs/models": "1.0.4", - "make-fetch-happen": "^11.1.0" + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -9504,7 +9473,7 @@ } }, "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.0.1", + "version": "7.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -9828,9 +9797,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/pkg-dir": { "version": "4.2.0", @@ -10497,9 +10466,9 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -10628,6 +10597,11 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/sse.js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/sse.js/-/sse.js-2.4.1.tgz", + "integrity": "sha512-0qXPFZCClp+RPWtldNTYUjDWDlStZq1nyRF7at8WDFotHEyCivEBlR7Z5ftcJnt9KpouRg+NdzGFvPTB2gHl8Q==" + }, "node_modules/ssri": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.0.tgz", @@ -11242,6 +11216,35 @@ "node": ">=8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -11619,9 +11622,9 @@ "dev": true }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -11857,4 +11860,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index fc4a2bf..0281f71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-extensions", - "version": "1.0.15", + "version": "1.0.16", "description": "Extensions for Plotly Dash.", "main": "build/index.js", "scripts": { @@ -29,6 +29,7 @@ "ramda": "^0.26.1", "react-loadable": "^5.5.0", "react-lottie": "^1.2.3", + "sse.js": "^2.4.1", "ssri": "^9.0.0" }, "devDependencies": { @@ -61,4 +62,4 @@ "node": ">=8.11.0", "npm": ">=6.1.0" } -} +} \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 0119b18..905ace9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,18 +13,15 @@ files = [ [[package]] name = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "anyio" version = "4.3.0" @@ -87,61 +84,15 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] -[[package]] -name = "black" -version = "24.4.2" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, - {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, - {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, - {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, - {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, - {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, - {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, - {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, - {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, - {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, - {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, - {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, - {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, - {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, - {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, - {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, - {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, - {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, - {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, - {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, - {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, - {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "blinker" -version = "1.8.1" +version = "1.8.2" description = "Fast, simple object-to-object and broadcast signaling" optional = false python-versions = ">=3.8" files = [ - {file = "blinker-1.8.1-py3-none-any.whl", hash = "sha256:5f1cdeff423b77c31b89de0565cd03e5275a03028f44b2b15f912632a58cced6"}, - {file = "blinker-1.8.1.tar.gz", hash = "sha256:da44ec748222dcd0105ef975eed946da197d5bdf8bafb6aa92f5bc89da63fa25"}, + {file = "blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01"}, + {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, ] [[package]] @@ -230,6 +181,17 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -373,63 +335,63 @@ cron = ["capturer (>=2.4)"] [[package]] name = "coverage" -version = "7.5.0" +version = "7.5.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, - {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, - {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, - {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, - {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, - {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, - {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, - {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, - {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, - {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, - {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, - {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, - {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, - {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, + {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, + {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, + {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, + {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, + {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, + {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, + {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, + {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, + {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, + {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, + {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, + {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, ] [package.dependencies] @@ -440,43 +402,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.5" +version = "42.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"}, - {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"}, - {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"}, - {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"}, - {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"}, - {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"}, - {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"}, - {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"}, - {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"}, - {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"}, - {file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"}, - {file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"}, - {file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"}, - {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"}, - {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"}, - {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"}, - {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"}, - {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"}, - {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"}, - {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"}, - {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"}, - {file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"}, - {file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"}, - {file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"}, - {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"}, - {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"}, - {file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"}, - {file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"}, - {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"}, - {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"}, - {file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"}, - {file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, + {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, + {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, + {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, + {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, + {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, + {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, ] [package.dependencies] @@ -629,6 +591,17 @@ files = [ graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + [[package]] name = "editorconfig" version = "0.12.4" @@ -672,6 +645,22 @@ typing-extensions = ">=4.8.0" [package.extras] all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +[[package]] +name = "filelock" +version = "3.14.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + [[package]] name = "fire" version = "0.6.0" @@ -711,13 +700,13 @@ dotenv = ["python-dotenv"] [[package]] name = "flask-caching" -version = "2.2.0" +version = "2.3.0" description = "Adds caching support to Flask applications." optional = false python-versions = ">=3.8" files = [ - {file = "Flask_Caching-2.2.0-py3-none-any.whl", hash = "sha256:5b74ad9e263cc3c5ac9c2d33c094eb99294b111ace78ccaa665d6b852b907e14"}, - {file = "flask_caching-2.2.0.tar.gz", hash = "sha256:9d2d30ee02250c47c3650fd6781b79e92d5964d91382a3697e5ebaf77ca0ea4f"}, + {file = "Flask_Caching-2.3.0-py3-none-any.whl", hash = "sha256:51771c75682e5abc1483b78b96d9131d7941dc669b073852edfa319dd4e29b6e"}, + {file = "flask_caching-2.3.0.tar.gz", hash = "sha256:d7e4ca64a33b49feb339fcdd17e6ba25f5e01168cf885e53790e885f83a4d2cf"}, ] [package.dependencies] @@ -811,6 +800,20 @@ files = [ {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, ] +[[package]] +name = "identify" +version = "2.5.36" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, + {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.7" @@ -896,165 +899,149 @@ six = ">=1.13.0" [[package]] name = "lxml" -version = "5.2.1" +version = "5.2.2" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" files = [ - {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1f7785f4f789fdb522729ae465adcaa099e2a3441519df750ebdccc481d961a1"}, - {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cc6ee342fb7fa2471bd9b6d6fdfc78925a697bf5c2bcd0a302e98b0d35bfad3"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794f04eec78f1d0e35d9e0c36cbbb22e42d370dda1609fb03bcd7aeb458c6377"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817d420c60a5183953c783b0547d9eb43b7b344a2c46f69513d5952a78cddf3"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2213afee476546a7f37c7a9b4ad4d74b1e112a6fafffc9185d6d21f043128c81"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b070bbe8d3f0f6147689bed981d19bbb33070225373338df755a46893528104a"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e02c5175f63effbd7c5e590399c118d5db6183bbfe8e0d118bdb5c2d1b48d937"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3dc773b2861b37b41a6136e0b72a1a44689a9c4c101e0cddb6b854016acc0aa8"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:d7520db34088c96cc0e0a3ad51a4fd5b401f279ee112aa2b7f8f976d8582606d"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:bcbf4af004f98793a95355980764b3d80d47117678118a44a80b721c9913436a"}, - {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2b44bec7adf3e9305ce6cbfa47a4395667e744097faed97abb4728748ba7d47"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1c5bb205e9212d0ebddf946bc07e73fa245c864a5f90f341d11ce7b0b854475d"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2c9d147f754b1b0e723e6afb7ba1566ecb162fe4ea657f53d2139bbf894d050a"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3545039fa4779be2df51d6395e91a810f57122290864918b172d5dc7ca5bb433"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a91481dbcddf1736c98a80b122afa0f7296eeb80b72344d7f45dc9f781551f56"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2ddfe41ddc81f29a4c44c8ce239eda5ade4e7fc305fb7311759dd6229a080052"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7baf9ffc238e4bf401299f50e971a45bfcc10a785522541a6e3179c83eabf0a"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31e9a882013c2f6bd2f2c974241bf4ba68c85eba943648ce88936d23209a2e01"}, - {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0a15438253b34e6362b2dc41475e7f80de76320f335e70c5528b7148cac253a1"}, - {file = "lxml-5.2.1-cp310-cp310-win32.whl", hash = "sha256:6992030d43b916407c9aa52e9673612ff39a575523c5f4cf72cdef75365709a5"}, - {file = "lxml-5.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:da052e7962ea2d5e5ef5bc0355d55007407087392cf465b7ad84ce5f3e25fe0f"}, - {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867"}, - {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f18a5a84e16886898e51ab4b1d43acb3083c39b14c8caeb3589aabff0ee0b270"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6f2c8372b98208ce609c9e1d707f6918cc118fea4e2c754c9f0812c04ca116d"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:394ed3924d7a01b5bd9a0d9d946136e1c2f7b3dc337196d99e61740ed4bc6fe1"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d077bc40a1fe984e1a9931e801e42959a1e6598edc8a3223b061d30fbd26bbc"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:764b521b75701f60683500d8621841bec41a65eb739b8466000c6fdbc256c240"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3a6b45da02336895da82b9d472cd274b22dc27a5cea1d4b793874eead23dd14f"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:5ea7b6766ac2dfe4bcac8b8595107665a18ef01f8c8343f00710b85096d1b53a"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:e196a4ff48310ba62e53a8e0f97ca2bca83cdd2fe2934d8b5cb0df0a841b193a"}, - {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dae0ed02f6b075426accbf6b2863c3d0a7eacc1b41fb40f2251d931e50188dad"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:ab31a88a651039a07a3ae327d68ebdd8bc589b16938c09ef3f32a4b809dc96ef"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:df2e6f546c4df14bc81f9498bbc007fbb87669f1bb707c6138878c46b06f6510"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5dd1537e7cc06efd81371f5d1a992bd5ab156b2b4f88834ca852de4a8ea523fa"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9b9ec9c9978b708d488bec36b9e4c94d88fd12ccac3e62134a9d17ddba910ea9"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8e77c69d5892cb5ba71703c4057091e31ccf534bd7f129307a4d084d90d014b8"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a8d5c70e04aac1eda5c829a26d1f75c6e5286c74743133d9f742cda8e53b9c2f"}, - {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c94e75445b00319c1fad60f3c98b09cd63fe1134a8a953dcd48989ef42318534"}, - {file = "lxml-5.2.1-cp311-cp311-win32.whl", hash = "sha256:4951e4f7a5680a2db62f7f4ab2f84617674d36d2d76a729b9a8be4b59b3659be"}, - {file = "lxml-5.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102"}, - {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:abc25c3cab9ec7fcd299b9bcb3b8d4a1231877e425c650fa1c7576c5107ab851"}, - {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6935bbf153f9a965f1e07c2649c0849d29832487c52bb4a5c5066031d8b44fd5"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d793bebb202a6000390a5390078e945bbb49855c29c7e4d56a85901326c3b5d9"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd5562927cdef7c4f5550374acbc117fd4ecc05b5007bdfa57cc5355864e0a4"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e7259016bc4345a31af861fdce942b77c99049d6c2107ca07dc2bba2435c1d9"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:530e7c04f72002d2f334d5257c8a51bf409db0316feee7c87e4385043be136af"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59689a75ba8d7ffca577aefd017d08d659d86ad4585ccc73e43edbfc7476781a"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f9737bf36262046213a28e789cc82d82c6ef19c85a0cf05e75c670a33342ac2c"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:3a74c4f27167cb95c1d4af1c0b59e88b7f3e0182138db2501c353555f7ec57f4"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:68a2610dbe138fa8c5826b3f6d98a7cfc29707b850ddcc3e21910a6fe51f6ca0"}, - {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f0a1bc63a465b6d72569a9bba9f2ef0334c4e03958e043da1920299100bc7c08"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c2d35a1d047efd68027817b32ab1586c1169e60ca02c65d428ae815b593e65d4"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:79bd05260359170f78b181b59ce871673ed01ba048deef4bf49a36ab3e72e80b"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:865bad62df277c04beed9478fe665b9ef63eb28fe026d5dedcb89b537d2e2ea6"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:44f6c7caff88d988db017b9b0e4ab04934f11e3e72d478031efc7edcac6c622f"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:71e97313406ccf55d32cc98a533ee05c61e15d11b99215b237346171c179c0b0"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:057cdc6b86ab732cf361f8b4d8af87cf195a1f6dc5b0ff3de2dced242c2015e0"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f3bbbc998d42f8e561f347e798b85513ba4da324c2b3f9b7969e9c45b10f6169"}, - {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:491755202eb21a5e350dae00c6d9a17247769c64dcf62d8c788b5c135e179dc4"}, - {file = "lxml-5.2.1-cp312-cp312-win32.whl", hash = "sha256:8de8f9d6caa7f25b204fc861718815d41cbcf27ee8f028c89c882a0cf4ae4134"}, - {file = "lxml-5.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f2a9efc53d5b714b8df2b4b3e992accf8ce5bbdfe544d74d5c6766c9e1146a3a"}, - {file = "lxml-5.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:70a9768e1b9d79edca17890175ba915654ee1725975d69ab64813dd785a2bd5c"}, - {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38d7b9a690b090de999835f0443d8aa93ce5f2064035dfc48f27f02b4afc3d0"}, - {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5670fb70a828663cc37552a2a85bf2ac38475572b0e9b91283dc09efb52c41d1"}, - {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:958244ad566c3ffc385f47dddde4145088a0ab893504b54b52c041987a8c1863"}, - {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6241d4eee5f89453307c2f2bfa03b50362052ca0af1efecf9fef9a41a22bb4f"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2a66bf12fbd4666dd023b6f51223aed3d9f3b40fef06ce404cb75bafd3d89536"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:9123716666e25b7b71c4e1789ec829ed18663152008b58544d95b008ed9e21e9"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:0c3f67e2aeda739d1cc0b1102c9a9129f7dc83901226cc24dd72ba275ced4218"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d5792e9b3fb8d16a19f46aa8208987cfeafe082363ee2745ea8b643d9cc5b45"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:88e22fc0a6684337d25c994381ed8a1580a6f5ebebd5ad41f89f663ff4ec2885"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:21c2e6b09565ba5b45ae161b438e033a86ad1736b8c838c766146eff8ceffff9"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:afbbdb120d1e78d2ba8064a68058001b871154cc57787031b645c9142b937a62"}, - {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:627402ad8dea044dde2eccde4370560a2b750ef894c9578e1d4f8ffd54000461"}, - {file = "lxml-5.2.1-cp36-cp36m-win32.whl", hash = "sha256:e89580a581bf478d8dcb97d9cd011d567768e8bc4095f8557b21c4d4c5fea7d0"}, - {file = "lxml-5.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:59565f10607c244bc4c05c0c5fa0c190c990996e0c719d05deec7030c2aa8289"}, - {file = "lxml-5.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:857500f88b17a6479202ff5fe5f580fc3404922cd02ab3716197adf1ef628029"}, - {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56c22432809085b3f3ae04e6e7bdd36883d7258fcd90e53ba7b2e463efc7a6af"}, - {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a55ee573116ba208932e2d1a037cc4b10d2c1cb264ced2184d00b18ce585b2c0"}, - {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:6cf58416653c5901e12624e4013708b6e11142956e7f35e7a83f1ab02f3fe456"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:64c2baa7774bc22dd4474248ba16fe1a7f611c13ac6123408694d4cc93d66dbd"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:74b28c6334cca4dd704e8004cba1955af0b778cf449142e581e404bd211fb619"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7221d49259aa1e5a8f00d3d28b1e0b76031655ca74bb287123ef56c3db92f213"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3dbe858ee582cbb2c6294dc85f55b5f19c918c2597855e950f34b660f1a5ede6"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:04ab5415bf6c86e0518d57240a96c4d1fcfc3cb370bb2ac2a732b67f579e5a04"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:6ab833e4735a7e5533711a6ea2df26459b96f9eec36d23f74cafe03631647c41"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f443cdef978430887ed55112b491f670bba6462cea7a7742ff8f14b7abb98d75"}, - {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, - {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, - {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, - {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, - {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, - {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, - {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d30321949861404323c50aebeb1943461a67cd51d4200ab02babc58bd06a86"}, - {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:b560e3aa4b1d49e0e6c847d72665384db35b2f5d45f8e6a5c0072e0283430533"}, - {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:058a1308914f20784c9f4674036527e7c04f7be6fb60f5d61353545aa7fcb739"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:adfb84ca6b87e06bc6b146dc7da7623395db1e31621c4785ad0658c5028b37d7"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:417d14450f06d51f363e41cace6488519038f940676ce9664b34ebf5653433a5"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a2dfe7e2473f9b59496247aad6e23b405ddf2e12ef0765677b0081c02d6c2c0b"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bf2e2458345d9bffb0d9ec16557d8858c9c88d2d11fed53998512504cd9df49b"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:58278b29cb89f3e43ff3e0c756abbd1518f3ee6adad9e35b51fb101c1c1daaec"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:64641a6068a16201366476731301441ce93457eb8452056f570133a6ceb15fca"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:78bfa756eab503673991bdcf464917ef7845a964903d3302c5f68417ecdc948c"}, - {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:11a04306fcba10cd9637e669fd73aa274c1c09ca64af79c041aa820ea992b637"}, - {file = "lxml-5.2.1-cp38-cp38-win32.whl", hash = "sha256:66bc5eb8a323ed9894f8fa0ee6cb3e3fb2403d99aee635078fd19a8bc7a5a5da"}, - {file = "lxml-5.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:9676bfc686fa6a3fa10cd4ae6b76cae8be26eb5ec6811d2a325636c460da1806"}, - {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cf22b41fdae514ee2f1691b6c3cdeae666d8b7fa9434de445f12bbeee0cf48dd"}, - {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec42088248c596dbd61d4ae8a5b004f97a4d91a9fd286f632e42e60b706718d7"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd53553ddad4a9c2f1f022756ae64abe16da1feb497edf4d9f87f99ec7cf86bd"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feaa45c0eae424d3e90d78823f3828e7dc42a42f21ed420db98da2c4ecf0a2cb"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddc678fb4c7e30cf830a2b5a8d869538bc55b28d6c68544d09c7d0d8f17694dc"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:853e074d4931dbcba7480d4dcab23d5c56bd9607f92825ab80ee2bd916edea53"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4691d60512798304acb9207987e7b2b7c44627ea88b9d77489bbe3e6cc3bd4"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:beb72935a941965c52990f3a32d7f07ce869fe21c6af8b34bf6a277b33a345d3"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:6588c459c5627fefa30139be4d2e28a2c2a1d0d1c265aad2ba1935a7863a4913"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:588008b8497667f1ddca7c99f2f85ce8511f8f7871b4a06ceede68ab62dff64b"}, - {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6787b643356111dfd4032b5bffe26d2f8331556ecb79e15dacb9275da02866e"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7c17b64b0a6ef4e5affae6a3724010a7a66bda48a62cfe0674dabd46642e8b54"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:27aa20d45c2e0b8cd05da6d4759649170e8dfc4f4e5ef33a34d06f2d79075d57"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d4f2cc7060dc3646632d7f15fe68e2fa98f58e35dd5666cd525f3b35d3fed7f8"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff46d772d5f6f73564979cd77a4fffe55c916a05f3cb70e7c9c0590059fb29ef"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:96323338e6c14e958d775700ec8a88346014a85e5de73ac7967db0367582049b"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:52421b41ac99e9d91934e4d0d0fe7da9f02bfa7536bb4431b4c05c906c8c6919"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:7a7efd5b6d3e30d81ec68ab8a88252d7c7c6f13aaa875009fe3097eb4e30b84c"}, - {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ed777c1e8c99b63037b91f9d73a6aad20fd035d77ac84afcc205225f8f41188"}, - {file = "lxml-5.2.1-cp39-cp39-win32.whl", hash = "sha256:644df54d729ef810dcd0f7732e50e5ad1bd0a135278ed8d6bcb06f33b6b6f708"}, - {file = "lxml-5.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:9ca66b8e90daca431b7ca1408cae085d025326570e57749695d6a01454790e95"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b0ff53900566bc6325ecde9181d89afadc59c5ffa39bddf084aaedfe3b06a11"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6037392f2d57793ab98d9e26798f44b8b4da2f2464388588f48ac52c489ea1"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9c07e7a45bb64e21df4b6aa623cb8ba214dfb47d2027d90eac197329bb5e94"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3249cc2989d9090eeac5467e50e9ec2d40704fea9ab72f36b034ea34ee65ca98"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f42038016852ae51b4088b2862126535cc4fc85802bfe30dea3500fdfaf1864e"}, - {file = "lxml-5.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:533658f8fbf056b70e434dff7e7aa611bcacb33e01f75de7f821810e48d1bb66"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:622020d4521e22fb371e15f580d153134bfb68d6a429d1342a25f051ec72df1c"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efa7b51824aa0ee957ccd5a741c73e6851de55f40d807f08069eb4c5a26b2baa"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c6ad0fbf105f6bcc9300c00010a2ffa44ea6f555df1a2ad95c88f5656104817"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e233db59c8f76630c512ab4a4daf5a5986da5c3d5b44b8e9fc742f2a24dbd460"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a014510830df1475176466b6087fc0c08b47a36714823e58d8b8d7709132a96"}, - {file = "lxml-5.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d38c8f50ecf57f0463399569aa388b232cf1a2ffb8f0a9a5412d0db57e054860"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5aea8212fb823e006b995c4dda533edcf98a893d941f173f6c9506126188860d"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff097ae562e637409b429a7ac958a20aab237a0378c42dabaa1e3abf2f896e5f"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f5d65c39f16717a47c36c756af0fb36144069c4718824b7533f803ecdf91138"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3d0c3dd24bb4605439bf91068598d00c6370684f8de4a67c2992683f6c309d6b"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e32be23d538753a8adb6c85bd539f5fd3b15cb987404327c569dfc5fd8366e85"}, - {file = "lxml-5.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cc518cea79fd1e2f6c90baafa28906d4309d24f3a63e801d855e7424c5b34144"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0af35bd8ebf84888373630f73f24e86bf016642fb8576fba49d3d6b560b7cbc"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8aca2e3a72f37bfc7b14ba96d4056244001ddcc18382bd0daa087fd2e68a354"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ca1e8188b26a819387b29c3895c47a5e618708fe6f787f3b1a471de2c4a94d9"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c8ba129e6d3b0136a0f50345b2cb3db53f6bda5dd8c7f5d83fbccba97fb5dcb5"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e998e304036198b4f6914e6a1e2b6f925208a20e2042563d9734881150c6c246"}, - {file = "lxml-5.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d3be9b2076112e51b323bdf6d5a7f8a798de55fb8d95fcb64bd179460cdc0704"}, - {file = "lxml-5.2.1.tar.gz", hash = "sha256:3f7765e69bbce0906a7c74d5fe46d2c7a7596147318dbc08e4a2431f3060e306"}, + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632"}, + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526"}, + {file = "lxml-5.2.2-cp310-cp310-win32.whl", hash = "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30"}, + {file = "lxml-5.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b"}, + {file = "lxml-5.2.2-cp311-cp311-win32.whl", hash = "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438"}, + {file = "lxml-5.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836"}, + {file = "lxml-5.2.2-cp312-cp312-win32.whl", hash = "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a"}, + {file = "lxml-5.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48"}, + {file = "lxml-5.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264"}, + {file = "lxml-5.2.2-cp36-cp36m-win32.whl", hash = "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3"}, + {file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"}, + {file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"}, + {file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"}, + {file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"}, + {file = "lxml-5.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1"}, + {file = "lxml-5.2.2-cp38-cp38-win32.whl", hash = "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30"}, + {file = "lxml-5.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9"}, + {file = "lxml-5.2.2-cp39-cp39-win32.whl", hash = "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf"}, + {file = "lxml-5.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324"}, + {file = "lxml-5.2.2.tar.gz", hash = "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"}, ] [package.extras] @@ -1135,13 +1122,13 @@ files = [ [[package]] name = "more-itertools" -version = "9.1.0" +version = "10.2.0" description = "More routines for operating on iterables, beyond itertools" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"}, - {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"}, + {file = "more-itertools-10.2.0.tar.gz", hash = "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1"}, + {file = "more_itertools-10.2.0-py3-none-any.whl", hash = "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684"}, ] [[package]] @@ -1168,6 +1155,53 @@ files = [ [package.dependencies] dill = ">=0.3.8" +[[package]] +name = "mypy" +version = "1.10.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, + {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, + {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, + {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, + {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, + {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, + {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, + {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, + {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, + {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, + {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, + {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, + {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, + {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, + {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, + {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, + {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, + {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, + {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -1191,42 +1225,19 @@ files = [ ] [[package]] -name = "numpy" -version = "1.24.4" -description = "Fundamental package for array computing in Python" +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" optional = false -python-versions = ">=3.8" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ - {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, - {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, - {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, - {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, - {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, - {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, - {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, - {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, - {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, - {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, - {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, ] +[package.dependencies] +setuptools = "*" + [[package]] name = "numpy" version = "1.26.4" @@ -1364,17 +1375,6 @@ sql-other = ["SQLAlchemy (>=1.4.16)"] test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.6.3)"] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "percy" version = "2.0.2" @@ -1391,13 +1391,13 @@ requests = ">=2.14.0" [[package]] name = "platformdirs" -version = "4.2.1" +version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, - {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] @@ -1435,6 +1435,24 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pre-commit" +version = "3.7.1" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, + {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "priority" version = "2.0.0" @@ -1638,13 +1656,13 @@ files = [ [[package]] name = "pytest" -version = "8.2.0" +version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"}, - {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"}, + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies] @@ -1789,13 +1807,13 @@ dotenv = ["python-dotenv"] [[package]] name = "requests" -version = "2.32.0" +version = "2.32.2" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ - {file = "requests-2.32.0-py3-none-any.whl", hash = "sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5"}, - {file = "requests-2.32.0.tar.gz", hash = "sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8"}, + {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, + {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, ] [package.dependencies] @@ -1822,6 +1840,32 @@ files = [ [package.dependencies] six = ">=1.7.0" +[[package]] +name = "ruff" +version = "0.4.5" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.4.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8f58e615dec58b1a6b291769b559e12fdffb53cc4187160a2fc83250eaf54e96"}, + {file = "ruff-0.4.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:84dd157474e16e3a82745d2afa1016c17d27cb5d52b12e3d45d418bcc6d49264"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f483ad9d50b00e7fd577f6d0305aa18494c6af139bce7319c68a17180087f4"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63fde3bf6f3ad4e990357af1d30e8ba2730860a954ea9282c95fc0846f5f64af"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e3ba4620dee27f76bbcad97067766026c918ba0f2d035c2fc25cbdd04d9c97"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:441dab55c568e38d02bbda68a926a3d0b54f5510095c9de7f95e47a39e0168aa"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1169e47e9c4136c997f08f9857ae889d614c5035d87d38fda9b44b4338909cdf"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:755ac9ac2598a941512fc36a9070a13c88d72ff874a9781493eb237ab02d75df"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4b02a65985be2b34b170025a8b92449088ce61e33e69956ce4d316c0fe7cce0"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:75a426506a183d9201e7e5664de3f6b414ad3850d7625764106f7b6d0486f0a1"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6e1b139b45e2911419044237d90b60e472f57285950e1492c757dfc88259bb06"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a6f29a8221d2e3d85ff0c7b4371c0e37b39c87732c969b4d90f3dad2e721c5b1"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d6ef817124d72b54cc923f3444828ba24fa45c3164bc9e8f1813db2f3d3a8a11"}, + {file = "ruff-0.4.5-py3-none-win32.whl", hash = "sha256:aed8166c18b1a169a5d3ec28a49b43340949e400665555b51ee06f22813ef062"}, + {file = "ruff-0.4.5-py3-none-win_amd64.whl", hash = "sha256:b0b03c619d2b4350b4a27e34fd2ac64d0dabe1afbf43de57d0f9d8a05ecffa45"}, + {file = "ruff-0.4.5-py3-none-win_arm64.whl", hash = "sha256:9d15de3425f53161b3f5a5658d4522e4eee5ea002bf2ac7aa380743dd9ad5fba"}, + {file = "ruff-0.4.5.tar.gz", hash = "sha256:286eabd47e7d4d521d199cab84deca135557e6d1e0f0d01c29e757c3cb151b54"}, +] + [[package]] name = "selenium" version = "4.2.0" @@ -1839,19 +1883,18 @@ urllib3 = {version = ">=1.26,<2.0", extras = ["secure", "socks"]} [[package]] name = "setuptools" -version = "69.5.1" +version = "70.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, - {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, + {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, + {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -1948,17 +1991,18 @@ exceptiongroup = "*" [[package]] name = "tenacity" -version = "8.2.3" +version = "8.3.0" description = "Retry code until it succeeds" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, ] [package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "termcolor" @@ -1987,13 +2031,13 @@ files = [ [[package]] name = "trio" -version = "0.25.0" +version = "0.25.1" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.8" files = [ - {file = "trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81"}, - {file = "trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e"}, + {file = "trio-0.25.1-py3-none-any.whl", hash = "sha256:e42617ba091e7b2e50c899052e83a3c403101841de925187f61e7b7eaebdf3fb"}, + {file = "trio-0.25.1.tar.gz", hash = "sha256:9f5314f014ea3af489e77b001861c535005c3858d38ec46b6b071ebfa339d7fb"}, ] [package.dependencies] @@ -2023,13 +2067,13 @@ wsproto = ">=0.14" [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] @@ -2096,6 +2140,26 @@ h11 = ">=0.8" [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "virtualenv" +version = "20.26.2" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, + {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "waitress" version = "3.0.0" @@ -2144,23 +2208,23 @@ h11 = ">=0.9.0,<1" [[package]] name = "zipp" -version = "3.18.1" +version = "3.18.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, - {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, + {file = "zipp-3.18.2-py3-none-any.whl", hash = "sha256:dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e"}, + {file = "zipp-3.18.2.tar.gz", hash = "sha256:6278d9ddbcfb1f1089a88fde84481528b07b0e10474e09dcfe53dad4069fa059"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] mantine = ["dash-mantine-components"] [metadata] lock-version = "2.0" -python-versions = ">=3.8,<4" -content-hash = "ffb30fa71e97eb623efdac3dccd58267441fdc51ef030991af0d844ea3656c99" +python-versions = ">=3.9,<4" +content-hash = "0c7ce2e8115040402778ba839ae9822c8c980bc297950ffb4b470deb4f8998fc" diff --git a/pyproject.toml b/pyproject.toml index 48feb3d..2e0e913 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dash-extensions" -version = "1.0.15" +version = "1.0.16" description = "Extensions for Plotly Dash." authors = ["emher "] license = "MIT" @@ -23,34 +23,37 @@ include = [ ] [tool.poetry.dependencies] -python = ">=3.8,<4" -dash = ">=2.15.0" -more-itertools = "^9.0.0" +python = ">=3.9,<4" +dash = ">=2.17.0" +more-itertools = ">=10.2.0, <11.0.0" jsbeautifier = "^1.14.3" Flask-Caching = "^2.1.0" dash-mantine-components = {version = "^0.14.3", optional = true} dataclass-wizard = "^0.22.2" +ruff = "^0.4.5" +pydantic = "^2.7.1" [tool.poetry.extras] mantine = ["dash-mantine-components"] -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] dash = {extras = ["dev", "testing"], version = "^2.17.0"} pytest-cov = "^4.0.0" -black = "^24.3.0" pandas = ">=1.5.3" quart = "^0.18.3" starlette = "^0.36.2" -requests = "^2.32.0" +requests = "^2.32.2" certifi = "^2023.07.22" uvicorn = "^0.20.0" sse-starlette = "^1.2.1" urllib3 = "^1.26.18" +pre-commit = "^3.7.1" +mypy = "^1.10.0" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" -[tool.black] +[tool.ruff] line-length = 120 -target-version = ["py39"] +target-version = "py39" diff --git a/src/lib/components/CycleBreaker.react.js b/src/lib/components/CycleBreaker.react.js index 1f49201..b0a23a4 100644 --- a/src/lib/components/CycleBreaker.react.js +++ b/src/lib/components/CycleBreaker.react.js @@ -39,4 +39,4 @@ CycleBreaker.propTypes = { */ setProps: PropTypes.func -}; \ No newline at end of file +}; diff --git a/src/lib/components/DeferScript.react.js b/src/lib/components/DeferScript.react.js index e1ffca1..67323f2 100644 --- a/src/lib/components/DeferScript.react.js +++ b/src/lib/components/DeferScript.react.js @@ -36,4 +36,4 @@ DeferScript.propTypes = { */ src: PropTypes.string -}; \ No newline at end of file +}; diff --git a/src/lib/components/Keyboard.react.js b/src/lib/components/Keyboard.react.js index 7694217..f352d4b 100644 --- a/src/lib/components/Keyboard.react.js +++ b/src/lib/components/Keyboard.react.js @@ -151,4 +151,4 @@ Keyboard.propTypes = { */ useCapture: PropTypes.bool -}; \ No newline at end of file +}; diff --git a/src/lib/components/Loading.react.js b/src/lib/components/Loading.react.js index 6c3ec15..1927230 100644 --- a/src/lib/components/Loading.react.js +++ b/src/lib/components/Loading.react.js @@ -15,7 +15,7 @@ const Loading = (props) => { useEffect(() => { const mounted = container && container.current; - const handlePreventDefault = (e) => { + const handlePreventDefault = (e) => { e.preventDefault(); } if(mounted){ diff --git a/src/lib/components/SSE.js b/src/lib/components/SSE.js new file mode 100644 index 0000000..f93de97 --- /dev/null +++ b/src/lib/components/SSE.js @@ -0,0 +1,102 @@ +import PropTypes from "prop-types"; +import { useEffect, useState } from "react"; +import { SSE as SSEjs } from "sse.js"; + + +/** + * The SSE component makes it possible to collect data from e.g. a ResponseStream. It's a wrapper around the SSE.js library. + * https://github.com/mpetazzoni/sse.js + */ +const SSE = ({ url, options, concat, setProps }) => { + const [data, setData] = useState(""); + + useEffect(() => { + // Reset on url change. + setProps({ done: false }) + setData("") + // Don't do anything if url is not set. + if (!url) { return () => { }; } + // Instantiate EventSource. + const sse = new SSEjs(url, options); + // Handle messages. + sse.onmessage = e => { + // Handle end of stream. + if (e.data === "[DONE]") { + setProps({ done: true }) + sse.close(); + return; + } + // Update value. + setData(data => concat ? data.concat(e.data) : e.data) + } + // Close on error. + sse.onerror = (e) => { + console.log("ERROR"); + console.log(e); + sse.close(); + } + // Close on unmount. + return () => { + sse.close(); + }; + }, [url, options]); + + // Update value. + setProps({ value: data }) + // Don't render anything. + return <>; +} + +SSE.defaultProps = { + concat: true, +}; + +SSE.propTypes = { + + /** + * The ID used to identify this component in Dash callbacks. + */ + id: PropTypes.string, + + /** + * Dash-assigned callback that should be called to report property changes + * to Dash, to make them available for callbacks. + */ + setProps: PropTypes.func, + + /** + * Options passed to the SSE constructor. https://github.com/mpetazzoni/sse.js?tab=readme-ov-file#options-reference + */ + options: PropTypes.shape({ + headers: PropTypes.object, + method: PropTypes.string, + payload: PropTypes.object, + withCredentials: PropTypes.bool, + start: PropTypes.bool, + debug: PropTypes.bool, + }), + + /** + * URL of the endpoint. + */ + url: PropTypes.string, + + /** + * A boolean indicating if the stream values should be concatenated. + */ + concat: PropTypes.bool, + + /** + * The data value. Either the latest, or the concatenated dependenig on the `concat` property. + */ + value: PropTypes.string, + + /** + * A boolean indicating if the (current) stream has ended. + */ + done: PropTypes.bool + +}; + + +export default SSE diff --git a/src/lib/components/WebSocket.react.js b/src/lib/components/WebSocket.react.js index 8fea4fe..383da64 100644 --- a/src/lib/components/WebSocket.react.js +++ b/src/lib/components/WebSocket.react.js @@ -135,4 +135,4 @@ DashWebSocket.propTypes = { */ setProps: PropTypes.func -} \ No newline at end of file +} diff --git a/src/lib/fragments/Lottie.react.js b/src/lib/fragments/Lottie.react.js index 734b282..206224d 100644 --- a/src/lib/fragments/Lottie.react.js +++ b/src/lib/fragments/Lottie.react.js @@ -56,4 +56,4 @@ export default class Lottie extends Component { } } -Lottie.propTypes = propTypes; \ No newline at end of file +Lottie.propTypes = propTypes; diff --git a/src/lib/index.js b/src/lib/index.js index 4b1febe..0c6176f 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -1,26 +1,20 @@ /* eslint-disable import/prefer-default-export */ -import Lottie from "./components/Lottie.react"; -import WebSocket from "./components/WebSocket.react"; import BeforeAfter from "./components/BeforeAfter.react"; -import Mermaid from "./components/Mermaid.react"; +import CycleBreaker from "./components/CycleBreaker.react"; import DeferScript from "./components/DeferScript.react"; -import Purify from "./components/Purify.react"; import EventListener from "./components/EventListener.react"; import EventSource from "./components/EventSource.react"; -import CycleBreaker from "./components/CycleBreaker.react"; import Keyboard from "./components/Keyboard.react"; import Loading from "./components/Loading.react"; +import Lottie from "./components/Lottie.react"; +import Mermaid from "./components/Mermaid.react"; +import Purify from "./components/Purify.react"; +import SSE from "./components/SSE"; +import WebSocket from "./components/WebSocket.react"; export { - Lottie, - WebSocket, - BeforeAfter, - Mermaid, - DeferScript, - Purify, - EventListener, - EventSource, - CycleBreaker, - Keyboard, - Loading + BeforeAfter, CycleBreaker, DeferScript, EventListener, + EventSource, Keyboard, + Loading, Lottie, Mermaid, Purify, SSE, WebSocket }; + diff --git a/tests/assets/dashExtensions_default.js b/tests/assets/dashExtensions_default.js new file mode 100644 index 0000000..b49f251 --- /dev/null +++ b/tests/assets/dashExtensions_default.js @@ -0,0 +1,7 @@ +window.dashExtensions = Object.assign({}, window.dashExtensions, { + default: { + function0: function(feature, latlng, context) { + return L.circleMarker(latlng); + } + } +}); diff --git a/tests/components/before_after.py b/tests/components/before_after.py index 96065ea..0d19bc9 100644 --- a/tests/components/before_after.py +++ b/tests/components/before_after.py @@ -1,8 +1,18 @@ from dash import Dash, html + from dash_extensions import BeforeAfter app = Dash() -app.layout = html.Div([BeforeAfter(before="assets/lena_bw.png", after="assets/lena_color.png", width=512, height=512)]) +app.layout = html.Div( + [ + BeforeAfter( + before="assets/lena_bw.png", + after="assets/lena_color.png", + width=512, + height=512, + ) + ] +) if __name__ == "__main__": app.run_server() diff --git a/tests/components/defer_script.py b/tests/components/defer_script.py index 883ecc5..f8f904b 100644 --- a/tests/components/defer_script.py +++ b/tests/components/defer_script.py @@ -1,12 +1,18 @@ -from dash import Dash, html from html import unescape + +from dash import Dash, html + from dash_extensions import DeferScript -mxgraph = r"{"highlight":"#0000ff","nav":true,"resize":true,"toolbar":"zoom layers lightbox","edit":"_blank","xml":"<mxfile host=\"app.diagrams.net\" modified=\"2021-06-07T06:06:13.695Z\" agent=\"5.0 (Windows)\" etag=\"4lPJKNab0_B4ArwMh0-7\" version=\"14.7.6\"><diagram id=\"YgMnHLNxFGq_Sfquzsd6\" name=\"Page-1\">jZJNT4QwEIZ/DUcToOriVVw1JruJcjDxYho60iaFIaUs4K+3yJSPbDbZSzN95qPTdyZgadm/GF7LAwrQQRyKPmBPQRzvktidIxgmwB4IFEaJCUULyNQvEAyJtkpAswm0iNqqegtzrCrI7YZxY7Dbhv2g3r5a8wLOQJZzfU4/lbByoslduPBXUIX0L0cheUrugwk0kgvsVojtA5YaRDtZZZ+CHrXzukx5zxe8c2MGKntNgknk8bs8fsj3+KtuDhxP+HZDVU5ct/RhatYOXgGDbSVgLBIG7LGTykJW83z0dm7kjklbaneLnEnlwFjoL/YZzb93WwNYgjWDC6EEdkuC0cZEO7p3i/6RF1WutL8nxmnkxVx6UcUZJIy/LgP49622mO3/AA==</diagram></mxfile>"}" +mxgraph = r"{"highlight":"#0000ff","nav":true,"resize":true,"toolbar":"zoom layers lightbox","edit":"_blank","xml":"<mxfile host=\"app.diagrams.net\" modified=\"2021-06-07T06:06:13.695Z\" agent=\"5.0 (Windows)\" etag=\"4lPJKNab0_B4ArwMh0-7\" version=\"14.7.6\"><diagram id=\"YgMnHLNxFGq_Sfquzsd6\" name=\"Page-1\">jZJNT4QwEIZ/DUcToOriVVw1JruJcjDxYho60iaFIaUs4K+3yJSPbDbZSzN95qPTdyZgadm/GF7LAwrQQRyKPmBPQRzvktidIxgmwB4IFEaJCUULyNQvEAyJtkpAswm0iNqqegtzrCrI7YZxY7Dbhv2g3r5a8wLOQJZzfU4/lbByoslduPBXUIX0L0cheUrugwk0kgvsVojtA5YaRDtZZZ+CHrXzukx5zxe8c2MGKntNgknk8bs8fsj3+KtuDhxP+HZDVU5ct/RhatYOXgGDbSVgLBIG7LGTykJW83z0dm7kjklbaneLnEnlwFjoL/YZzb93WwNYgjWDC6EEdkuC0cZEO7p3i/6RF1WutL8nxmnkxVx6UcUZJIy/LgP49622mO3/AA==</diagram></mxfile>"}" # noqa: E501 app = Dash(__name__) app.layout = html.Div( [ - html.Div(className="mxgraph", style={"maxWidth": "100%"}, **{"data-mxgraph": unescape(mxgraph)}), + html.Div( + className="mxgraph", + style={"maxWidth": "100%"}, + **{"data-mxgraph": unescape(mxgraph)}, + ), DeferScript(src="https://viewer.diagrams.net/js/viewer-static.min.js"), ] ) diff --git a/tests/components/event_listener.py b/tests/components/event_listener.py index bc60a8b..3d36eff 100644 --- a/tests/components/event_listener.py +++ b/tests/components/event_listener.py @@ -1,11 +1,14 @@ import pandas as pd -from dash import Dash, html, Input, Output, dash_table as dt +from dash import Dash, Input, Output +from dash import dash_table as dt +from dash import html from dash.exceptions import PreventUpdate + from dash_extensions import EventListener # Create a small data table. -df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv') -table = dt.DataTable(df.to_dict('records'), [{"name": i, "id": i} for i in df.columns], id="tbl") +df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv") +table = dt.DataTable(df.to_dict("records"), [{"name": i, "id": i} for i in df.columns], id="tbl") # The event(s) to listen to (i.e. click) and the prop(s) to record, i.e. the column name. row_index = "srcElement.attributes.data-dash-row.value" events = [{"event": "click", "props": [row_index]}] diff --git a/tests/components/keyboard.py b/tests/components/keyboard.py index b7fe873..ec147aa 100644 --- a/tests/components/keyboard.py +++ b/tests/components/keyboard.py @@ -1,4 +1,5 @@ from dash import Dash + from dash_extensions import Keyboard app = Dash() diff --git a/tests/components/lottie.py b/tests/components/lottie.py index 88725c9..080483c 100644 --- a/tests/components/lottie.py +++ b/tests/components/lottie.py @@ -1,9 +1,14 @@ -from dash import Dash, html, dcc, Input, Output, no_update +from dash import Dash, Input, Output, dcc, html, no_update + from dash_extensions import Lottie # Setup options. url = "https://assets9.lottiefiles.com/packages/lf20_YXD37q.json" -options = dict(loop=True, autoplay=True, rendererSettings=dict(preserveAspectRatio="xMidYMid slice")) +options = dict( + loop=True, + autoplay=True, + rendererSettings=dict(preserveAspectRatio="xMidYMid slice"), +) # Create example app. app = Dash(__name__) app.layout = html.Div( diff --git a/tests/components/mermaid.py b/tests/components/mermaid.py index c03fc9d..af13531 100644 --- a/tests/components/mermaid.py +++ b/tests/components/mermaid.py @@ -1,4 +1,5 @@ -from dash import Dash, html, Output, Input +from dash import Dash, Input, Output, html + from dash_extensions import Mermaid chart = """ diff --git a/tests/components/purify.py b/tests/components/purify.py index a573786..93edda3 100644 --- a/tests/components/purify.py +++ b/tests/components/purify.py @@ -1,4 +1,5 @@ from dash import Dash + from dash_extensions import Purify app = Dash() diff --git a/tests/components/ticker.py b/tests/components/ticker.py index f3ea63e..9cbe592 100644 --- a/tests/components/ticker.py +++ b/tests/components/ticker.py @@ -1,4 +1,5 @@ from dash import Dash, html + from dash_extensions import Ticker app = Dash(__name__) diff --git a/tests/mock_app.py b/tests/mock_app.py index 6273a59..8287ed2 100644 --- a/tests/mock_app.py +++ b/tests/mock_app.py @@ -1,31 +1,36 @@ -from dash_extensions.enrich import Dash, callback, html, Input, Output, ctx +from dash_extensions.enrich import Dash, Input, Output, callback, ctx, html app = Dash(__name__) -app.layout = html.Div([ - html.Button('Button 1', id='btn-1'), - html.Button('Button 2', id='btn-2'), - html.Button('Button 3', id='btn-3'), - html.Div(id='container'), - html.Div(id='container-no-ctx') -]) +app.layout = html.Div( + [ + html.Button("Button 1", id="btn-1"), + html.Button("Button 2", id="btn-2"), + html.Button("Button 3", id="btn-3"), + html.Div(id="container"), + html.Div(id="container-no-ctx"), + ] +) @callback( - Output('container-no-ctx', 'children'), - Input('btn-1', 'n_clicks'), - Input('btn-2', 'n_clicks')) + Output("container-no-ctx", "children"), + Input("btn-1", "n_clicks"), + Input("btn-2", "n_clicks"), +) def update(btn1, btn2): - return f'button 1: {btn1} & button 2: {btn2}' + return f"button 1: {btn1} & button 2: {btn2}" -@callback(Output('container', 'children'), - Input('btn-1', 'n_clicks'), - Input('btn-2', 'n_clicks'), - Input('btn-3', 'n_clicks')) +@callback( + Output("container", "children"), + Input("btn-1", "n_clicks"), + Input("btn-2", "n_clicks"), + Input("btn-3", "n_clicks"), +) def display(btn1, btn2, btn3): button_clicked = ctx.triggered_id - return f'You last clicked button with ID {button_clicked}' + return f"You last clicked button with ID {button_clicked}" -if __name__ == '__main__': +if __name__ == "__main__": app.run_server(debug=True) diff --git a/tests/mock_async.py b/tests/mock_async.py index ddeea7c..6d2762f 100644 --- a/tests/mock_async.py +++ b/tests/mock_async.py @@ -37,5 +37,5 @@ async def websocket_endpoint(websocket): if __name__ == "__main__": - logging.basicConfig(format='{levelname:7} {message}', style='{', level=logging.INFO) - uvicorn.run(async_server, port=5002, log_config=None) \ No newline at end of file + logging.basicConfig(format="{levelname:7} {message}", style="{", level=logging.INFO) + uvicorn.run(async_server, port=5002, log_config=None) diff --git a/tests/test_async.py b/tests/test_async.py index a60c271..b2152d0 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -1,13 +1,13 @@ import time +from multiprocessing import Process + import pytest import uvicorn +from dash import Dash, Input, Output, dcc, html -from multiprocessing import Process from dash_extensions import EventSource, WebSocket -from dash import Dash, Input, Output, html, dcc - from dash_extensions.enrich import DashBlueprint, DashProxy -from tests.mock_async import sse_response, async_server, ws_response +from tests.mock_async import async_server, sse_response, ws_response # region Async mock server fixture @@ -27,13 +27,14 @@ def ws_example_bp(extra_children=None) -> DashBlueprint: dcc.Input(id="input", autoComplete="off"), html.Div(id="msg"), WebSocket(url=ws_server_url, id="ws"), - ] + (extra_children if extra_children is not None else []) + ] + + (extra_children if extra_children is not None else []) ) # Send input value using websocket. send = "function(value){return value;}" dbp.clientside_callback(send, Output("ws", "send"), [Input("input", "value")]) # Update div using websocket. - receive = 'function(msg){return msg.data;}' + receive = "function(msg){return msg.data;}" dbp.clientside_callback(receive, Output("msg", "children"), [Input("ws", "message")]) return dbp @@ -48,6 +49,7 @@ def server(): # endregion + def test_server_sent_events(dash_duo, server): # Create small example app. app = Dash(__name__) diff --git a/tests/test_callback_pytest.py b/tests/test_callback_pytest.py index f1e201a..cff5ad2 100644 --- a/tests/test_callback_pytest.py +++ b/tests/test_callback_pytest.py @@ -1,4 +1,5 @@ from contextvars import copy_context + from dash._callback_context import context_value from dash._utils import AttributeDict @@ -7,7 +8,7 @@ def test_update_callback(): output = update(1, 0) - assert output == 'button 1: 1 & button 2: 0' + assert output == "button 1: 1 & button 2: 0" def test_display_callback(): @@ -17,4 +18,4 @@ def run_callback(): ctx = copy_context() output = ctx.run(run_callback) - assert output == f'You last clicked button with ID btn-1-ctx-example' + assert output == "You last clicked button with ID btn-1-ctx-example" diff --git a/tests/test_components.py b/tests/test_components.py index 251d27f..7605fd8 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -2,7 +2,15 @@ from dash.testing.application_runners import import_app # All custom dash components. -components = ["before_after", "defer_script", "event_listener", "lottie", "mermaid", "purify", "keyboard"] +components = [ + "before_after", + "defer_script", + "event_listener", + "lottie", + "mermaid", + "purify", + "keyboard", +] # Basic test for the component rendering. diff --git a/tests/test_dataiku.py b/tests/test_dataiku.py index f0de338..6ff3538 100644 --- a/tests/test_dataiku.py +++ b/tests/test_dataiku.py @@ -1,7 +1,9 @@ import os +from shutil import rmtree + from dash import Dash + from dash_extensions.dataiku import bind_assets_folder -from shutil import rmtree def test_bind_assets_folder(): @@ -10,7 +12,7 @@ def test_bind_assets_folder(): # Create a mock asset dir. tmp_dir = "/tmp/assets/" os.makedirs(tmp_dir, exist_ok=True) - with open(os.path.join(tmp_dir, asset_name), 'w') as f: + with open(os.path.join(tmp_dir, asset_name), "w") as f: f.write("const a = 0;") # Clear the asset dir. app = Dash() diff --git a/tests/test_enrich.py b/tests/test_enrich.py index c599ff8..61db81e 100644 --- a/tests/test_enrich.py +++ b/tests/test_enrich.py @@ -9,14 +9,39 @@ import dash import pandas as pd import pytest -import dash_extensions.enrich from dash.exceptions import PreventUpdate +from pydantic import BaseModel -from dash_extensions.enrich import Output, Input, State, CallbackBlueprint, html, DashProxy, NoOutputTransform, Trigger, \ - TriggerTransform, MultiplexerTransform, PrefixIdTransform, callback, clientside_callback, DashLogger, LogTransform, \ - BlockingCallbackTransform, dcc, ServersideOutputTransform, Serverside, ALL, CycleBreakerTransform, \ - CycleBreakerInput, DependencyCollection, DashBlueprint, MATCH, DataclassTransform - +import dash_extensions.enrich +from dash_extensions.enrich import ( + ALL, + MATCH, + BaseModelTransform, + BlockingCallbackTransform, + CallbackBlueprint, + CycleBreakerInput, + CycleBreakerTransform, + DashBlueprint, + DashLogger, + DashProxy, + DataclassTransform, + DependencyCollection, + Input, + LogTransform, + MultiplexerTransform, + NoOutputTransform, + Output, + PrefixIdTransform, + Serverside, + ServersideOutputTransform, + State, + Trigger, + TriggerTransform, + callback, + clientside_callback, + dcc, + html, +) # region Test utils/stubs @@ -33,7 +58,7 @@ def _css_escape(s): def _css_selector(_id): - return f'#{_css_escape(_stringify_id(_id))}' + return f"#{_css_escape(_stringify_id(_id))}" def _cssid(**kwargs): @@ -44,11 +69,7 @@ def _cssid(**kwargs): def _get_basic_dash_proxy(**kwargs) -> DashProxy: app = DashProxy(**kwargs) - app.layout = html.Div([ - html.Button(id="btn"), - html.Div(id="log_server"), - html.Div(id="log_client") - ]) + app.layout = html.Div([html.Button(id="btn"), html.Div(id="log_server"), html.Div(id="log_client")]) return app @@ -62,14 +83,20 @@ def update_log(n_clicks): def _bind_basic_callback_flex(app): - @app.callback(output=dict(n=Output("log_server", "children")), inputs=dict(n_clicks=Input("btn", "n_clicks"))) + @app.callback( + output=dict(n=Output("log_server", "children")), + inputs=dict(n_clicks=Input("btn", "n_clicks")), + ) def update_log(n_clicks): return dict(n=n_clicks) def _bind_basic_clientside_callback(app): - app.clientside_callback("function(x){return x;}", - Output("log_client", "children"), Input("btn", "n_clicks")) + app.clientside_callback( + "function(x){return x;}", + Output("log_client", "children"), + Input("btn", "n_clicks"), + ) def _basic_dash_proxy_test(dash_duo, app, element_ids=None, btn_id="btn"): @@ -88,14 +115,31 @@ def _basic_dash_proxy_test(dash_duo, app, element_ids=None, btn_id="btn"): @pytest.mark.parametrize( - 'tst, flt', - [(dict(a=Input("a", "prop"), b=[Input("b", "prop")], c=dict(ca=[Input("ca1", "prop"), Input("ca2", "prop")])), - [Input("a", "prop"), Input("b", "prop"), Input("ca1", "prop"), Input("ca2", "prop")]), - ([Input("a", "prop"), Input("b", "prop"), Input("c", "prop")], - [Input("a", "prop"), Input("b", "prop"), Input("c", "prop")]), - ((Input("a", "prop"), Input("b", "prop"), Input("c", "prop")), - [Input("a", "prop"), Input("b", "prop"), Input("c", "prop")]) - ]) + "tst, flt", + [ + ( + dict( + a=Input("a", "prop"), + b=[Input("b", "prop")], + c=dict(ca=[Input("ca1", "prop"), Input("ca2", "prop")]), + ), + [ + Input("a", "prop"), + Input("b", "prop"), + Input("ca1", "prop"), + Input("ca2", "prop"), + ], + ), + ( + [Input("a", "prop"), Input("b", "prop"), Input("c", "prop")], + [Input("a", "prop"), Input("b", "prop"), Input("c", "prop")], + ), + ( + (Input("a", "prop"), Input("b", "prop"), Input("c", "prop")), + [Input("a", "prop"), Input("b", "prop"), Input("c", "prop")], + ), + ], +) def test_dependency_collection(tst, flt): dc = DependencyCollection(tst) # Test iteration. @@ -121,10 +165,14 @@ def test_callback_blueprint(): cbp = CallbackBlueprint( [State("s", "prop"), State("s2", "prop")], [Output("o", "prop")], - [Input("i", "prop")] + [Input("i", "prop")], ) assert list(cbp.outputs) == [Output("o", "prop")] - assert list(cbp.inputs) == [State("s", "prop"), State("s2", "prop"), Input("i", "prop")] + assert list(cbp.inputs) == [ + State("s", "prop"), + State("s2", "prop"), + Input("i", "prop"), + ] # Test mix. cbp = CallbackBlueprint( [State("s", "prop"), State("s2", "prop")], @@ -132,36 +180,30 @@ def test_callback_blueprint(): [Output("o", "prop")], State("s3", "prop"), [Input("i", "prop")], - Output("o2", "prop") + Output("o2", "prop"), ) assert list(cbp.outputs) == [Output("o", "prop"), Output("o2", "prop")] - assert list(cbp.inputs) == [State("s", "prop"), State("s2", "prop"), Input("i0", "prop"), - State("s3", "prop"), Input("i", "prop")] + assert list(cbp.inputs) == [ + State("s", "prop"), + State("s2", "prop"), + Input("i0", "prop"), + State("s3", "prop"), + Input("i", "prop"), + ] # Test variables. my_input = html.Button() my_output = html.Div() - cbp = CallbackBlueprint( - Input(my_input, "n_clicks"), - Output(my_output, "children") - ) + cbp = CallbackBlueprint(Input(my_input, "n_clicks"), Output(my_output, "children")) assert list(cbp.outputs) == [Output(my_output, "children")] assert list(cbp.inputs) == [Input(my_input, "n_clicks")] # Test kwargs. - cbp = CallbackBlueprint( - Input(my_input, "n_clicks"), - Output(my_output, "children"), - hello="world" - ) + cbp = CallbackBlueprint(Input(my_input, "n_clicks"), Output(my_output, "children"), hello="world") assert cbp.kwargs == dict(hello="world") def test_flexible_callback_signature(): # Test input/output/state as kwargs. - cbp = CallbackBlueprint( - output=[Output("o", "prop")], - inputs=[Input("i", "prop")], - hello="world" - ) + cbp = CallbackBlueprint(output=[Output("o", "prop")], inputs=[Input("i", "prop")], hello="world") assert list(cbp.inputs) == [Input("i", "prop")] assert list(cbp.outputs) == [Output("o", "prop")] assert cbp.kwargs == dict(hello="world") @@ -169,7 +211,7 @@ def test_flexible_callback_signature(): cbp = CallbackBlueprint( output=dict(o=Output("o", "prop"), u=Output("u", "prop")), inputs=dict(i=Input("i", "prop"), s=State("s", "prop")), - hello="world" + hello="world", ) assert list(cbp.inputs) == [Input("i", "prop"), State("s", "prop")] assert list(cbp.outputs) == [Output("o", "prop"), Output("u", "prop")] @@ -177,24 +219,35 @@ def test_flexible_callback_signature(): # Test complex dict grouping. cbp = CallbackBlueprint( output=[Output("o", "prop"), Output("u", "prop")], - inputs=dict(w=dict(i=Input("i", "prop"), s=State("s", "prop")), z=dict(i=Input("i2", "prop"))), - hello="world" + inputs=dict( + w=dict(i=Input("i", "prop"), s=State("s", "prop")), + z=dict(i=Input("i2", "prop")), + ), + hello="world", ) - assert list(cbp.inputs) == [Input("i", "prop"), State("s", "prop"), Input("i2", "prop")] + assert list(cbp.inputs) == [ + Input("i", "prop"), + State("s", "prop"), + Input("i2", "prop"), + ] assert list(cbp.outputs) == [Output("o", "prop"), Output("u", "prop")] assert cbp.kwargs == dict(hello="world") def test_flexible_callback_signature_in_app(dash_duo): app = DashProxy() - app.layout = html.Div([ - html.Div(id="a", children="a"), - html.Div(id="b", children="b"), - html.Div(id="log", children=None), - ]) - - @app.callback(output=dict(x=Output("log", "children")), - inputs=dict(dict(g=dict(a=Input("a", "children"), b=Input("b", "children"))))) + app.layout = html.Div( + [ + html.Div(id="a", children="a"), + html.Div(id="b", children="b"), + html.Div(id="log", children=None), + ] + ) + + @app.callback( + output=dict(x=Output("log", "children")), + inputs=dict(dict(g=dict(a=Input("a", "children"), b=Input("b", "children")))), + ) def update_x(g): return dict(x=f"{g['a']}_{g['b']}") @@ -215,9 +268,11 @@ def test_dash_proxy(dash_duo): def test_dash_output_input_state_compatibility(dash_duo): app = _get_basic_dash_proxy() - @app.callback(dash.Output("log_server", "children"), - dash.Input("btn", "n_clicks"), - dash.State("btn", "n_clicks")) + @app.callback( + dash.Output("log_server", "children"), + dash.Input("btn", "n_clicks"), + dash.State("btn", "n_clicks"), + ) def update_log(n_clicks, state): return n_clicks @@ -225,14 +280,19 @@ def update_log(n_clicks, state): @pytest.mark.parametrize( - 'args, kwargs', - [([Input("btn", "n_clicks")], dict()), - ([], dict(inputs=dict(n_clicks=Input("btn", "n_clicks"))))]) + "args, kwargs", + [ + ([Input("btn", "n_clicks")], dict()), + ([], dict(inputs=dict(n_clicks=Input("btn", "n_clicks")))), + ], +) def test_no_output_transform(dash_duo, args, kwargs): app = DashProxy() - app.layout = html.Div([ - html.Button(id="btn"), - ]) + app.layout = html.Div( + [ + html.Button(id="btn"), + ] + ) @app.callback(*args, **kwargs) def update(n_clicks): @@ -252,19 +312,23 @@ def update(n_clicks): def test_trigger_transform(dash_duo): app = DashProxy(prevent_initial_callbacks=True, transforms=[TriggerTransform()]) - app.layout = html.Div([ - html.Button(id="btn1"), - html.Button(id="btn2"), - html.Button(id="btn3"), - html.Button(id="btn4"), - html.Div(id="log"), - ]) - - @app.callback(Output("log", "children"), - Trigger("btn1", "n_clicks"), - Input("btn2", "n_clicks"), - Trigger("btn3", "n_clicks"), - State("btn4", "n_clicks")) + app.layout = html.Div( + [ + html.Button(id="btn1"), + html.Button(id="btn2"), + html.Button(id="btn3"), + html.Button(id="btn4"), + html.Div(id="log"), + ] + ) + + @app.callback( + Output("log", "children"), + Trigger("btn1", "n_clicks"), + Input("btn2", "n_clicks"), + Trigger("btn3", "n_clicks"), + State("btn4", "n_clicks"), + ) def update(n_clicks2, n_clicks4): return f"{str(n_clicks2)}-{str(n_clicks4)}" @@ -288,13 +352,15 @@ def update(n_clicks2, n_clicks4): def test_trigger_transform_clientside(dash_duo): app = DashProxy(prevent_initial_callbacks=True, transforms=[TriggerTransform()]) - app.layout = html.Div([ - html.Button(id="btn1"), - html.Button(id="btn2"), - html.Button(id="btn3"), - html.Button(id="btn4"), - html.Div(id="log"), - ]) + app.layout = html.Div( + [ + html.Button(id="btn1"), + html.Button(id="btn2"), + html.Button(id="btn3"), + html.Button(id="btn4"), + html.Div(id="log"), + ] + ) app.clientside_callback( """(nClicks2, nClicks4) => `${nClicks2}-${nClicks4}`""", @@ -302,7 +368,8 @@ def test_trigger_transform_clientside(dash_duo): Trigger("btn1", "n_clicks"), Input("btn2", "n_clicks"), Trigger("btn3", "n_clicks"), - State("btn4", "n_clicks")) + State("btn4", "n_clicks"), + ) # Check that the app works. dash_duo.start_server(app) @@ -323,17 +390,32 @@ def test_trigger_transform_clientside(dash_duo): @pytest.mark.parametrize( - 'args, kwargs', - [([Output("log", "children"), Input("right", "n_clicks")], dict()), - ([], dict(output=[Output("log", "children")], inputs=dict(n_clicks=Input("right", "n_clicks"))))]) + "args, kwargs", + [ + ([Output("log", "children"), Input("right", "n_clicks")], dict()), + ( + [], + dict( + output=[Output("log", "children")], + inputs=dict(n_clicks=Input("right", "n_clicks")), + ), + ), + ], +) def test_multiplexer_transform(dash_duo, args, kwargs): app = DashProxy(prevent_initial_callbacks=True, transforms=[MultiplexerTransform()]) - app.layout = html.Div([ - html.Button(id="left"), - html.Button(id="right"), - html.Div(id="log"), - ]) - app.clientside_callback("function(x){return 'left'}", Output("log", "children"), Input("left", "n_clicks")) + app.layout = html.Div( + [ + html.Button(id="left"), + html.Button(id="right"), + html.Div(id="log"), + ] + ) + app.clientside_callback( + "function(x){return 'left'}", + Output("log", "children"), + Input("left", "n_clicks"), + ) @app.callback(*args, **kwargs) def update_right(n_clicks): @@ -353,8 +435,10 @@ def update_right(n_clicks): def test_multiplexer_transform_wildcard(dash_duo): def make_callback(i): - @app.callback(Output({"type": "div", "id": ALL}, "children"), - Input({"type": f"button{i}", "id": ALL}, "n_clicks")) + @app.callback( + Output({"type": "div", "id": ALL}, "children"), + Input({"type": f"button{i}", "id": ALL}, "n_clicks"), + ) def func(n): return [f"Hello from group {i}"] * len(n) @@ -362,7 +446,7 @@ def make_block(i): layout = [ html.Button(f"Button 0 in group {i}", id={"type": f"button{i}", "id": "x"}), html.Button(f"Button 1 in group {i}", id={"type": f"button{i}", "id": "y"}), - html.Div(f"Div {i}", id={"type": f"div", "id": i}), + html.Div(f"Div {i}", id={"type": "div", "id": i}), ] make_callback(i) return layout @@ -377,7 +461,7 @@ def make_block(i): assert dash_duo.find_element(_cssid(id="1", type="div")).text == "Hello from group 1" -@pytest.mark.parametrize('flex', [False, True]) +@pytest.mark.parametrize("flex", [False, True]) def test_prefix_id_transform(dash_duo, flex): app = _get_basic_dash_proxy(transforms=[PrefixIdTransform(prefix="x")]) _bind_basic_callback(app, flex) @@ -387,17 +471,35 @@ def test_prefix_id_transform(dash_duo, flex): @pytest.mark.parametrize( - 'args, kwargs', - [([Output("log", "children"), Input("right", "n_clicks")], dict()), - ([], dict(output=[Output("log", "children")], inputs=dict(n_clicks=Input("right", "n_clicks"))))]) + "args, kwargs", + [ + ([Output("log", "children"), Input("right", "n_clicks")], dict()), + ( + [], + dict( + output=[Output("log", "children")], + inputs=dict(n_clicks=Input("right", "n_clicks")), + ), + ), + ], +) def test_multiplexer_and_prefix_transform(dash_duo, args, kwargs): - app = DashProxy(prevent_initial_callbacks=True, transforms=[PrefixIdTransform("prefix"), MultiplexerTransform()]) - app.layout = html.Div([ - html.Button(id="left"), - html.Button(id="right"), - html.Div(id="log"), - ]) - app.clientside_callback("function(x){return 'left'}", Output("log", "children"), Input("left", "n_clicks")) + app = DashProxy( + prevent_initial_callbacks=True, + transforms=[PrefixIdTransform("prefix"), MultiplexerTransform()], + ) + app.layout = html.Div( + [ + html.Button(id="left"), + html.Button(id="right"), + html.Div(id="log"), + ] + ) + app.clientside_callback( + "function(x){return 'left'}", + Output("log", "children"), + Input("left", "n_clicks"), + ) @app.callback(*args, **kwargs) def update_right(n_clicks): @@ -417,8 +519,11 @@ def update_right(n_clicks): def test_global_blueprint(dash_duo): app = _get_basic_dash_proxy() - clientside_callback("function(x){return x;}", - Output("log_client", "children"), Input("btn", "n_clicks")) + clientside_callback( + "function(x){return x;}", + Output("log_client", "children"), + Input("btn", "n_clicks"), + ) @callback(Output("log_server", "children"), Input("btn", "n_clicks")) def update_log(n_clicks): @@ -431,10 +536,19 @@ def update_log(n_clicks): @pytest.mark.parametrize( - 'args, kwargs, port', - [([Output("log", "children"), Input("trigger", "n_intervals")], dict(), 4757), - ([], dict(output=[Output("log", "children")], - inputs=dict(tick=Input("trigger", "n_intervals"))), 4758)]) + "args, kwargs, port", + [ + ([Output("log", "children"), Input("trigger", "n_intervals")], dict(), 4757), + ( + [], + dict( + output=[Output("log", "children")], + inputs=dict(tick=Input("trigger", "n_intervals")), + ), + 4758, + ), + ], +) def test_blocking_callback_transform(dash_duo, args, kwargs, port): app = DashProxy(transforms=[BlockingCallbackTransform(timeout=5)]) app.layout = html.Div([html.Div(id="log"), dcc.Interval(id="trigger", interval=500)]) @@ -467,11 +581,20 @@ def update(value): f.send_keys("c") dash_duo.wait_for_text_to_equal("#log", "abc", timeout=5) # final invocation + @pytest.mark.parametrize( - 'args, kwargs', - [([Output("store", "children"), Input("btn", "n_clicks")], dict()), - ([], dict(output=Output("store", "children"), - inputs=dict(n_clicks=Input("btn", "n_clicks"))))]) + "args, kwargs", + [ + ([Output("store", "children"), Input("btn", "n_clicks")], dict()), + ( + [], + dict( + output=Output("store", "children"), + inputs=dict(n_clicks=Input("btn", "n_clicks")), + ), + ), + ], +) def test_dataclass_transform(dash_duo, args, kwargs): @dataclass class StateModel: @@ -479,11 +602,56 @@ class StateModel: list_of_values: list[int] app = DashProxy(prevent_initial_callbacks=True, transforms=[DataclassTransform()]) - app.layout = html.Div([ - html.Button(id="btn"), - dcc.Store(id="store"), - html.Div(id="log"), - ]) + app.layout = html.Div( + [ + html.Button(id="btn"), + dcc.Store(id="store"), + html.Div(id="log"), + ] + ) + + @app.callback(Output("store", "data"), Input("btn", "n_clicks")) + def update_default(n_clicks: str): + return StateModel(value=datetime(2000, 1, 1), list_of_values=[1, 2, 3, 4, 5]) + + @app.callback(Output("log", "children"), Input("store", "data")) + def update_log(state: StateModel): + return f"{state.value.isoformat()}: {str(state.list_of_values)}" + + # Check that stuff works. It doesn't using a normal Dash object. + dash_duo.start_server(app) + assert dash_duo.find_element("#log").text == "" + dash_duo.find_element("#btn").click() + time.sleep(0.1) # wait for callback code to execute. + assert dash_duo.find_element("#log").text == "2000-01-01T00:00:00: [1, 2, 3, 4, 5]" + + +@pytest.mark.parametrize( + "args, kwargs", + [ + ([Output("store", "children"), Input("btn", "n_clicks")], dict()), + ( + [], + dict( + output=Output("store", "children"), + inputs=dict(n_clicks=Input("btn", "n_clicks")), + ), + ), + ], +) +def test_base_model_transform(dash_duo, args, kwargs): + class StateModel(BaseModel): + value: datetime + list_of_values: list[int] + + app = DashProxy(prevent_initial_callbacks=True, transforms=[BaseModelTransform()]) + app.layout = html.Div( + [ + html.Button(id="btn"), + dcc.Store(id="store"), + html.Div(id="log"), + ] + ) @app.callback(Output("store", "data"), Input("btn", "n_clicks")) def update_default(n_clicks: str): @@ -502,17 +670,27 @@ def update_log(state: StateModel): @pytest.mark.parametrize( - 'args, kwargs', - [([Output("store", "children"), Input("btn", "n_clicks")], dict()), - ([], dict(output=Output("store", "children"), - inputs=dict(n_clicks=Input("btn", "n_clicks"))))]) + "args, kwargs", + [ + ([Output("store", "children"), Input("btn", "n_clicks")], dict()), + ( + [], + dict( + output=Output("store", "children"), + inputs=dict(n_clicks=Input("btn", "n_clicks")), + ), + ), + ], +) def test_serverside_output_transform(dash_duo, args, kwargs): app = DashProxy(prevent_initial_callbacks=True, transforms=[ServersideOutputTransform()]) - app.layout = html.Div([ - html.Button(id="btn"), - html.Div(id="store"), - html.Div(id="log"), - ]) + app.layout = html.Div( + [ + html.Button(id="btn"), + html.Div(id="store"), + html.Div(id="log"), + ] + ) @app.callback(*args, **kwargs) def update_default(n_clicks): @@ -532,7 +710,7 @@ def update_log(data): assert dash_duo.find_element("#log").text == '{"A":{"0":1}}' -def test_serverside_output_transform_wildcard(dash_duo): +def test_serverside_output_transform_wildcard(dash_duo): # noqa: C901 def _id(t, i): return {"type": t, "index": i} @@ -543,35 +721,34 @@ def make_block(i): html.Div(id=_id("log", i)), ] - app = DashProxy(prevent_initial_callbacks=True, transforms=[ServersideOutputTransform(), MultiplexerTransform()]) + app = DashProxy( + prevent_initial_callbacks=True, + transforms=[ServersideOutputTransform(), MultiplexerTransform()], + ) app.layout = html.Div(make_block("1") + make_block("2") + [html.Div(id="log_all"), html.Button(id="btn_all")]) - @app.callback(Output(_id("sso", MATCH), "children"), - Input(_id("btn", MATCH), "n_clicks")) + @app.callback(Output(_id("sso", MATCH), "children"), Input(_id("btn", MATCH), "n_clicks")) def update_default(n_clicks): """ Populate serverside output ONE at a time, i.e. WRITE to SSO using MATCH. """ return Serverside(pd.DataFrame(columns=["A"], data=[n_clicks])) - @app.callback(Output(_id("sso", ALL), "children"), - Input("btn_all", "n_clicks")) + @app.callback(Output(_id("sso", ALL), "children"), Input("btn_all", "n_clicks")) def update_all(n_clicks): """ Populate serverside output ALL at once, i.e. WRITE to SSO using ALL. """ return tuple([Serverside(pd.DataFrame(columns=["B"], data=[n_clicks]))] * 2) - @app.callback(Output(_id("log", MATCH), "children"), - Input(_id("sso", MATCH), "children")) + @app.callback(Output(_id("log", MATCH), "children"), Input(_id("sso", MATCH), "children")) def update_log(data): """ Populate log elements ONE at a time, i.e. READ from SSO using MATCH. """ return data.to_json() - @app.callback(Output("log_all", "children"), - Input(_id("sso", ALL), "children")) + @app.callback(Output("log_all", "children"), Input(_id("sso", ALL), "children")) def update_log_all(data): """ Populate ALL log elements, i.e. READ from SSO using ALL. @@ -607,10 +784,18 @@ def update_log_all(data): @pytest.mark.parametrize( - 'args, kwargs', - [([Output("log_server", "children"), Input("btn", "n_clicks")], dict()), - ([], dict(output=[Output("log_server", "children")], - inputs=dict(n_clicks=Input("btn", "n_clicks"))))]) + "args, kwargs", + [ + ([Output("log_server", "children"), Input("btn", "n_clicks")], dict()), + ( + [], + dict( + output=[Output("log_server", "children")], + inputs=dict(n_clicks=Input("btn", "n_clicks")), + ), + ), + ], +) def test_log_transform(dash_duo, args, kwargs): app = _get_basic_dash_proxy(transforms=[LogTransform(try_use_mantine=False)]) @@ -628,18 +813,36 @@ def update_log(n_clicks, dash_logger: DashLogger): @pytest.mark.parametrize( - 'c_args, c_kwargs, f_args, f_kwargs', - [([Output("celsius", "value"), CycleBreakerInput("fahrenheit", "value")], dict(), - [Output("fahrenheit", "value"), Input("celsius", "value")], dict()), - ([], dict(output=Output("celsius", "value"), inputs=dict(value=CycleBreakerInput("fahrenheit", "value"))), - [], dict(output=Output("fahrenheit", "value"), inputs=dict(value=Input("celsius", "value")))) - ]) -def test_cycle_breaker_transform(dash_duo, c_args, c_kwargs, f_args, f_kwargs): + "c_args, c_kwargs, f_args, f_kwargs", + [ + ( + [Output("celsius", "value"), CycleBreakerInput("fahrenheit", "value")], + dict(), + [Output("fahrenheit", "value"), Input("celsius", "value")], + dict(), + ), + ( + [], + dict( + output=Output("celsius", "value"), + inputs=dict(value=CycleBreakerInput("fahrenheit", "value")), + ), + [], + dict( + output=Output("fahrenheit", "value"), + inputs=dict(value=Input("celsius", "value")), + ), + ), + ], +) +def test_cycle_breaker_transform(dash_duo, c_args, c_kwargs, f_args, f_kwargs): # noqa: C901 app = DashProxy(transforms=[CycleBreakerTransform()]) - app.layout = html.Div([ - dcc.Input(id="celsius", type="number"), - dcc.Input(id="fahrenheit", type="number"), - ]) + app.layout = html.Div( + [ + dcc.Input(id="celsius", type="number"), + dcc.Input(id="fahrenheit", type="number"), + ] + ) def validate_input(value) -> decimal: if value is None: @@ -659,11 +862,7 @@ def update_fahrenheit(value): dash_duo.start_server(app) time.sleep(0.1) - logs = [ - entry - for entry in dash_duo.driver.get_log("browser") - if entry["timestamp"] > dash_duo._last_ts - ] + logs = [entry for entry in dash_duo.driver.get_log("browser") if entry["timestamp"] > dash_duo._last_ts] assert len(logs) <= int(os.environ.get("TEST_CYCLE_BREAKER_ALLOWED_ERRORS", "0")) f = dash_duo.find_element("#fahrenheit") f.send_keys("32") diff --git a/tests/test_javascript.py b/tests/test_javascript.py index d0e6885..593a24c 100644 --- a/tests/test_javascript.py +++ b/tests/test_javascript.py @@ -20,9 +20,9 @@ def test_namespace(): os.remove(asset_path) # Check how the variable looks. ptl = assign(js_func) - assert ptl == {'variable': 'dashExtensions.default.function0'} + assert ptl == {"variable": "dashExtensions.default.function0"} # Check that assets are written. - with open(asset_path, 'r') as f: + with open(asset_path, "r") as f: assets_content = f.read() assert assets_content == expected