diff --git a/doc/source/modules.rst b/doc/source/modules.rst new file mode 100644 index 00000000..12835237 --- /dev/null +++ b/doc/source/modules.rst @@ -0,0 +1,70 @@ +Developer Documentation +======================= + +.. toctree:: + :maxdepth: 1 + + ixmp4.core/modules + ixmp4.data/modules + ixmp4.server/modules + ixmp4.cli + ixmp4.db + ixmp4.db.utils + ixmp4.conf + tests + + +Package/Folder Structure +------------------------ + +.. code:: bash + + . + ├── ixmp4 + │ ├── cli # cli + │ ├── conf # configuration module, loads settings etc. + │ ├── core # contains the facade layer for the core python API + │ ├── data + │ │ ├── abstract # ABCs for data source models and repositories + │ │ ├── api # data source implementation for the web api + │ │ ├── backend # data source backends + │ │ └── db # data source implementation for databases (sqlalchemy) + │ ├── db # database management + │ ├── server # web application server + │ └── rest # REST endpoints + ├── run # runtime artifacts + └── tests # tests + +Architecture +------------ + +ixmp4 provides a Python API, a REST API and a compatibility layer for Postgres and SQLite Databases. +The Python API can interact with databases directly or use the REST API of a compatible ixmp4 server instance. + +:: + + -> calls -> + Web or SQL + Platform Backend Server SQL Backend + │ ┌────────────┐ ┌───────────┐ ┌─ │ ┌──────────┐ ┌───────────┐ ─┐ │ ┌─┐ + P │ │ │ │ │ │ │ │ │ │ │ │ S │ │ │ + y │ │ ┌────────┐ │ │ ┌───────┐ │ │ R │ │ ┌──────┐ │ │ ┌───────┐ │ │ Q │ │D│ + t │ │ │ │ │ │ │ │ │ ┌─┘ E │ │ │Endp. │ │ │ │ │ │ └─┐ L │ │a│ + h │ │ │Facade │ │ │ │Model │ │ │ S │ │ └──────┘ │ │ │Model │ │ │ A │ │t│ + o │ │ └────────┘ │ │ ├───────┤ │ │ T │ │ │ │ ├───────┤ │ │ l │ │a│ + n │ │ │ │ ├───────┤ │ │ │ │ ┌──────┐ │ │ ├───────┤ │ │ c │ │b│ + │ │ ... │ │ │ │ │ │ A │ │ │Endp. │ │ │ │ │ │ │ h │ │a│ + A │ │ │ │ │Repo. │ │ └─┐ P │ │ └──────┘ │ │ │Repo. │ │ ┌─┘ e │ │s│ + P │ │ │ │ └───────┘ │ │ I │ │ │ │ └───────┘ │ │ m │ │e│ + I │ │ │ │ ... │ │ │ │ ... │ │ ... │ │ y │ │ │ + │ └────────────┘ └───────────┘ └─ │ └──────────┘ └───────────┘ ─┘ │ └─┘ + + ixmp4.core ixmp4.data ixmp4.server ixmp4.data + +Note that a REST SDK in another programming language would have to implement only the +components before the bracketed part of the diagram (``ixmp4.data.api`` + optionally a facade layer). + +Overall both the “facade” layer and the “data source” layer are split +into “models” (representing a row in a database or a json object) and +“repositories” (representing a database table or a collection of REST +endpoints) which manage these models. diff --git a/doc/source/tests.rst b/doc/source/tests.rst new file mode 100644 index 00000000..75746b23 --- /dev/null +++ b/doc/source/tests.rst @@ -0,0 +1,82 @@ +Tests +===== + +Run tests with the CLI for a default configuration: + +.. code:: bash + + ixmp4 test [--with-backend] [--with-benchmarks] + +Unfortunately, since you are using ixmp4 to execute the tests, global statements are not +included in the coverage calculations. To circumvent this, use the ``--dry`` parameter. + +.. code:: bash + + ixmp4 test --with-backend --dry + # -> pytest --cov-report xml:.coverage.xml --cov-report term --cov=ixmp4 -rsx --benchmark-skip + + eval $(ixmp4 test --with-backend --dry) + # -> executes pytest + +Alternatively, use ``pytest`` directly: + +.. code:: bash + + py.test + +Running tests with PostgreSQL +----------------------------- + +In order to run the local tests with PostgreSQL you'll need to have a local +instance of this database running. The easiest way to do this is using a docker +container. + +The docker container of the database needs to be started first and then the tests can be +run normally using pytest. If everything is working correctly, the tests for +PostgreSQL should not be skipped. + + +For PostgreSQL using the official `postgres `_ image +is recommended. Get the latest version on your local machine using (having docker +installed): + +.. code:: bash + + docker pull postgres + +and run the container with: + +.. code:: bash + + docker run -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=test -p 5432:5432 -d postgres + +please note that you'll have to wait for a few seconds for the databases to be up and +running. + +In case there are any error messages during the start up of the container along those lines: + +.. code:: bash + + ... Error response from daemon: driver failed programming external connectivity on + endpoint ... + Error starting userland proxy: listen tcp4 0.0.0.0:5432: bind: address already in + use. + +you have to find the process running on the port in question (in the above case 5432) +and kill it: + +.. code:: bash + + sudo ss -lptn 'sport = :5432' + sudo kill + +Profiling +--------- + +Some tests will output profiler information to the ``.profiles/`` +directory (using the ``profiled`` fixture). You can analyze these using +``snakeviz``. For example: + +.. code:: bash + + snakeviz .profiles/test_add_datapoints_full_benchmark.prof diff --git a/ixmp4/cli/platforms.py b/ixmp4/cli/platforms.py index 86d1312e..f46fb8a6 100644 --- a/ixmp4/cli/platforms.py +++ b/ixmp4/cli/platforms.py @@ -1,6 +1,6 @@ import re -from typing import Optional from pathlib import Path +from typing import Optional import typer @@ -12,7 +12,6 @@ from . import utils - app = typer.Typer() @@ -27,7 +26,7 @@ def validate_name(name: str): def validate_dsn(dsn: str | None): if dsn is None: return None - match = re.match(r"^(sqlite|postgresql|oracle|https|http)(\:\/\/)", dsn) + match = re.match(r"^(sqlite|postgresql|https|http)(\:\/\/)", dsn) if match is None: raise typer.BadParameter( "Platform dsn must be a valid URl or database connection string." diff --git a/ixmp4/conf/credentials.py b/ixmp4/conf/credentials.py index 1aaec0f8..f15b7b9b 100644 --- a/ixmp4/conf/credentials.py +++ b/ixmp4/conf/credentials.py @@ -1,6 +1,6 @@ from contextlib import suppress from pathlib import Path -import rtoml as toml +import toml class Credentials(object): diff --git a/ixmp4/conf/manager.py b/ixmp4/conf/manager.py index d5b118e4..ff093d73 100644 --- a/ixmp4/conf/manager.py +++ b/ixmp4/conf/manager.py @@ -101,7 +101,7 @@ def _request( params = hashabledict(params) if json is not None: - if type(json) == dict: + if type(json) is dict: json = hashabledict(json) else: json = tuple(json) diff --git a/ixmp4/conf/settings.py b/ixmp4/conf/settings.py index 376c9c95..c118b7ec 100644 --- a/ixmp4/conf/settings.py +++ b/ixmp4/conf/settings.py @@ -1,17 +1,18 @@ -import os import logging import logging.config -from typing import Literal +import os from pathlib import Path -from httpx import ConnectError +from typing import Literal -from pydantic import BaseSettings, Field, validator, HttpUrl, Extra +from httpx import ConnectError +from pydantic import BaseSettings, Extra, Field, HttpUrl, validator from ixmp4.core.exceptions import InvalidCredentials + +from .auth import AnonymousAuth, ManagerAuth from .credentials import Credentials -from .toml import TomlConfig from .manager import ManagerConfig -from .auth import ManagerAuth, AnonymousAuth +from .toml import TomlConfig from .user import local_user logger = logging.getLogger(__name__) @@ -105,9 +106,7 @@ def get_auth(self): self._default_auth = AnonymousAuth() def load_manager_config(self): - self._manager = ManagerConfig( - self.manager_url, self.default_auth, remote=True - ) + self._manager = ManagerConfig(self.manager_url, self.default_auth, remote=True) def load_toml_config(self): if self.default_auth is not None: diff --git a/ixmp4/conf/toml.py b/ixmp4/conf/toml.py index 46e462af..3df40ab0 100644 --- a/ixmp4/conf/toml.py +++ b/ixmp4/conf/toml.py @@ -1,6 +1,6 @@ from pathlib import Path from typing import Any -import rtoml as toml +import toml import json from ixmp4.core.exceptions import PlatformNotFound, PlatformNotUnique @@ -29,7 +29,6 @@ def load(self): def dump(self): obj = {} for c in self.platforms.values(): - # needed for rtoml to serialize `Path` objects dict_ = json.loads(c.json()) dict_.pop("user", None) name = dict_.pop("name") diff --git a/ixmp4/core/__init__.py b/ixmp4/core/__init__.py index c20970d5..55eb6bb2 100644 --- a/ixmp4/core/__init__.py +++ b/ixmp4/core/__init__.py @@ -1,8 +1,9 @@ # flake8: noqa +from .iamc.variable import Variable as Variable from .model import Model as Model -from .scenario import Scenario as Scenario -from .run import Run as Run +from .optimization.indexset import IndexSet as IndexSet +from .platform import Platform as Platform from .region import Region as Region +from .run import Run as Run +from .scenario import Scenario as Scenario from .unit import Unit as Unit -from .platform import Platform as Platform -from .iamc.variable import Variable as Variable diff --git a/ixmp4/core/iamc/data.py b/ixmp4/core/iamc/data.py index ac3e4bb5..0fa6ed84 100644 --- a/ixmp4/core/iamc/data.py +++ b/ixmp4/core/iamc/data.py @@ -5,11 +5,11 @@ from pandera.typing import Series from ixmp4.data.abstract import DataPoint as DataPointModel +from ixmp4.data.abstract import Run from ..base import BaseFacade -from .repository import IamcRepository -from ..run import RunModel as Run from ..utils import substitute_type +from .repository import IamcRepository def to_dimensionless(df: pd.DataFrame) -> pd.DataFrame: diff --git a/ixmp4/core/optimization/__init__.py b/ixmp4/core/optimization/__init__.py new file mode 100644 index 00000000..d13d3fde --- /dev/null +++ b/ixmp4/core/optimization/__init__.py @@ -0,0 +1 @@ +from .data import OptimizationData diff --git a/ixmp4/core/optimization/data.py b/ixmp4/core/optimization/data.py new file mode 100644 index 00000000..f620b125 --- /dev/null +++ b/ixmp4/core/optimization/data.py @@ -0,0 +1,21 @@ +from functools import partial + +from ixmp4.data.abstract import Run + +from ..base import BaseFacade +from .indexset import IndexSet as IndexSetModel +from .indexset import IndexSetRepository + + +class OptimizationData(BaseFacade): + """An optimization data instance, which provides access to optimization data such as + IndexSet, Table, Variable, etc.""" + + IndexSet: partial[IndexSetModel] + + indexsets: IndexSetRepository + + def __init__(self, *args, run: Run, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.IndexSet = partial(IndexSetModel, _backend=self.backend, _run=run) + self.indexsets = IndexSetRepository(_backend=self.backend, _run=run) diff --git a/ixmp4/core/optimization/indexset.py b/ixmp4/core/optimization/indexset.py new file mode 100644 index 00000000..4668e005 --- /dev/null +++ b/ixmp4/core/optimization/indexset.py @@ -0,0 +1,117 @@ +from datetime import datetime +from typing import ClassVar, Iterable + +import pandas as pd + +from ixmp4.core.base import BaseFacade, BaseModelFacade +from ixmp4.data.abstract import Docs as DocsModel +from ixmp4.data.abstract import IndexSet as IndexSetModel +from ixmp4.data.abstract import Run + + +class IndexSet(BaseModelFacade): + _model: IndexSetModel + _run: Run + NotFound: ClassVar = IndexSetModel.NotFound + NotUnique: ClassVar = IndexSetModel.NotUnique + + def __init__( + self, + name: str, + _run: Run, + **kwargs, + ) -> None: + super().__init__(**kwargs) + self._run = _run + if getattr(self, "_model", None) is None: + try: + self._model = self.backend.optimization.indexsets.get( + run_id=self._run.id, name=name + ) + # TODO: provide logging information if IndexSet already exists + except IndexSetModel.NotFound: + self._model = self.backend.optimization.indexsets.create( + run_id=self._run.id, + name=name, + ) + + @property + def id(self) -> int: + return self._model.id + + @property + def name(self) -> str: + return self._model.name + + @property + def elements(self) -> list[int | str]: + return self._model.elements + + def add(self, elements: int | list[int | str] | str) -> None: + """Adds elements to an existing IndexSet.""" + self.backend.optimization.indexsets.add_elements( + indexset_id=self._model.id, elements=elements + ) + self._model.elements = self.backend.optimization.indexsets.get( + run_id=self._run.id, name=self._model.name + ).elements + + @property + def run_id(self) -> int: + return self._run.id + + @property + def created_at(self) -> datetime | None: + return self._model.created_at + + @property + def created_by(self) -> str | None: + return self._model.created_by + + @property + def docs(self): + try: + return self.backend.optimization.indexsets.docs.get(self.id).description + except DocsModel.NotFound: + return None + + @docs.setter + def docs(self, description): + if description is None: + self.backend.optimization.indexsets.docs.delete(self.id) + else: + self.backend.optimization.indexsets.docs.set(self.id, description) + + @docs.deleter + def docs(self): + try: + self.backend.optimization.indexsets.docs.delete(self.id) + # TODO: silently failing + except DocsModel.NotFound: + return None + + def __str__(self) -> str: + return f"" + + +class IndexSetRepository(BaseFacade): + _run: Run + + def __init__(self, _run: Run, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self._run = _run + + def list(self, name: str | None = None) -> Iterable[IndexSet]: + indexsets = self.backend.optimization.indexsets.list(name=name) + return [ + IndexSet( + _backend=self.backend, + _model=i, + _run=self._run, + name=i.name, + ) + for i in indexsets + ] + + def tabulate(self, name: str | None = None) -> pd.DataFrame: + return self.backend.optimization.indexsets.tabulate(name=name) diff --git a/ixmp4/core/run.py b/ixmp4/core/run.py index ef8bd6a2..be664921 100644 --- a/ixmp4/core/run.py +++ b/ixmp4/core/run.py @@ -1,11 +1,13 @@ -from typing import Iterable, ClassVar from collections import UserDict +from typing import ClassVar, Iterable import pandas as pd from ixmp4.data.abstract import Run as RunModel -from .base import BaseModelFacade, BaseFacade + +from .base import BaseFacade, BaseModelFacade from .iamc import IamcData +from .optimization import OptimizationData class Run(BaseModelFacade): @@ -41,6 +43,7 @@ def __init__( self.iamc = IamcData(_backend=self.backend, run=self._model) self._meta = RunMetaFacade(_backend=self.backend, run=self._model) + self.optimization = OptimizationData(_backend=self.backend, run=self._model) @property def model(self): diff --git a/ixmp4/data/abstract/__init__.py b/ixmp4/data/abstract/__init__.py index 1d1a4128..9fa84486 100644 --- a/ixmp4/data/abstract/__init__.py +++ b/ixmp4/data/abstract/__init__.py @@ -5,35 +5,32 @@ # flake8: noqa from .base import ( - BaseModel, BaseMeta, - Retriever, + BaseModel, + BulkDeleter, + BulkUpserter, Creator, Deleter, + Enumerator, Lister, + Retriever, Tabulator, - Enumerator, - BulkUpserter, - BulkDeleter, ) -from .model import Model, ModelRepository -from .run import Run, RunRepository -from .meta import RunMetaEntry, RunMetaEntryRepository, StrictMetaValue, MetaValue -from .scenario import Scenario, ScenarioRepository -from .unit import Unit, UnitRepository -from .region import Region, RegionRepository from .docs import Docs, DocsRepository - -from .iamc import ( - Variable, - VariableRepository, +from .iamc import ( # AnnualDataPoint,; SubAnnualDataPoint,; CategoricalDataPoint, + DataPoint, + DataPointRepository, Measurand, MeasurandRepository, TimeSeries, TimeSeriesRepository, - DataPoint, - # AnnualDataPoint, - # SubAnnualDataPoint, - # CategoricalDataPoint, - DataPointRepository, + Variable, + VariableRepository, ) +from .meta import MetaValue, RunMetaEntry, RunMetaEntryRepository, StrictMetaValue +from .model import Model, ModelRepository +from .optimization import IndexSet, IndexSetRepository +from .region import Region, RegionRepository +from .run import Run, RunRepository +from .scenario import Scenario, ScenarioRepository +from .unit import Unit, UnitRepository diff --git a/ixmp4/data/abstract/iamc/variable.py b/ixmp4/data/abstract/iamc/variable.py index ab41ea9c..9e8b0370 100644 --- a/ixmp4/data/abstract/iamc/variable.py +++ b/ixmp4/data/abstract/iamc/variable.py @@ -1,9 +1,11 @@ -from typing import Protocol, Iterable +from typing import Iterable, Protocol import pandas as pd + from ixmp4.data import types -from ..docs import DocsRepository + from .. import base +from ..docs import DocsRepository class Variable(base.BaseModel, Protocol): @@ -39,7 +41,7 @@ def create(self, name: str) -> Variable: Raises ------ - :class:`ixmp4.core.exceptions.VariableNotUnique`: + :class:`ixmp4.data.abstract.Variable.NotUnique`: If the variable with `name` is not unique. Returns diff --git a/ixmp4/data/abstract/optimization/__init__.py b/ixmp4/data/abstract/optimization/__init__.py new file mode 100644 index 00000000..b02e3205 --- /dev/null +++ b/ixmp4/data/abstract/optimization/__init__.py @@ -0,0 +1 @@ +from .indexset import IndexSet, IndexSetRepository diff --git a/ixmp4/data/abstract/optimization/indexset.py b/ixmp4/data/abstract/optimization/indexset.py new file mode 100644 index 00000000..f905a25b --- /dev/null +++ b/ixmp4/data/abstract/optimization/indexset.py @@ -0,0 +1,137 @@ +from typing import Iterable, List, Protocol + +import pandas as pd + +from ixmp4.data import types + +from .. import base +from ..docs import DocsRepository + + +class IndexSet(base.BaseModel, Protocol): + """IndexSet data model.""" + + name: types.String + """Unique name of the IndexSet.""" + + elements: types.JsonList + """Unique list of str or int.""" + + created_at: types.DateTime + "Creation date/time. TODO" + created_by: types.String + "Creator. TODO" + + def __str__(self) -> str: + return f"" + + +class IndexSetRepository( + base.Creator, + base.Retriever, + base.Enumerator, + Protocol, +): + docs: DocsRepository + + def create(self, run_id: int, name: str) -> IndexSet: + """Creates an IndexSet. + + Parameters + ---------- + run_id : int + The id of the :class:`ixmp4.data.abstract.Run` for which this IndexSet is defined. + name : str + The name of the IndexSet. + + Raises + ------ + :class:`ixmp4.data.abstract.IndexSet.NotUnique`: + If the IndexSet with `name` already exists. + + Returns + ------- + :class:`ixmp4.data.abstract.IndexSet`: + The created IndexSet. + """ + ... + + def get(self, run_id: int, name: str) -> IndexSet: + """Retrieves an IndexSet. + + Parameters + ---------- + run_id : int + The id of the :class:`ixmp4.data.abstract.Run` for which this IndexSet is defined. + name : str + The unique name of the IndexSet. + + Raises + ------ + :class:`ixmp4.data.abstract.IndexSet.NotFound`: + If the IndexSet with `name` does not exist. + + Returns + ------- + :class:`ixmp4.data.abstract.IndexSet`: + The retrieved IndexSet. + """ + ... + + def list(self, *, name: str | None = None, **kwargs) -> Iterable[IndexSet]: + """Lists IndexSets by specified criteria. + + Parameters + ---------- + name : str + The name of an IndexSet. If supplied only one result will be returned. + # TODO: Update kwargs + **kwargs: any + More filter parameters as specified in `ixmp4.data.db.iamc.variable.filters.VariableFilter`. + + Returns + ------- + Iterable[:class:`ixmp4.data.abstract.IndexSet`]: + List of IndexSets. + """ + ... + + def tabulate(self, *, name: str | None = None, **kwargs) -> pd.DataFrame: + """Tabulate IndexSets by specified criteria. + + Parameters + ---------- + name : str + The name of an IndexSet. If supplied only one result will be returned. + # TODO: Update kwargs + **kwargs: any + More filter parameters as specified in `ixmp4.data.db.iamc.variable.filters.VariableFilter`. + + Returns + ------- + :class:`pandas.DataFrame`: + A data frame with the columns: + - id + - name + - elements + """ + ... + + def add_elements( + self, indexset_id: int, elements: int | List[int | str] | str + ) -> None: + """Adds elements to an existing IndexSet. + + Parameters + ---------- + indexset_id : int + The id of the target IndexSet. + elements : int | List[int | str] | str + The elements to be added to the IndexSet. + + Returns + ------- + None: + Due to compatibility with ixmp. + """ + ... diff --git a/ixmp4/data/abstract/run.py b/ixmp4/data/abstract/run.py index 9e45af05..df093bd9 100644 --- a/ixmp4/data/abstract/run.py +++ b/ixmp4/data/abstract/run.py @@ -1,8 +1,8 @@ -from typing import Protocol, Iterable, ClassVar +from typing import ClassVar, Iterable, Protocol import pandas as pd -from ixmp4.core.exceptions import NoDefaultRunVersion, IxmpError +from ixmp4.core.exceptions import IxmpError, NoDefaultRunVersion from ixmp4.data import types from . import base @@ -108,7 +108,7 @@ def get_or_create( Returns ------- - :class:`ixmp4..data.abstract.Run`: + :class:`ixmp4.data.abstract.Run`: The retrieved or created run. """ try: @@ -161,7 +161,7 @@ def list( Returns ------- - Iterable[:class:`ixmp4..data.abstract.Run`]: + Iterable[:class:`ixmp4.data.abstract.Run`]: List of runs. """ ... diff --git a/ixmp4/data/api/__init__.py b/ixmp4/data/api/__init__.py index bcf82702..e24ada49 100644 --- a/ixmp4/data/api/__init__.py +++ b/ixmp4/data/api/__init__.py @@ -1,25 +1,19 @@ # flake8: noqa from .base import BaseModel, DataFrame - -from .run import Run, RunRepository -from .meta import RunMetaEntry, RunMetaEntryRepository -from .unit import Unit, UnitRepository -from .region import Region, RegionParent, RegionRepository -from .scenario import Scenario, ScenarioRepository -from .model import Model, ModelRepository from .docs import Docs, DocsRepository - -from .iamc import ( - Variable, - VariableRepository, - # Measurand, - # MeasurandRepository, - TimeSeries, - TimeSeriesRepository, +from .iamc import ( # Measurand,; MeasurandRepository,; AnnualDataPoint,; SubAnnualDataPoint,; CategoricalDataPoint, DataPoint, - # AnnualDataPoint, - # SubAnnualDataPoint, - # CategoricalDataPoint, DataPointRepository, + TimeSeries, + TimeSeriesRepository, + Variable, + VariableRepository, ) +from .meta import RunMetaEntry, RunMetaEntryRepository +from .model import Model, ModelRepository +from .optimization import IndexSet, IndexSetRepository +from .region import Region, RegionParent, RegionRepository +from .run import Run, RunRepository +from .scenario import Scenario, ScenarioRepository +from .unit import Unit, UnitRepository diff --git a/ixmp4/data/api/base.py b/ixmp4/data/api/base.py index e4ea1396..c2a0155c 100644 --- a/ixmp4/data/api/base.py +++ b/ixmp4/data/api/base.py @@ -1,24 +1,15 @@ -from typing import ( - Mapping, - Sequence, - Iterable, - Type, - ClassVar, - TypeVar, - Generic, - Any, -) from json.decoder import JSONDecodeError +from typing import Any, ClassVar, Generic, Iterable, Mapping, Sequence, Type, TypeVar import httpx import pandas as pd from pydantic import BaseModel as PydanticBaseModel from ixmp4.core.exceptions import ( - registry, ImproperlyConfigured, - UnknownApiError, IxmpError, + UnknownApiError, + registry, ) @@ -175,10 +166,10 @@ def get(self, *args, **kwargs) -> ModelType: try: [obj] = list_ - except ValueError: + except ValueError as e: raise self.model_class.NotFound( f"Expected exactly one result, got {len(list_)} instead." - ) + ) from e return self.model_class(**obj) diff --git a/ixmp4/data/api/iamc/variable.py b/ixmp4/data/api/iamc/variable.py index ccd8f75f..9a78024e 100644 --- a/ixmp4/data/api/iamc/variable.py +++ b/ixmp4/data/api/iamc/variable.py @@ -1,12 +1,12 @@ -from typing import Iterable, ClassVar from datetime import datetime +from typing import ClassVar, Iterable import pandas as pd from ixmp4.data import abstract -from ..docs import Docs, DocsRepository from .. import base +from ..docs import Docs, DocsRepository class Variable(base.BaseModel): @@ -23,9 +23,7 @@ class Variable(base.BaseModel): class VariableDocsRepository(DocsRepository): model_class = Docs - prefix = ( - "docs/iamc/variables/" # TODO: what does this do that the below prefix doesn't? - ) + prefix = "docs/iamc/variables/" class VariableRepository( diff --git a/ixmp4/data/api/optimization/__init__.py b/ixmp4/data/api/optimization/__init__.py new file mode 100644 index 00000000..b02e3205 --- /dev/null +++ b/ixmp4/data/api/optimization/__init__.py @@ -0,0 +1 @@ +from .indexset import IndexSet, IndexSetRepository diff --git a/ixmp4/data/api/optimization/indexset.py b/ixmp4/data/api/optimization/indexset.py new file mode 100644 index 00000000..fb9f2649 --- /dev/null +++ b/ixmp4/data/api/optimization/indexset.py @@ -0,0 +1,71 @@ +from datetime import datetime +from typing import ClassVar, Iterable, List + +import pandas as pd +from pydantic import StrictInt, StrictStr + +from ixmp4.data import abstract + +from .. import base +from ..docs import Docs, DocsRepository + + +class IndexSet(base.BaseModel): + NotFound: ClassVar = abstract.IndexSet.NotFound + NotUnique: ClassVar = abstract.IndexSet.NotUnique + DeletionPrevented: ClassVar = abstract.IndexSet.DeletionPrevented + + id: int + name: str + elements: StrictInt | list[StrictInt | StrictStr] | StrictStr | None + run__id: int + + created_at: datetime | None + created_by: str | None + + +class IndexSetDocsRepository(DocsRepository): + model_class = Docs + prefix = "docs/optimization/indexsets/" + + +class IndexSetRepository( + base.Creator[IndexSet], + base.Retriever[IndexSet], + base.Enumerator[IndexSet], + abstract.IndexSetRepository, +): + model_class = IndexSet + prefix = "optimization/indexsets/" + enumeration_method = "PATCH" + + def __init__(self, client, *args, **kwargs) -> None: + super().__init__(client, *args, **kwargs) + self.docs = IndexSetDocsRepository(self.client) + + def create( + self, + run_id: int, + name: str, + ) -> IndexSet: + return super().create(run_id=run_id, name=name) + + def get(self, run_id: int, name: str) -> IndexSet: + return super().get(name=name, run_id=run_id) + + def list(self, *args, **kwargs) -> Iterable[IndexSet]: + return super().list(*args, **kwargs) + + def tabulate(self, *args, **kwargs) -> pd.DataFrame: + return super().tabulate(*args, **kwargs) + + def enumerate(self, *args, **kwargs) -> Iterable[IndexSet] | pd.DataFrame: + return super().enumerate(*args, **kwargs) + + def add_elements( + self, + indexset_id: int, + elements: StrictInt | List[StrictInt | StrictStr] | StrictStr, + ) -> None: + kwargs = {"indexset_id": indexset_id, "elements": elements} + self._request("PATCH", self.prefix + str(indexset_id) + "/", json=kwargs) diff --git a/ixmp4/data/backend/api.py b/ixmp4/data/backend/api.py index ac85988b..dde7b87b 100644 --- a/ixmp4/data/backend/api.py +++ b/ixmp4/data/backend/api.py @@ -1,25 +1,27 @@ import logging + import httpx import pandas as pd from fastapi.testclient import TestClient -from ixmp4.core.exceptions import UnknownApiError, ImproperlyConfigured -from ixmp4.conf.auth import BaseAuth, SelfSignedAuth, User from ixmp4.conf import settings -from ixmp4.conf.manager import MockManagerConfig, ManagerPlatformInfo, PlatformInfo +from ixmp4.conf.auth import BaseAuth, SelfSignedAuth, User +from ixmp4.conf.manager import ManagerPlatformInfo, MockManagerConfig, PlatformInfo +from ixmp4.core.exceptions import ImproperlyConfigured, UnknownApiError from ixmp4.data.api import ( DataPointRepository, - RunRepository, + IndexSetRepository, + ModelRepository, RunMetaEntryRepository, - TimeSeriesRepository, + RunRepository, ScenarioRepository, - ModelRepository, + TimeSeriesRepository, VariableRepository, ) -from ixmp4.data.api.unit import UnitRepository from ixmp4.data.api.region import RegionRepository +from ixmp4.data.api.unit import UnitRepository from ixmp4.server import app, v1 -from ixmp4.server.rest import deps, APIInfo +from ixmp4.server.rest import APIInfo, deps from .base import Backend @@ -62,9 +64,11 @@ def get_auth(self, rest_url: str, override_auth: BaseAuth | None) -> BaseAuth: logger.debug("Server UTC Time: " + api_info.utcnow.strftime("%c")) logger.debug("Server Is Managed: " + str(api_info.is_managed)) if api_info.manager_url is not None: - logger.debug("Server Manager URL: " + api_info.manager_url) - - if api_info.manager_url != settings.manager_url and api_info.is_managed: + if ( + api_info.manager_url.rstrip("/") != settings.manager_url.rstrip("/") + and api_info.is_managed + ): + logger.error("Server Manager URL: " + api_info.manager_url) logger.error("Local Manager URL: " + settings.manager_url) raise ImproperlyConfigured( "Trying to connect to a managed REST Platform " @@ -84,14 +88,15 @@ def get_auth(self, rest_url: str, override_auth: BaseAuth | None) -> BaseAuth: return override_auth def create_repositories(self): - self.runs = RunRepository(self.client) - self.meta = RunMetaEntryRepository(self.client) self.iamc.datapoints = DataPointRepository(self.client) self.iamc.timeseries = TimeSeriesRepository(self.client) self.iamc.variables = VariableRepository(self.client) + self.meta = RunMetaEntryRepository(self.client) + self.models = ModelRepository(self.client) + self.optimization.indexsets = IndexSetRepository(self.client) self.regions = RegionRepository(self.client) + self.runs = RunRepository(self.client) self.scenarios = ScenarioRepository(self.client) - self.models = ModelRepository(self.client) self.units = UnitRepository(self.client) diff --git a/ixmp4/data/backend/base.py b/ixmp4/data/backend/base.py index 1ef4382a..8129c5f7 100644 --- a/ixmp4/data/backend/base.py +++ b/ixmp4/data/backend/base.py @@ -1,13 +1,14 @@ from ixmp4.conf.base import PlatformInfo from ixmp4.data.abstract import ( DataPointRepository, - RunRepository, + IndexSetRepository, + ModelRepository, + RegionRepository, RunMetaEntryRepository, + RunRepository, + ScenarioRepository, TimeSeriesRepository, UnitRepository, - RegionRepository, - ScenarioRepository, - ModelRepository, VariableRepository, ) @@ -18,16 +19,22 @@ class IamcSubobject(object): variables: VariableRepository +class OptimizationSubobject(object): + indexsets: IndexSetRepository + + class Backend(object): + iamc: IamcSubobject info: PlatformInfo - runs: RunRepository meta: RunMetaEntryRepository + models: ModelRepository + optimization: OptimizationSubobject regions: RegionRepository - units: UnitRepository + runs: RunRepository scenarios: ScenarioRepository - models: ModelRepository - iamc: IamcSubobject + units: UnitRepository def __init__(self, info: PlatformInfo) -> None: self.info = info self.iamc = IamcSubobject() + self.optimization = OptimizationSubobject() diff --git a/ixmp4/data/backend/db.py b/ixmp4/data/backend/db.py index 27645b43..2d799ef7 100644 --- a/ixmp4/data/backend/db.py +++ b/ixmp4/data/backend/db.py @@ -1,26 +1,27 @@ import logging -from typing import Generator from contextlib import contextmanager from functools import lru_cache +from typing import Generator -from sqlalchemy.engine import create_engine, Engine +from sqlalchemy.engine import Engine, create_engine from sqlalchemy.orm.session import sessionmaker from sqlalchemy.pool import StaticPool -from ixmp4.core.exceptions import ProgrammingError from ixmp4.conf.base import PlatformInfo -from ixmp4.conf.user import User from ixmp4.conf.manager import ManagerConfig, ManagerPlatformInfo +from ixmp4.conf.user import User +from ixmp4.core.exceptions import ProgrammingError from ixmp4.data.db import ( BaseModel, DataPointRepository, - RunRepository, + IndexSetRepository, + ModelRepository, + RegionRepository, RunMetaEntryRepository, + RunRepository, + ScenarioRepository, TimeSeriesRepository, UnitRepository, - RegionRepository, - ScenarioRepository, - ModelRepository, VariableRepository, ) @@ -46,21 +47,22 @@ def __init__(self, info: PlatformInfo) -> None: self.make_engine(info.dsn) self.make_repositories() + def make_engine(self, dsn: str): + self.engine = cached_create_engine(dsn) + self.session = self.Session(bind=self.engine) + def make_repositories(self): - self.runs = RunRepository(self) - self.meta = RunMetaEntryRepository(self) self.iamc.datapoints = DataPointRepository(self) self.iamc.timeseries = TimeSeriesRepository(self) self.iamc.variables = VariableRepository(self) + self.meta = RunMetaEntryRepository(self) + self.models = ModelRepository(self) + self.optimization.indexsets = IndexSetRepository(self) self.regions = RegionRepository(self) + self.runs = RunRepository(self) self.scenarios = ScenarioRepository(self) - self.models = ModelRepository(self) self.units = UnitRepository(self) - def make_engine(self, dsn: str): - self.engine = cached_create_engine(dsn) - self.session = self.Session(bind=self.engine) - def close(self): self.session.close() @@ -120,16 +122,3 @@ def __init__(self, *args, **kwargs) -> None: **kwargs, ) self.reset() - - -class OracleTestBackend(SqlAlchemyBackend): - def __init__(self, *args, **kwargs) -> None: - super().__init__( - PlatformInfo( - name="oracle-test", - dsn="oracle+oracledb://ixmp4_test:ixmp4_test@localhost:1521?service_name=XEPDB1", - ), - *args, - **kwargs, - ) - self.reset() diff --git a/ixmp4/data/db/__init__.py b/ixmp4/data/db/__init__.py index 983cfab6..78f1bbfb 100644 --- a/ixmp4/data/db/__init__.py +++ b/ixmp4/data/db/__init__.py @@ -4,25 +4,22 @@ # flake8: noqa from .base import BaseModel, BaseRepository -from .unit import Unit, UnitRepository -from .region import Region, RegionRepository -from .iamc import ( - Variable, - VariableRepository, - TimeSeriesRepository, - TimeSeries, +from .docs import BaseDocsRepository, docs_model +from .iamc import ( # AnnualDataPoint,; SubAnnualDataPoint,; CategoricalDataPoint, + DataPoint, + DataPointRepository, Measurand, MeasurandRepository, - DataPoint, + TimeSeries, + TimeSeriesRepository, UniversalDataPoint, - OracleDataPoint, - # AnnualDataPoint, - # SubAnnualDataPoint, - # CategoricalDataPoint, - DataPointRepository, + Variable, + VariableRepository, ) +from .meta import RunMetaEntry, RunMetaEntryRepository from .model import Model, ModelRepository +from .optimization import IndexSet, IndexSetRepository +from .region import Region, RegionRepository from .run import Run, RunRepository -from .meta import RunMetaEntry, RunMetaEntryRepository from .scenario import Scenario, ScenarioRepository -from .docs import docs_model, BaseDocsRepository +from .unit import Unit, UnitRepository diff --git a/ixmp4/data/db/base.py b/ixmp4/data/db/base.py index c0d6a6b4..d616d1c9 100644 --- a/ixmp4/data/db/base.py +++ b/ixmp4/data/db/base.py @@ -1,50 +1,36 @@ +import sqlite3 +from datetime import datetime from typing import ( + TYPE_CHECKING, Any, + ClassVar, + Generic, Iterable, Iterator, Tuple, - Generic, TypeVar, - ClassVar, - TYPE_CHECKING, ) -from datetime import datetime -from sqlalchemy.engine.interfaces import Dialect +import dask.dataframe as dd +import numpy as np +import pandas as pd +from sqlalchemy import event, text from sqlalchemy.engine import Engine +from sqlalchemy.engine.interfaces import Dialect from sqlalchemy.exc import IntegrityError, NoResultFound -from sqlalchemy.orm.session import Session -from sqlalchemy.sql.schema import ( - MetaData, - Identity, -) from sqlalchemy.ext.compiler import compiles - from sqlalchemy.orm import Bundle, DeclarativeBase, declared_attr -from sqlalchemy import event, text - -import sqlite3 - -import pandas as pd -import dask.dataframe as dd -import numpy as np +from sqlalchemy.orm.session import Session +from sqlalchemy.sql.schema import Identity, MetaData from ixmp4 import db -from ixmp4.db import filters +from ixmp4.core.exceptions import Forbidden, IxmpError, ProgrammingError from ixmp4.data import abstract, types -from ixmp4.core.exceptions import ProgrammingError, IxmpError, Forbidden +from ixmp4.db import filters if TYPE_CHECKING: from ixmp4.data.backend.db import SqlAlchemyBackend -convention = { - "ix": "ix_%(column_0_label)s", - "uq": "uq_%(table_name)s_%(column_0_N_name)s", - "ck": "ck_%(table_name)s_%(constraint_name)s", - "fk": "fk_%(table_name)s_%(column_0_N_name)s_%(referred_table_name)s", - "pk": "pk_%(table_name)s", -} - @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): @@ -82,7 +68,15 @@ def __str__(self): return self.__class__.__name__ -BaseModel.metadata = MetaData(naming_convention=convention) +BaseModel.metadata = MetaData( + naming_convention={ + "ix": "ix_%(column_0_label)s", + "uq": "uq_%(table_name)s_%(column_0_N_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + "fk": "fk_%(table_name)s_%(column_0_N_name)s_%(referred_table_name)s", + "pk": "pk_%(table_name)s", + } +) ModelType = TypeVar("ModelType", bound=BaseModel) @@ -252,8 +246,6 @@ class BulkOperator(Selecter[ModelType]): @property def max_list_length(self) -> int: - if self.dialect.name == "oracle": - return 1000 return 50_000 def tabulate( diff --git a/ixmp4/data/db/filters.py b/ixmp4/data/db/filters.py deleted file mode 100644 index 5d7f81d7..00000000 --- a/ixmp4/data/db/filters.py +++ /dev/null @@ -1,89 +0,0 @@ -from ixmp4.db import filters, utils - -from . import Run, Model, Scenario, Region, Unit, Variable, Measurand, TimeSeries - - -class ModelFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - name: filters.String - - class Config: - sqla_model = Model - - def join(self, exc, **kwargs): - return exc.join(Model, Run.model) - - -class ScenarioFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - name: filters.String - - class Config: - sqla_model = Scenario - - def join(self, exc, **kwargs): - return exc.join(Scenario, Run.scenario) - - -class RunFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - version: filters.Integer - default_only: filters.Boolean = filters.Field(True) - is_default: filters.Boolean - model: ModelFilter | None - scenario: ScenarioFilter | None - - class Config: - sqla_model = Run - - def filter_default_only(self, exc, c, v, **kwargs): - if v: - return exc.where(Run.is_default) - else: - return exc - - def join(self, exc, **kwargs): - if not utils.is_joined(exc, Run): - exc = exc.join(Run, TimeSeries.run) - return exc - - -class VariableFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - name: filters.String - - class Config: - sqla_model = Variable - - def join(self, exc, **kwargs): - if not utils.is_joined(exc, Measurand): - exc = exc.join(Measurand, TimeSeries.measurand) - exc = exc.join(Variable, Measurand.variable) - return exc - - -class UnitFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - name: filters.String - - class Config: - sqla_model = Unit - - def join(self, exc, **kwargs): - if not utils.is_joined(exc, Measurand): - exc = exc.join(Measurand, TimeSeries.measurand) - exc = exc.join(Unit, Measurand.unit) - return exc - - -class RegionFilter(filters.BaseFilter, metaclass=filters.FilterMeta): - id: filters.Id - name: filters.String - hierarchy: filters.String - - class Config: - sqla_model = Region - - def join(self, exc, **kwargs): - exc = exc.join(Region, TimeSeries.region) - return exc diff --git a/ixmp4/data/db/filters/__init__.py b/ixmp4/data/db/filters/__init__.py new file mode 100644 index 00000000..5470a174 --- /dev/null +++ b/ixmp4/data/db/filters/__init__.py @@ -0,0 +1,7 @@ +from .model import ModelFilter +from .optimizationindexset import OptimizationIndexSetFilter +from .region import RegionFilter +from .run import RunFilter +from .scenario import ScenarioFilter +from .unit import UnitFilter +from .variable import VariableFilter diff --git a/ixmp4/data/db/filters/model.py b/ixmp4/data/db/filters/model.py new file mode 100644 index 00000000..9b2ed510 --- /dev/null +++ b/ixmp4/data/db/filters/model.py @@ -0,0 +1,14 @@ +from ixmp4.db import filters + +from .. import Model, Run + + +class ModelFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + + class Config: + sqla_model = Model + + def join(self, exc, **kwargs): + return exc.join(Model, Run.model) diff --git a/ixmp4/data/db/filters/optimizationindexset.py b/ixmp4/data/db/filters/optimizationindexset.py new file mode 100644 index 00000000..78251bb4 --- /dev/null +++ b/ixmp4/data/db/filters/optimizationindexset.py @@ -0,0 +1,16 @@ +from ixmp4.db import filters + +from .. import IndexSet, Run + + +class OptimizationIndexSetFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + run__id: filters.Integer = filters.Field(alias="run_id") + + class Config: + sqla_model = IndexSet + + def join(self, exc, **kwargs): + exc = exc.join(Run, onclause=IndexSet.run__id == Run.id) + return exc diff --git a/ixmp4/data/db/filters/region.py b/ixmp4/data/db/filters/region.py new file mode 100644 index 00000000..6ca0ae0d --- /dev/null +++ b/ixmp4/data/db/filters/region.py @@ -0,0 +1,16 @@ +from ixmp4.db import filters + +from .. import Region, TimeSeries + + +class RegionFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + hierarchy: filters.String + + class Config: + sqla_model = Region + + def join(self, exc, **kwargs): + exc = exc.join(Region, TimeSeries.region) + return exc diff --git a/ixmp4/data/db/filters/run.py b/ixmp4/data/db/filters/run.py new file mode 100644 index 00000000..156c1451 --- /dev/null +++ b/ixmp4/data/db/filters/run.py @@ -0,0 +1,28 @@ +from ixmp4.db import filters, utils + +from .. import Run, TimeSeries +from .model import ModelFilter +from .scenario import ScenarioFilter + + +class RunFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + version: filters.Integer + default_only: filters.Boolean = filters.Field(True) + is_default: filters.Boolean + model: ModelFilter | None + scenario: ScenarioFilter | None + + class Config: + sqla_model = Run + + def filter_default_only(self, exc, c, v, **kwargs): + if v: + return exc.where(Run.is_default) + else: + return exc + + def join(self, exc, **kwargs): + if not utils.is_joined(exc, Run): + exc = exc.join(Run, TimeSeries.run) + return exc diff --git a/ixmp4/data/db/filters/scenario.py b/ixmp4/data/db/filters/scenario.py new file mode 100644 index 00000000..b9641d3b --- /dev/null +++ b/ixmp4/data/db/filters/scenario.py @@ -0,0 +1,14 @@ +from ixmp4.db import filters + +from .. import Run, Scenario + + +class ScenarioFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + + class Config: + sqla_model = Scenario + + def join(self, exc, **kwargs): + return exc.join(Scenario, Run.scenario) diff --git a/ixmp4/data/db/filters/unit.py b/ixmp4/data/db/filters/unit.py new file mode 100644 index 00000000..03149f66 --- /dev/null +++ b/ixmp4/data/db/filters/unit.py @@ -0,0 +1,17 @@ +from ixmp4.db import filters, utils + +from .. import Measurand, TimeSeries, Unit + + +class UnitFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + + class Config: + sqla_model = Unit + + def join(self, exc, **kwargs): + if not utils.is_joined(exc, Measurand): + exc = exc.join(Measurand, TimeSeries.measurand) + exc = exc.join(Unit, Measurand.unit) + return exc diff --git a/ixmp4/data/db/filters/variable.py b/ixmp4/data/db/filters/variable.py new file mode 100644 index 00000000..b5733ee9 --- /dev/null +++ b/ixmp4/data/db/filters/variable.py @@ -0,0 +1,17 @@ +from ixmp4.db import filters, utils + +from .. import Measurand, TimeSeries, Variable + + +class VariableFilter(filters.BaseFilter, metaclass=filters.FilterMeta): + id: filters.Id + name: filters.String + + class Config: + sqla_model = Variable + + def join(self, exc, **kwargs): + if not utils.is_joined(exc, Measurand): + exc = exc.join(Measurand, TimeSeries.measurand) + exc = exc.join(Variable, Measurand.variable) + return exc diff --git a/ixmp4/data/db/iamc/__init__.py b/ixmp4/data/db/iamc/__init__.py index 2d0447e7..dcd8ad77 100644 --- a/ixmp4/data/db/iamc/__init__.py +++ b/ixmp4/data/db/iamc/__init__.py @@ -1,13 +1,9 @@ # flaske8: noqa -from .variable import Variable, VariableRepository -from .timeseries import TimeSeries, TimeSeriesRepository -from .measurand import Measurand, MeasurandRepository -from .datapoint import ( +from .datapoint import ( # AnnualDataPoint,; SubAnnualDataPoint,; CategoricalDataPoint, DataPoint, - UniversalDataPoint, - OracleDataPoint, - # AnnualDataPoint, - # SubAnnualDataPoint, - # CategoricalDataPoint, DataPointRepository, + UniversalDataPoint, ) +from .measurand import Measurand, MeasurandRepository +from .timeseries import TimeSeries, TimeSeriesRepository +from .variable import Variable, VariableRepository diff --git a/ixmp4/data/db/iamc/datapoint/__init__.py b/ixmp4/data/db/iamc/datapoint/__init__.py index 733f6a96..edff1cdd 100644 --- a/ixmp4/data/db/iamc/datapoint/__init__.py +++ b/ixmp4/data/db/iamc/datapoint/__init__.py @@ -1,3 +1,3 @@ # flake8: noqa -from .model import DataPoint, UniversalDataPoint, OracleDataPoint, get_datapoint_model +from .model import DataPoint, UniversalDataPoint, get_datapoint_model from .repository import DataPointRepository diff --git a/ixmp4/data/db/iamc/datapoint/model.py b/ixmp4/data/db/iamc/datapoint/model.py index 1da84d79..c96fb91d 100644 --- a/ixmp4/data/db/iamc/datapoint/model.py +++ b/ixmp4/data/db/iamc/datapoint/model.py @@ -4,6 +4,7 @@ from ixmp4 import db from ixmp4.data import abstract + from .. import base @@ -44,20 +45,5 @@ def __tablename__(cls) -> str: ) -class OracleDataPoint(DataPoint): - @declared_attr.directive - def __tablename__(cls) -> str: - return "iamc_datapoint_oracle" - - __table_args__ = ( - db.UniqueConstraint( - "time_series__id", "step_year", "step_category", "step_datetime" - ), - ) - - def get_datapoint_model(session) -> type[DataPoint]: - if session.bind.dialect.name == "oracle": - return OracleDataPoint - else: - return UniversalDataPoint + return UniversalDataPoint diff --git a/ixmp4/data/db/iamc/datapoint/repository.py b/ixmp4/data/db/iamc/datapoint/repository.py index 518caa81..3562221e 100644 --- a/ixmp4/data/db/iamc/datapoint/repository.py +++ b/ixmp4/data/db/iamc/datapoint/repository.py @@ -1,32 +1,30 @@ -from typing import Iterable, Any - -from sqlalchemy import select -from sqlalchemy.orm import Bundle +from typing import Any, Iterable import numpy as np import pandas as pd import pandera as pa from pandera.typing import DataFrame, Series +from sqlalchemy import select +from sqlalchemy.orm import Bundle from ixmp4 import db +from ixmp4.core.decorators import check_types +from ixmp4.core.exceptions import InconsistentIamcType, ProgrammingError from ixmp4.data import abstract from ixmp4.data.auth.decorators import guard -from ixmp4.data.db.unit import Unit -from ixmp4.data.db.region import Region -from ixmp4.data.db.run import RunRepository, Run from ixmp4.data.db.model import Model +from ixmp4.data.db.region import Region +from ixmp4.data.db.run import Run, RunRepository from ixmp4.data.db.scenario import Scenario -from ixmp4.core.exceptions import InconsistentIamcType, ProgrammingError -from ixmp4.core.decorators import check_types +from ixmp4.data.db.unit import Unit -from ..timeseries import TimeSeriesRepository, TimeSeries -from ..variable import Variable -from ..measurand import Measurand from .. import base - -from .model import DataPoint -from .filter import DataPointFilter +from ..measurand import Measurand +from ..timeseries import TimeSeries, TimeSeriesRepository +from ..variable import Variable from . import get_datapoint_model +from .filter import DataPointFilter +from .model import DataPoint class RemoveDataPointFrameSchema(pa.SchemaModel): @@ -90,7 +88,7 @@ class DataPointRepository( def __init__(self, *args, **kwargs) -> None: backend, *_ = args # A different underlying database table - # needs to be used for oracle databases. + # needed to be used for oracle databases. self.model_class = get_datapoint_model(backend.session) self.timeseries = TimeSeriesRepository(*args, **kwargs) diff --git a/ixmp4/data/db/optimization/__init__.py b/ixmp4/data/db/optimization/__init__.py new file mode 100644 index 00000000..b02e3205 --- /dev/null +++ b/ixmp4/data/db/optimization/__init__.py @@ -0,0 +1 @@ +from .indexset import IndexSet, IndexSetRepository diff --git a/ixmp4/data/db/optimization/base.py b/ixmp4/data/db/optimization/base.py new file mode 100644 index 00000000..72aed4e1 --- /dev/null +++ b/ixmp4/data/db/optimization/base.py @@ -0,0 +1,18 @@ +# flake8: noqa +from ..base import BaseModel as RootBaseModel +from ..base import ( + BulkDeleter, + BulkUpserter, + Creator, + Deleter, + Enumerator, + Lister, + Retriever, + Selecter, + Tabulator, +) + + +class BaseModel(RootBaseModel): + __abstract__ = True + table_prefix = "optimization_" diff --git a/ixmp4/data/db/optimization/indexset/__init__.py b/ixmp4/data/db/optimization/indexset/__init__.py new file mode 100644 index 00000000..c6f1275f --- /dev/null +++ b/ixmp4/data/db/optimization/indexset/__init__.py @@ -0,0 +1,2 @@ +from .model import IndexSet +from .repository import IndexSetRepository diff --git a/ixmp4/data/db/optimization/indexset/docs.py b/ixmp4/data/db/optimization/indexset/docs.py new file mode 100644 index 00000000..db49e4a8 --- /dev/null +++ b/ixmp4/data/db/optimization/indexset/docs.py @@ -0,0 +1,8 @@ +from ixmp4.data.db.docs import BaseDocsRepository, docs_model + +from .model import IndexSet + + +class IndexSetDocsRepository(BaseDocsRepository): + model_class = docs_model(IndexSet) # IndexSetDocs + dimension_model_class = IndexSet diff --git a/ixmp4/data/db/optimization/indexset/filter.py b/ixmp4/data/db/optimization/indexset/filter.py new file mode 100644 index 00000000..dc929524 --- /dev/null +++ b/ixmp4/data/db/optimization/indexset/filter.py @@ -0,0 +1,14 @@ +from ixmp4.data.db import filters as base +from ixmp4.db import filters + + +class OptimizationIndexSetFilter( + base.OptimizationIndexSetFilter, metaclass=filters.FilterMeta +): + indexset: base.OptimizationIndexSetFilter | None + run: base.RunFilter | None = filters.Field( + default=base.RunFilter(id=None, version=None) + ) + + def join(self, exc, session=None): + return exc diff --git a/ixmp4/data/db/optimization/indexset/model.py b/ixmp4/data/db/optimization/indexset/model.py new file mode 100644 index 00000000..6f3f4c14 --- /dev/null +++ b/ixmp4/data/db/optimization/indexset/model.py @@ -0,0 +1,38 @@ +from typing import ClassVar + +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.orm import validates + +from ixmp4 import db +from ixmp4.data import types +from ixmp4.data.abstract import optimization as abstract + +from .. import base + + +class IndexSet(base.BaseModel): + NotFound: ClassVar = abstract.IndexSet.NotFound + NotUnique: ClassVar = abstract.IndexSet.NotUnique + DeletionPrevented: ClassVar = abstract.IndexSet.DeletionPrevented + + name: types.String = db.Column(db.String(255), nullable=False, unique=True) + elements: types.JsonList = db.Column(db.JsonType, nullable=False, default=[]) + + created_at: types.DateTime = db.Column(db.DateTime, nullable=True) + created_by: types.String = db.Column(db.String(255), nullable=True) + + @declared_attr + def run__id(cls): + return db.Column( + db.Integer, db.ForeignKey("run.id"), nullable=False, index=True + ) + + @validates("elements") + def validate_elements(self, key, value): + unique = set() + for element in value: + if element in unique: + raise ValueError(f"{element} already defined for IndexSet {self.name}!") + else: + unique.add(element) + return value diff --git a/ixmp4/data/db/optimization/indexset/repository.py b/ixmp4/data/db/optimization/indexset/repository.py new file mode 100644 index 00000000..f74eb91c --- /dev/null +++ b/ixmp4/data/db/optimization/indexset/repository.py @@ -0,0 +1,81 @@ +from typing import Iterable, List + +import pandas as pd + +from ixmp4 import db +from ixmp4.data.abstract import optimization as abstract +from ixmp4.data.auth.decorators import guard + +from .. import base +from .docs import IndexSetDocsRepository +from .model import IndexSet + + +class IndexSetRepository( + base.Creator[IndexSet], + base.Retriever[IndexSet], + base.Enumerator[IndexSet], + abstract.IndexSetRepository, +): + model_class = IndexSet + + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.docs = IndexSetDocsRepository(*args, **kwargs) + + from .filter import OptimizationIndexSetFilter + + self.filter_class = OptimizationIndexSetFilter + + def add(self, run_id: int, name: str) -> IndexSet: + indexset = IndexSet(run__id=run_id, name=name, **self.get_creation_info()) + self.session.add(indexset) + return indexset + + @guard("view") + def get(self, run_id: int, name: str) -> IndexSet: + exc = db.select(IndexSet).where( + (IndexSet.name == name) & (IndexSet.run__id == run_id) + ) + try: + return self.session.execute(exc).scalar_one() + except db.NoResultFound: + raise IndexSet.NotFound + + @guard("view") + def get_by_id(self, id: int) -> IndexSet: + obj = self.session.get(self.model_class, id) + + if obj is None: + raise IndexSet.NotFound(id=id) + + return obj + + @guard("edit") + def create(self, run_id: int, name: str, **kwargs) -> IndexSet: + return super().create(run_id=run_id, name=name, **kwargs) + + @guard("view") + def list(self, *args, **kwargs) -> Iterable[IndexSet]: + return super().list(*args, **kwargs) + + @guard("view") + def tabulate(self, *args, **kwargs) -> pd.DataFrame: + return super().tabulate(*args, **kwargs) + + @guard("edit") + def add_elements( + self, + indexset_id: int, + elements: int | List[int | str] | str, + ) -> None: + indexset = self.get_by_id(id=indexset_id) + if not isinstance(elements, list): + elements = [elements] + if indexset.elements is None: + indexset.elements = elements + else: + indexset.elements = indexset.elements + elements + + self.session.add(indexset) + self.session.commit() diff --git a/ixmp4/data/db/run/model.py b/ixmp4/data/db/run/model.py index 62b64fbe..667ee322 100644 --- a/ixmp4/data/db/run/model.py +++ b/ixmp4/data/db/run/model.py @@ -2,9 +2,10 @@ from ixmp4 import db from ixmp4.data import abstract, types - from ixmp4.data.db.model.model import Model +from ixmp4.data.db.optimization.indexset import IndexSet from ixmp4.data.db.scenario.model import Scenario + from .. import base @@ -37,5 +38,7 @@ class Run(base.BaseModel): foreign_keys=[scenario__id], ) + indexset: types.Mapped[list["IndexSet"]] = db.relationship() + version: types.Integer = db.Column(db.Integer, nullable=False) is_default: types.Boolean = db.Column(db.Boolean, default=False, nullable=False) diff --git a/ixmp4/data/db/unit/repository.py b/ixmp4/data/db/unit/repository.py index c50bf5e0..47cf622b 100644 --- a/ixmp4/data/db/unit/repository.py +++ b/ixmp4/data/db/unit/repository.py @@ -1,18 +1,15 @@ from typing import Iterable import pandas as pd - from sqlalchemy.exc import NoResultFound from ixmp4 import db from ixmp4.data import abstract from ixmp4.data.auth.decorators import guard -from ixmp4.core.exceptions import OperationNotSupported from .. import base - -from .model import Unit from .docs import UnitDocsRepository +from .model import Unit class UnitRepository( @@ -33,10 +30,6 @@ def __init__(self, *args, **kwargs) -> None: self.docs = UnitDocsRepository(*args, **kwargs) def add(self, name: str) -> Unit: - if self.dialect.name == "oracle" and name.strip() == "": - raise OperationNotSupported( - "On ORACLE databases an empty string is not allowed as a unit's name." - ) unit = Unit(name=name, **self.get_creation_info()) self.session.add(unit) return unit diff --git a/ixmp4/data/types.py b/ixmp4/data/types.py index f5160daf..0a1e6c78 100644 --- a/ixmp4/data/types.py +++ b/ixmp4/data/types.py @@ -1,12 +1,12 @@ from datetime import datetime +from typing import Any -from sqlalchemy.orm import ( - Mapped as Mapped, -) +from sqlalchemy.orm import Mapped as Mapped - -Integer = Mapped[int] -Float = Mapped[float] -String = Mapped[str] Boolean = Mapped[bool] DateTime = Mapped[datetime] +Float = Mapped[float] +Integer = Mapped[int] +JsonList = Mapped[list[int | str]] +JsonDict = Mapped[dict[str, Any]] +String = Mapped[str] diff --git a/ixmp4/db/__init__.py b/ixmp4/db/__init__.py index b82687b2..b269b435 100644 --- a/ixmp4/db/__init__.py +++ b/ixmp4/db/__init__.py @@ -35,29 +35,33 @@ # flake8: noqa from sqlalchemy import ( - sql, - UniqueConstraint, ForeignKey, - Sequence, Index, - select, - exists, + Sequence, + UniqueConstraint, delete, - update, - insert, + exists, func, + insert, or_, + select, + sql, + update, ) +from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import ( - relationship, - backref, + Relationship, Session, aliased, - Relationship, + backref, mapped_column, + relationship, ) from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.types import * + from . import utils Column = mapped_column +JsonType = JSON() +JsonType = JsonType.with_variant(JSONB(), "postgresql") diff --git a/ixmp4/db/filters.py b/ixmp4/db/filters.py index 978922a6..434c9e4f 100644 --- a/ixmp4/db/filters.py +++ b/ixmp4/db/filters.py @@ -1,9 +1,9 @@ -from typing import Iterable, Optional, Any +from typing import Any, Iterable, Optional -from pydantic import BaseModel, Field, Extra, ValidationError +from pydantic import BaseModel, Extra, Field, ValidationError from ixmp4 import db -from ixmp4.core.exceptions import ProgrammingError, BadFilterArguments +from ixmp4.core.exceptions import BadFilterArguments, ProgrammingError def exact(c, v): @@ -181,7 +181,7 @@ def __init__(self, **data: Any) -> None: try: super().__init__(**data) except ValidationError as e: - raise BadFilterArguments(model=e.model, errors=e.errors) + raise BadFilterArguments(model=e.model.__name__, errors=e.errors()) def join(self, exc: db.sql.Select, session=None) -> db.sql.Select: return exc diff --git a/ixmp4/db/migrations/versions/da1fba23f206_create_optimization_indexset_table.py b/ixmp4/db/migrations/versions/da1fba23f206_create_optimization_indexset_table.py new file mode 100644 index 00000000..c50a1bd3 --- /dev/null +++ b/ixmp4/db/migrations/versions/da1fba23f206_create_optimization_indexset_table.py @@ -0,0 +1,141 @@ +# type: ignore +"""Create optimization_indexset table + +Revision ID: da1fba23f206 +Revises: c71efc396d2b +Create Date: 2023-08-30 12:29:50.037072 + +""" +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# Revision identifiers, used by Alembic. +revision = "da1fba23f206" +down_revision = "c71efc396d2b" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "optimization_indexset", + sa.Column("name", sa.String(length=255), nullable=False), + sa.Column( + "elements", + sa.JSON().with_variant( + postgresql.JSONB(astext_type=sa.Text()), "postgresql" + ), + nullable=False, + ), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("created_by", sa.String(length=255), nullable=True), + sa.Column("run__id", sa.Integer(), nullable=False), + sa.Column( + "id", + sa.Integer(), + sa.Identity(always=False, on_null=True, start=1, increment=1), + nullable=False, + ), + sa.ForeignKeyConstraint( + ["run__id"], + ["run.id"], + name=op.f("fk_optimization_indexset_run__id_run"), + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_optimization_indexset")), + sa.UniqueConstraint("name", name=op.f("uq_optimization_indexset_name")), + ) + with op.batch_alter_table("optimization_indexset", schema=None) as batch_op: + batch_op.create_index( + batch_op.f("ix_optimization_indexset_run__id"), + ["run__id"], + unique=False, + ) + + op.create_table( + "optimization_indexset_docs", + sa.Column("description", sa.Text(), nullable=False), + sa.Column("dimension__id", sa.Integer(), nullable=True), + sa.Column( + "id", + sa.Integer(), + sa.Identity(always=False, on_null=True, start=1, increment=1), + nullable=False, + ), + sa.ForeignKeyConstraint( + ["dimension__id"], + ["optimization_indexset.id"], + name=op.f( + "fk_optimization_indexset_docs_dimension__id_optimization_indexset" + ), + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_optimization_indexset_docs")), + sa.UniqueConstraint( + "dimension__id", + name=op.f("uq_optimization_indexset_docs_dimension__id"), + ), + ) + with op.batch_alter_table("iamc_datapoint_oracle", schema=None) as batch_op: + batch_op.drop_index("ix_iamc_datapoint_oracle_step_category") + batch_op.drop_index("ix_iamc_datapoint_oracle_step_datetime") + batch_op.drop_index("ix_iamc_datapoint_oracle_step_year") + batch_op.drop_index("ix_iamc_datapoint_oracle_time_series__id") + batch_op.drop_index("ix_iamc_datapoint_oracle_type") + + op.drop_table("iamc_datapoint_oracle") + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "iamc_datapoint_oracle", + sa.Column("value", sa.FLOAT(), nullable=True), + sa.Column("type", sa.VARCHAR(length=255), nullable=False), + sa.Column("step_category", sa.VARCHAR(length=1023), nullable=True), + sa.Column("step_year", sa.INTEGER(), nullable=True), + sa.Column("step_datetime", sa.DATETIME(), nullable=True), + sa.Column("time_series__id", sa.INTEGER(), nullable=False), + sa.Column("id", sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint( + ["time_series__id"], + ["iamc_timeseries.id"], + name="fk_iamc_datapoint_oracle_time_series__id_iamc_timeseries", + ), + sa.PrimaryKeyConstraint("id", name="pk_iamc_datapoint_oracle"), + sa.UniqueConstraint( + "time_series__id", + "step_year", + "step_category", + "step_datetime", + name="uq_iamc_datapoint_oracle_time_series__id_step_year_step_category_step_datetime", + ), + ) + with op.batch_alter_table("iamc_datapoint_oracle", schema=None) as batch_op: + batch_op.create_index("ix_iamc_datapoint_oracle_type", ["type"], unique=False) + batch_op.create_index( + "ix_iamc_datapoint_oracle_time_series__id", + ["time_series__id"], + unique=False, + ) + batch_op.create_index( + "ix_iamc_datapoint_oracle_step_year", ["step_year"], unique=False + ) + batch_op.create_index( + "ix_iamc_datapoint_oracle_step_datetime", + ["step_datetime"], + unique=False, + ) + batch_op.create_index( + "ix_iamc_datapoint_oracle_step_category", + ["step_category"], + unique=False, + ) + + op.drop_table("optimization_indexset_docs") + with op.batch_alter_table("optimization_indexset", schema=None) as batch_op: + batch_op.drop_index(batch_op.f("ix_optimization_indexset_run__id")) + + op.drop_table("optimization_indexset") + # ### end Alembic commands ### diff --git a/ixmp4/db/utils/__init__.py b/ixmp4/db/utils/__init__.py index b0ac8cd5..22c4e646 100644 --- a/ixmp4/db/utils/__init__.py +++ b/ixmp4/db/utils/__init__.py @@ -1,6 +1,7 @@ from contextlib import suppress from sqlalchemy import sql, inspect from sqlalchemy.sql import ColumnCollection +from sqlalchemy.orm import Mapper from ixmp4.core.exceptions import ProgrammingError @@ -19,7 +20,7 @@ def is_joined(exc: sql.Select, model): def get_columns(model_class: type) -> ColumnCollection: - mapper = inspect(model_class) + mapper: Mapper | None = inspect(model_class) if mapper is not None: return mapper.selectable.columns else: diff --git a/ixmp4/server/rest/__init__.py b/ixmp4/server/rest/__init__.py index 767e5f16..d9aceaa7 100644 --- a/ixmp4/server/rest/__init__.py +++ b/ixmp4/server/rest/__init__.py @@ -1,25 +1,23 @@ from datetime import datetime -from fastapi import FastAPI, Request, Depends, Path -from fastapi.responses import JSONResponse +from fastapi import Depends, FastAPI, Path, Request from fastapi.encoders import jsonable_encoder from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse from ixmp4.conf import settings from ixmp4.core.exceptions import IxmpError -from . import unit, scenario, region, meta, run, model, docs, deps +from . import deps, docs, meta, model, region, run, scenario, unit from .base import BaseModel -from .iamc import ( - datapoint, - timeseries, - model as iamc_model, - scenario as iamc_scenario, - region as iamc_region, - variable as iamc_variable, - unit as iamc_unit, -) - +from .iamc import datapoint +from .iamc import model as iamc_model +from .iamc import region as iamc_region +from .iamc import scenario as iamc_scenario +from .iamc import timeseries +from .iamc import unit as iamc_unit +from .iamc import variable as iamc_variable +from .optimization import indexset v1 = FastAPI() @@ -31,20 +29,22 @@ allow_headers=["*"], ) -v1.include_router(run.router) -v1.include_router(meta.router) + v1.include_router(datapoint.router, prefix="/iamc") -v1.include_router(timeseries.router, prefix="/iamc") +v1.include_router(docs.router) v1.include_router(iamc_model.router, prefix="/iamc") v1.include_router(iamc_scenario.router, prefix="/iamc") v1.include_router(iamc_region.router, prefix="/iamc") v1.include_router(iamc_unit.router, prefix="/iamc") v1.include_router(iamc_variable.router, prefix="/iamc") +v1.include_router(indexset.router, prefix="/optimization") +v1.include_router(meta.router) +v1.include_router(model.router) v1.include_router(region.router) +v1.include_router(run.router) v1.include_router(scenario.router) -v1.include_router(model.router) +v1.include_router(timeseries.router, prefix="/iamc") v1.include_router(unit.router) -v1.include_router(docs.router) class APIInfo(BaseModel): diff --git a/ixmp4/server/rest/docs.py b/ixmp4/server/rest/docs.py index ca7a6e8a..a4211665 100644 --- a/ixmp4/server/rest/docs.py +++ b/ixmp4/server/rest/docs.py @@ -1,8 +1,10 @@ from fastapi import APIRouter, Depends, Path, Query -from ixmp4.data.backend import Backend + from ixmp4.data import api -from .base import BaseModel +from ixmp4.data.backend import Backend + from . import deps +from .base import BaseModel router: APIRouter = APIRouter( prefix="/docs", @@ -133,3 +135,27 @@ def delete_variables( backend: Backend = Depends(deps.get_backend), ): return backend.iamc.variables.docs.delete(dimension_id) + + +@router.get("/optimization/indexsets/", response_model=list[api.Docs]) +def list_indexsets( + dimension_id: int | None = Query(None), + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.docs.list(dimension_id=dimension_id) + + +@router.post("/optimization/indexsets/", response_model=api.Docs) +def set_indexsets( + docs: DocsInput, + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.docs.set(**docs.dict()) + + +@router.delete("/optimization/indexsets/{dimension_id}/") +def delete_indexsets( + dimension_id: int = Path(None), + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.docs.delete(dimension_id) diff --git a/ixmp4/server/rest/optimization/__init__.py b/ixmp4/server/rest/optimization/__init__.py new file mode 100644 index 00000000..a6e8f01e --- /dev/null +++ b/ixmp4/server/rest/optimization/__init__.py @@ -0,0 +1 @@ +from . import indexset diff --git a/ixmp4/server/rest/optimization/indexset.py b/ixmp4/server/rest/optimization/indexset.py new file mode 100644 index 00000000..c6ca14aa --- /dev/null +++ b/ixmp4/server/rest/optimization/indexset.py @@ -0,0 +1,69 @@ +from fastapi import APIRouter, Body, Depends, Query +from pydantic import StrictInt, StrictStr + +from ixmp4.data import api +from ixmp4.data.backend import Backend +from ixmp4.data.db.filters.optimizationindexset import OptimizationIndexSetFilter + +from .. import deps +from ..base import BaseModel +from ..decorators import autodoc + +router: APIRouter = APIRouter( + prefix="/indexsets", + tags=["optimization", "indexsets"], +) + + +class IndexSetInput(BaseModel): + run_id: int + name: str + + +class EnumerationOutput(BaseModel): + __root__: list[api.IndexSet] | api.DataFrame + + +class ElementsInput(BaseModel): + elements: StrictInt | list[StrictInt | StrictStr] | StrictStr + + +@autodoc +@router.get("/", response_model=EnumerationOutput) +def enumerate( + filter: OptimizationIndexSetFilter = Depends(), + table: bool | None = Query(False), + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.enumerate(_filter=filter, table=bool(table)) + + +@autodoc +@router.patch("/", response_model=EnumerationOutput) +def query( + filter: OptimizationIndexSetFilter = Body(OptimizationIndexSetFilter()), + table: bool = Query(False), + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.enumerate(_filter=filter, table=bool(table)) + + +@autodoc +@router.post("/", response_model=api.IndexSet) +def create( + indexset: IndexSetInput, + backend: Backend = Depends(deps.get_backend), +): + return backend.optimization.indexsets.create(**indexset.dict()) + + +@autodoc +@router.patch("/{indexset_id}/") +def add_elements( + indexset_id: int, + elements: ElementsInput, + backend: Backend = Depends(deps.get_backend), +): + backend.optimization.indexsets.add_elements( + indexset_id=indexset_id, **elements.dict() + ) diff --git a/poetry.lock b/poetry.lock index fde37682..87cc1218 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -13,13 +13,13 @@ files = [ [[package]] name = "alembic" -version = "1.11.1" +version = "1.11.3" description = "A database migration tool for SQLAlchemy." optional = false python-versions = ">=3.7" files = [ - {file = "alembic-1.11.1-py3-none-any.whl", hash = "sha256:dc871798a601fab38332e38d6ddb38d5e734f60034baeb8e2db5b642fccd8ab8"}, - {file = "alembic-1.11.1.tar.gz", hash = "sha256:6a810a6b012c88b33458fceb869aef09ac75d6ace5291915ba7fae44de372c01"}, + {file = "alembic-1.11.3-py3-none-any.whl", hash = "sha256:d6c96c2482740592777c400550a523bc7a9aada4e210cae2e733354ddae6f6f8"}, + {file = "alembic-1.11.3.tar.gz", hash = "sha256:3db4ce81a9072e1b5aa44c2d202add24553182672a12daf21608d6f62a8f9cf9"}, ] [package.dependencies] @@ -32,13 +32,13 @@ tz = ["python-dateutil"] [[package]] name = "anyio" -version = "3.7.0" +version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.7" files = [ - {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, - {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, ] [package.dependencies] @@ -47,10 +47,21 @@ idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (<0.22)"] +[[package]] +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = "*" +files = [ + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, +] + [[package]] name = "asgiref" version = "3.7.2" @@ -68,6 +79,23 @@ typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] +[[package]] +name = "asttokens" +version = "2.2.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, + {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, +] + +[package.dependencies] +six = "*" + +[package.extras] +test = ["astroid", "pytest"] + [[package]] name = "atomicwrites" version = "1.4.1" @@ -107,38 +135,46 @@ files = [ {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] +[[package]] +name = "backcall" +version = "0.2.0" +description = "Specifications for callback functions passed in to an API" +optional = false +python-versions = "*" +files = [ + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, +] + [[package]] name = "black" -version = "23.3.0" +version = "23.7.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, ] [package.dependencies] @@ -155,15 +191,58 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "build" +version = "0.10.0" +description = "A simple, correct Python build frontend" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"}, + {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "os_name == \"nt\""} +packaging = ">=19.0" +pyproject_hooks = "*" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] +test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"] +typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"] +virtualenv = ["virtualenv (>=20.0.35)"] + +[[package]] +name = "cachecontrol" +version = "0.12.14" +description = "httplib2 caching for requests" +optional = false +python-versions = ">=3.6" +files = [ + {file = "CacheControl-0.12.14-py2.py3-none-any.whl", hash = "sha256:1c2939be362a70c4e5f02c6249462b3b7a24441e4f1ced5e9ef028172edf356a"}, + {file = "CacheControl-0.12.14.tar.gz", hash = "sha256:d1087f45781c0e00616479bfd282c78504371ca71da017b49df9f5365a95feba"}, +] + +[package.dependencies] +lockfile = {version = ">=0.9", optional = true, markers = "extra == \"filecache\""} +msgpack = ">=0.5.2" +requests = "*" + +[package.extras] +filecache = ["lockfile (>=0.9)"] +redis = ["redis (>=2.10.5)"] + [[package]] name = "certifi" -version = "2023.5.7" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] @@ -244,97 +323,112 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, ] +[[package]] +name = "cleo" +version = "2.0.1" +description = "Cleo allows you to create beautiful and testable command-line interfaces." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "cleo-2.0.1-py3-none-any.whl", hash = "sha256:6eb133670a3ed1f3b052d53789017b6e50fca66d1287e6e6696285f4cb8ea448"}, + {file = "cleo-2.0.1.tar.gz", hash = "sha256:eb4b2e1f3063c11085cebe489a6e9124163c226575a3c3be69b2e51af4a15ec5"}, +] + +[package.dependencies] +crashtest = ">=0.4.1,<0.5.0" +rapidfuzz = ">=2.2.0,<3.0.0" + [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -362,104 +456,130 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "comm" +version = "0.1.4" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.6" +files = [ + {file = "comm-0.1.4-py3-none-any.whl", hash = "sha256:6d52794cba11b36ed9860999cd10fd02d6b2eac177068fdd585e1e2f8a96e67a"}, + {file = "comm-0.1.4.tar.gz", hash = "sha256:354e40a59c9dd6db50c5cc6b4acc887d82e9603787f83b68c01a80a923984d15"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] +test = ["pytest"] +typing = ["mypy (>=0.990)"] + [[package]] name = "coverage" -version = "7.2.7" +version = "7.3.0" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, - {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, - {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, - {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, - {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, - {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, - {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, - {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, - {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, - {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, - {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, - {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, - {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, - {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, - {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, - {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, - {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, - {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, + {file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"}, + {file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"}, + {file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"}, + {file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"}, + {file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"}, + {file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"}, + {file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"}, + {file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"}, + {file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"}, + {file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"}, + {file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"}, + {file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"}, + {file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"}, + {file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"}, + {file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"}, + {file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"}, + {file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"}, + {file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"}, + {file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"}, + {file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"}, + {file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"}, + {file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"}, ] [package.extras] toml = ["tomli"] +[[package]] +name = "crashtest" +version = "0.4.1" +description = "Manage Python errors with ease" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "crashtest-0.4.1-py3-none-any.whl", hash = "sha256:8d23eac5fa660409f57472e3851dab7ac18aba459a8d19cbbba86d3d5aecd2a5"}, + {file = "crashtest-0.4.1.tar.gz", hash = "sha256:80d7b1f316ebfbd429f648076d6275c877ba30ba48979de4191714a75266f0ce"}, +] + [[package]] name = "cryptography" -version = "41.0.1" +version = "41.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"}, - {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"}, - {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"}, - {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"}, - {file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"}, - {file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"}, - {file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, + {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, + {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, + {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, ] [package.dependencies] @@ -477,13 +597,13 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "dask" -version = "2023.6.0" +version = "2023.8.1" description = "Parallel PyData with Task Scheduling" optional = false python-versions = ">=3.9" files = [ - {file = "dask-2023.6.0-py3-none-any.whl", hash = "sha256:294f449108397c4ca7a3bca27e32cb0fe9c65599c57d6301b3b70f825c2457d4"}, - {file = "dask-2023.6.0.tar.gz", hash = "sha256:980741966ef4d14c62dfb146f315f57d5eaaa6bedc52866f99687bc6054c2d4b"}, + {file = "dask-2023.8.1-py3-none-any.whl", hash = "sha256:53627bb324975624835a0f2b64b3b7e24afb4947ca5b371e0092c7e98adad0e2"}, + {file = "dask-2023.8.1.tar.gz", hash = "sha256:5c4b402908938dc87506e0fc07fb0dfa329e59587adf34531cd300fe853b3bf8"}, ] [package.dependencies] @@ -499,11 +619,49 @@ toolz = ">=0.10.0" [package.extras] array = ["numpy (>=1.21)"] complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)"] -dataframe = ["numpy (>=1.21)", "pandas (>=1.3)"] +dataframe = ["dask[array]", "pandas (>=1.3)"] diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] -distributed = ["distributed (==2023.6.0)"] +distributed = ["distributed (==2023.8.1)"] test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist"] +[[package]] +name = "debugpy" +version = "1.6.7.post1" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "debugpy-1.6.7.post1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:903bd61d5eb433b6c25b48eae5e23821d4c1a19e25c9610205f5aeaccae64e32"}, + {file = "debugpy-1.6.7.post1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16882030860081e7dd5aa619f30dec3c2f9a421e69861125f83cc372c94e57d"}, + {file = "debugpy-1.6.7.post1-cp310-cp310-win32.whl", hash = "sha256:eea8d8cfb9965ac41b99a61f8e755a8f50e9a20330938ad8271530210f54e09c"}, + {file = "debugpy-1.6.7.post1-cp310-cp310-win_amd64.whl", hash = "sha256:85969d864c45f70c3996067cfa76a319bae749b04171f2cdeceebe4add316155"}, + {file = "debugpy-1.6.7.post1-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:890f7ab9a683886a0f185786ffbda3b46495c4b929dab083b8c79d6825832a52"}, + {file = "debugpy-1.6.7.post1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4ac7a4dba28801d184b7fc0e024da2635ca87d8b0a825c6087bb5168e3c0d28"}, + {file = "debugpy-1.6.7.post1-cp37-cp37m-win32.whl", hash = "sha256:3370ef1b9951d15799ef7af41f8174194f3482ee689988379763ef61a5456426"}, + {file = "debugpy-1.6.7.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:65b28435a17cba4c09e739621173ff90c515f7b9e8ea469b92e3c28ef8e5cdfb"}, + {file = "debugpy-1.6.7.post1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:92b6dae8bfbd497c90596bbb69089acf7954164aea3228a99d7e43e5267f5b36"}, + {file = "debugpy-1.6.7.post1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72f5d2ecead8125cf669e62784ef1e6300f4067b0f14d9f95ee00ae06fc7c4f7"}, + {file = "debugpy-1.6.7.post1-cp38-cp38-win32.whl", hash = "sha256:f0851403030f3975d6e2eaa4abf73232ab90b98f041e3c09ba33be2beda43fcf"}, + {file = "debugpy-1.6.7.post1-cp38-cp38-win_amd64.whl", hash = "sha256:3de5d0f97c425dc49bce4293df6a04494309eedadd2b52c22e58d95107e178d9"}, + {file = "debugpy-1.6.7.post1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:38651c3639a4e8bbf0ca7e52d799f6abd07d622a193c406be375da4d510d968d"}, + {file = "debugpy-1.6.7.post1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:038c51268367c9c935905a90b1c2d2dbfe304037c27ba9d19fe7409f8cdc710c"}, + {file = "debugpy-1.6.7.post1-cp39-cp39-win32.whl", hash = "sha256:4b9eba71c290852f959d2cf8a03af28afd3ca639ad374d393d53d367f7f685b2"}, + {file = "debugpy-1.6.7.post1-cp39-cp39-win_amd64.whl", hash = "sha256:973a97ed3b434eab0f792719a484566c35328196540676685c975651266fccf9"}, + {file = "debugpy-1.6.7.post1-py2.py3-none-any.whl", hash = "sha256:1093a5c541af079c13ac8c70ab8b24d1d35c8cacb676306cf11e57f699c02926"}, + {file = "debugpy-1.6.7.post1.zip", hash = "sha256:fe87ec0182ef624855d05e6ed7e0b7cb1359d2ffa2a925f8ec2d22e98b75d0ca"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + [[package]] name = "deepmerge" version = "1.1.0" @@ -515,6 +673,17 @@ files = [ {file = "deepmerge-1.1.0.tar.gz", hash = "sha256:4c27a0db5de285e1a7ceac7dbc1531deaa556b627dea4900c8244581ecdfea2d"}, ] +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + [[package]] name = "docutils" version = "0.18.1" @@ -526,6 +695,94 @@ files = [ {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, ] +[[package]] +name = "dulwich" +version = "0.21.5" +description = "Python Git Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dulwich-0.21.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8864719bc176cdd27847332a2059127e2f7bab7db2ff99a999873cb7fff54116"}, + {file = "dulwich-0.21.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3800cdc17d144c1f7e114972293bd6c46688f5bcc2c9228ed0537ded72394082"}, + {file = "dulwich-0.21.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2f676bfed8146966fe934ee734969d7d81548fbd250a8308582973670a9dab1"}, + {file = "dulwich-0.21.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db330fb59fe3b9d253bdf0e49a521739db83689520c4921ab1c5242aaf77b82"}, + {file = "dulwich-0.21.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e8f6d4f4f4d01dd1d3c968e486d4cd77f96f772da7265941bc506de0944ddb9"}, + {file = "dulwich-0.21.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1cc0c9ba19ac1b2372598802bc9201a9c45e5d6f1f7a80ec40deeb10acc4e9ae"}, + {file = "dulwich-0.21.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:61e10242b5a7a82faa8996b2c76239cfb633620b02cdd2946e8af6e7eb31d651"}, + {file = "dulwich-0.21.5-cp310-cp310-win32.whl", hash = "sha256:7f357639b56146a396f48e5e0bc9bbaca3d6d51c8340bd825299272b588fff5f"}, + {file = "dulwich-0.21.5-cp310-cp310-win_amd64.whl", hash = "sha256:891d5c73e2b66d05dbb502e44f027dc0dbbd8f6198bc90dae348152e69d0befc"}, + {file = "dulwich-0.21.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45d6198e804b539708b73a003419e48fb42ff2c3c6dd93f63f3b134dff6dd259"}, + {file = "dulwich-0.21.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c2a565d4e704d7f784cdf9637097141f6d47129c8fffc2fac699d57cb075a169"}, + {file = "dulwich-0.21.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:823091d6b6a1ea07dc4839c9752198fb39193213d103ac189c7669736be2eaff"}, + {file = "dulwich-0.21.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2c9931b657f2206abec0964ec2355ee2c1e04d05f8864e823ffa23c548c4548"}, + {file = "dulwich-0.21.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dc358c2ee727322a09b7c6da43d47a1026049dbd3ad8d612eddca1f9074b298"}, + {file = "dulwich-0.21.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6155ab7388ee01c670f7c5d8003d4e133eebebc7085a856c007989f0ba921b36"}, + {file = "dulwich-0.21.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a605e10d72f90a39ea2e634fbfd80f866fc4df29a02ea6db52ae92e5fd4a2003"}, + {file = "dulwich-0.21.5-cp311-cp311-win32.whl", hash = "sha256:daa607370722c3dce99a0022397c141caefb5ed32032a4f72506f4817ea6405b"}, + {file = "dulwich-0.21.5-cp311-cp311-win_amd64.whl", hash = "sha256:5e56b2c1911c344527edb2bf1a4356e2fb7e086b1ba309666e1e5c2224cdca8a"}, + {file = "dulwich-0.21.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:85d3401d08b1ec78c7d58ae987c4bb7b768a438f3daa74aeb8372bebc7fb16fa"}, + {file = "dulwich-0.21.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90479608e49db93d8c9e4323bc0ec5496678b535446e29d8fd67dc5bbb5d51bf"}, + {file = "dulwich-0.21.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9a6bf99f57bcac4c77fc60a58f1b322c91cc4d8c65dc341f76bf402622f89cb"}, + {file = "dulwich-0.21.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3e68b162af2aae995355e7920f89d50d72b53d56021e5ac0a546d493b17cbf7e"}, + {file = "dulwich-0.21.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0ab86d6d42e385bf3438e70f3c9b16de68018bd88929379e3484c0ef7990bd3c"}, + {file = "dulwich-0.21.5-cp37-cp37m-win32.whl", hash = "sha256:f2eeca6d61366cf5ee8aef45bed4245a67d4c0f0d731dc2383eabb80fa695683"}, + {file = "dulwich-0.21.5-cp37-cp37m-win_amd64.whl", hash = "sha256:1b20a3656b48c941d49c536824e1e5278a695560e8de1a83b53a630143c4552e"}, + {file = "dulwich-0.21.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3932b5e17503b265a85f1eda77ede647681c3bab53bc9572955b6b282abd26ea"}, + {file = "dulwich-0.21.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6616132d219234580de88ceb85dd51480dc43b1bdc05887214b8dd9cfd4a9d40"}, + {file = "dulwich-0.21.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:eaf6c7fb6b13495c19c9aace88821c2ade3c8c55b4e216cd7cc55d3e3807d7fa"}, + {file = "dulwich-0.21.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be12a46f73023970125808a4a78f610c055373096c1ecea3280edee41613eba8"}, + {file = "dulwich-0.21.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baecef0d8b9199822c7912876a03a1af17833f6c0d461efb62decebd45897e49"}, + {file = "dulwich-0.21.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:82f632afb9c7c341a875d46aaa3e6c5e586c7a64ce36c9544fa400f7e4f29754"}, + {file = "dulwich-0.21.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82cdf482f8f51fcc965ffad66180b54a9abaea9b1e985a32e1acbfedf6e0e363"}, + {file = "dulwich-0.21.5-cp38-cp38-win32.whl", hash = "sha256:c8ded43dc0bd2e65420eb01e778034be5ca7f72e397a839167eda7dcb87c4248"}, + {file = "dulwich-0.21.5-cp38-cp38-win_amd64.whl", hash = "sha256:2aba0fdad2a19bd5bb3aad6882580cb33359c67b48412ccd4cfccd932012b35e"}, + {file = "dulwich-0.21.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fd4ad079758514375f11469e081723ba8831ce4eaa1a64b41f06a3a866d5ac34"}, + {file = "dulwich-0.21.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fe62685bf356bfb4d0738f84a3fcf0d1fc9e11fee152e488a20b8c66a52429e"}, + {file = "dulwich-0.21.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aae448da7d80306dda4fc46292fed7efaa466294571ab3448be16714305076f1"}, + {file = "dulwich-0.21.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b24cb1fad0525dba4872e9381bc576ea2a6dcdf06b0ed98f8e953e3b1d719b89"}, + {file = "dulwich-0.21.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e39b7c2c9bda6acae83b25054650a8bb7e373e886e2334721d384e1479bf04b"}, + {file = "dulwich-0.21.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26456dba39d1209fca17187db06967130e27eeecad2b3c2bbbe63467b0bf09d6"}, + {file = "dulwich-0.21.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:281310644e02e3aa6d76bcaffe2063b9031213c4916b5f1a6e68c25bdecfaba4"}, + {file = "dulwich-0.21.5-cp39-cp39-win32.whl", hash = "sha256:4814ca3209dabe0fe7719e9545fbdad7f8bb250c5a225964fe2a31069940c4cf"}, + {file = "dulwich-0.21.5-cp39-cp39-win_amd64.whl", hash = "sha256:c922a4573267486be0ef85216f2da103fb38075b8465dc0e90457843884e4860"}, + {file = "dulwich-0.21.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e52b20c4368171b7d32bd3ab0f1d2402e76ad4f2ea915ff9aa73bc9fa2b54d6d"}, + {file = "dulwich-0.21.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeb736d777ee21f2117a90fc453ee181aa7eedb9e255b5ef07c51733f3fe5cb6"}, + {file = "dulwich-0.21.5-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e8a79c1ed7166f32ad21974fa98d11bf6fd74e94a47e754c777c320e01257c6"}, + {file = "dulwich-0.21.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b943517e30bd651fbc275a892bb96774f3893d95fe5a4dedd84496a98eaaa8ab"}, + {file = "dulwich-0.21.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:32493a456358a3a6c15bbda07106fc3d4cc50834ee18bc7717968d18be59b223"}, + {file = "dulwich-0.21.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aa44b812d978fc22a04531f5090c3c369d5facd03fa6e0501d460a661800c7f"}, + {file = "dulwich-0.21.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f46bcb6777e5f9f4af24a2bd029e88b77316269d24ce66be590e546a0d8f7b7"}, + {file = "dulwich-0.21.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a917fd3b4493db3716da2260f16f6b18f68d46fbe491d851d154fc0c2d984ae4"}, + {file = "dulwich-0.21.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:684c52cff867d10c75a7238151ca307582b3d251bbcd6db9e9cffbc998ef804e"}, + {file = "dulwich-0.21.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9019189d7a8f7394df6a22cd5b484238c5776e42282ad5d6d6c626b4c5f43597"}, + {file = "dulwich-0.21.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:494024f74c2eef9988adb4352b3651ac1b6c0466176ec62b69d3d3672167ba68"}, + {file = "dulwich-0.21.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f9b6ac1b1c67fc6083c42b7b6cd3b211292c8a6517216c733caf23e8b103ab6d"}, + {file = "dulwich-0.21.5.tar.gz", hash = "sha256:70955e4e249ddda6e34a4636b90f74e931e558f993b17c52570fa6144b993103"}, +] + +[package.dependencies] +urllib3 = ">=1.25" + +[package.extras] +fastimport = ["fastimport"] +https = ["urllib3 (>=1.24.1)"] +paramiko = ["paramiko"] +pgp = ["gpg"] + +[[package]] +name = "dunamai" +version = "1.18.0" +description = "Dynamic version generation" +optional = false +python-versions = ">=3.5,<4.0" +files = [ + {file = "dunamai-1.18.0-py3-none-any.whl", hash = "sha256:f9284a9f4048f0b809d11539896e78bde94c05b091b966a04a44ab4c48df03ce"}, + {file = "dunamai-1.18.0.tar.gz", hash = "sha256:5200598561ea5ba956a6174c36e402e92206c6a6aa4a93a6c5cb8003ee1e0997"}, +] + +[package.dependencies] +packaging = ">=20.9" + [[package]] name = "et-xmlfile" version = "1.1.0" @@ -539,18 +796,32 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "executing" +version = "1.2.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = "*" +files = [ + {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, + {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, +] + +[package.extras] +tests = ["asttokens", "littleutils", "pytest", "rich"] + [[package]] name = "fastapi" version = "0.94.1" @@ -572,21 +843,39 @@ dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (> doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] +[[package]] +name = "filelock" +version = "3.12.3" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.12.3-py3-none-any.whl", hash = "sha256:f067e40ccc40f2b48395a80fcbd4728262fab54e232e090a4063ab804179efeb"}, + {file = "filelock-3.12.3.tar.gz", hash = "sha256:0ecc1dd2ec4672a10c8550a8182f1bd0c0a5088470ecd5a125e45f49472fac3d"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-timeout (>=2.1)"] + [[package]] name = "flake8" -version = "6.0.0" +version = "6.1.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" files = [ - {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"}, - {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"}, + {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, + {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.10.0,<2.11.0" -pyflakes = ">=3.0.0,<3.1.0" +pycodestyle = ">=2.11.0,<2.12.0" +pyflakes = ">=3.1.0,<3.2.0" [[package]] name = "flake8-bugbear" @@ -788,6 +1077,27 @@ files = [ {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, ] +[[package]] +name = "html5lib" +version = "1.1" +description = "HTML parser based on the WHATWG HTML specification" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + +[package.dependencies] +six = ">=1.9" +webencodings = "*" + +[package.extras] +all = ["chardet (>=2.2)", "genshi", "lxml"] +chardet = ["chardet (>=2.2)"] +genshi = ["genshi"] +lxml = ["lxml"] + [[package]] name = "httpcore" version = "0.16.3" @@ -895,13 +1205,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.6.0" +version = "6.8.0" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, - {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, ] [package.dependencies] @@ -910,7 +1220,7 @@ zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "iniconfig" @@ -923,6 +1233,140 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "installer" +version = "0.7.0" +description = "A library for installing Python wheels." +optional = false +python-versions = ">=3.7" +files = [ + {file = "installer-0.7.0-py3-none-any.whl", hash = "sha256:05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53"}, + {file = "installer-0.7.0.tar.gz", hash = "sha256:a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631"}, +] + +[[package]] +name = "ipykernel" +version = "6.25.1" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.25.1-py3-none-any.whl", hash = "sha256:c8a2430b357073b37c76c21c52184db42f6b4b0e438e1eb7df3c4440d120497c"}, + {file = "ipykernel-6.25.1.tar.gz", hash = "sha256:050391364c0977e768e354bdb60cbbfbee7cbb943b1af1618382021136ffd42f"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=20" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "8.14.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.14.0-py3-none-any.whl", hash = "sha256:248aca623f5c99a6635bc3857677b7320b9b8039f99f070ee0d20a5ca5a8e6bf"}, + {file = "ipython-8.14.0.tar.gz", hash = "sha256:1d197b907b6ba441b692c48cf2a3a2de280dc0ac91a3405b39349a50272ca0a1"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "sys_platform == \"darwin\""} +backcall = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pickleshare = "*" +prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" + +[package.extras] +all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] + +[[package]] +name = "jaraco-classes" +version = "3.3.0" +description = "Utility functions for Python class constructs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jaraco.classes-3.3.0-py3-none-any.whl", hash = "sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb"}, + {file = "jaraco.classes-3.3.0.tar.gz", hash = "sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621"}, +] + +[package.dependencies] +more-itertools = "*" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[[package]] +name = "jedi" +version = "0.19.0" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"}, + {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jeepney" +version = "0.8.0" +description = "Low-level, pure Python DBus protocol wrapper." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, + {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, +] + +[package.extras] +test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] +trio = ["async_generator", "trio"] + [[package]] name = "jinja2" version = "3.1.2" @@ -942,23 +1386,104 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.17.3" +version = "4.19.0" description = "An implementation of JSON Schema validation for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, + {file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"}, + {file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"}, ] [package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +[[package]] +name = "jsonschema-specifications" +version = "2023.7.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, + {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, +] + +[package.dependencies] +referencing = ">=0.28.0" + +[[package]] +name = "jupyter-client" +version = "8.3.0" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.3.0-py3-none-any.whl", hash = "sha256:7441af0c0672edc5d28035e92ba5e32fadcfa8a4e608a434c228836a89df6158"}, + {file = "jupyter_client-8.3.0.tar.gz", hash = "sha256:3af69921fe99617be1670399a0b857ad67275eefcfa291e2c81a160b7b650f5f"}, +] + +[package.dependencies] +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.3.1" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.3.1-py3-none-any.whl", hash = "sha256:ae9036db959a71ec1cac33081eeb040a79e681f08ab68b0883e9a676c7a90dce"}, + {file = "jupyter_core-5.3.1.tar.gz", hash = "sha256:5ba5c7938a7f97a6b0481463f7ff0dbac7c15ba48cf46fa4035ca6e838aa1aba"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "keyring" +version = "23.13.1" +description = "Store and access your passwords safely." +optional = false +python-versions = ">=3.7" +files = [ + {file = "keyring-23.13.1-py3-none-any.whl", hash = "sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd"}, + {file = "keyring-23.13.1.tar.gz", hash = "sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""} +"jaraco.classes" = "*" +jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} +pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} +SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} + +[package.extras] +completion = ["shtab"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] +testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] + [[package]] name = "latexcodec" version = "2.0.1" @@ -984,6 +1509,17 @@ files = [ {file = "locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632"}, ] +[[package]] +name = "lockfile" +version = "0.12.2" +description = "Platform-independent file locking module" +optional = false +python-versions = "*" +files = [ + {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, + {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, +] + [[package]] name = "mako" version = "1.2.4" @@ -1062,6 +1598,20 @@ files = [ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.5" +files = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] + +[package.dependencies] +traitlets = "*" + [[package]] name = "mccabe" version = "0.7.0" @@ -1084,43 +1634,126 @@ files = [ {file = "mistune-2.0.5.tar.gz", hash = "sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34"}, ] +[[package]] +name = "more-itertools" +version = "10.1.0" +description = "More routines for operating on iterables, beyond itertools" +optional = false +python-versions = ">=3.8" +files = [ + {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, + {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, +] + +[[package]] +name = "msgpack" +version = "1.0.5" +description = "MessagePack serializer" +optional = false +python-versions = "*" +files = [ + {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:525228efd79bb831cf6830a732e2e80bc1b05436b086d4264814b4b2955b2fa9"}, + {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f8d8b3bf1ff2672567d6b5c725a1b347fe838b912772aa8ae2bf70338d5a198"}, + {file = "msgpack-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdc793c50be3f01106245a61b739328f7dccc2c648b501e237f0699fe1395b81"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cb47c21a8a65b165ce29f2bec852790cbc04936f502966768e4aae9fa763cb7"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e42b9594cc3bf4d838d67d6ed62b9e59e201862a25e9a157019e171fbe672dd3"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55b56a24893105dc52c1253649b60f475f36b3aa0fc66115bffafb624d7cb30b"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1967f6129fc50a43bfe0951c35acbb729be89a55d849fab7686004da85103f1c"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a97bf595a232c3ee6d57ddaadd5453d174a52594bf9c21d10407e2a2d9b3bd"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d25dd59bbbbb996eacf7be6b4ad082ed7eacc4e8f3d2df1ba43822da9bfa122a"}, + {file = "msgpack-1.0.5-cp310-cp310-win32.whl", hash = "sha256:382b2c77589331f2cb80b67cc058c00f225e19827dbc818d700f61513ab47bea"}, + {file = "msgpack-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:4867aa2df9e2a5fa5f76d7d5565d25ec76e84c106b55509e78c1ede0f152659a"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9f5ae84c5c8a857ec44dc180a8b0cc08238e021f57abdf51a8182e915e6299f0"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e6ca5d5699bcd89ae605c150aee83b5321f2115695e741b99618f4856c50898"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5494ea30d517a3576749cad32fa27f7585c65f5f38309c88c6d137877fa28a5a"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ab2f3331cb1b54165976a9d976cb251a83183631c88076613c6c780f0d6e45a"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28592e20bbb1620848256ebc105fc420436af59515793ed27d5c77a217477705"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe5c63197c55bce6385d9aee16c4d0641684628f63ace85f73571e65ad1c1e8d"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed40e926fa2f297e8a653c954b732f125ef97bdd4c889f243182299de27e2aa9"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b2de4c1c0538dcb7010902a2b97f4e00fc4ddf2c8cda9749af0e594d3b7fa3d7"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf22a83f973b50f9d38e55c6aade04c41ddda19b00c4ebc558930d78eecc64ed"}, + {file = "msgpack-1.0.5-cp311-cp311-win32.whl", hash = "sha256:c396e2cc213d12ce017b686e0f53497f94f8ba2b24799c25d913d46c08ec422c"}, + {file = "msgpack-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c4c68d87497f66f96d50142a2b73b97972130d93677ce930718f68828b382e2"}, + {file = "msgpack-1.0.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2b031c2e9b9af485d5e3c4520f4220d74f4d222a5b8dc8c1a3ab9448ca79c57"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f837b93669ce4336e24d08286c38761132bc7ab29782727f8557e1eb21b2080"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1d46dfe3832660f53b13b925d4e0fa1432b00f5f7210eb3ad3bb9a13c6204a6"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:366c9a7b9057e1547f4ad51d8facad8b406bab69c7d72c0eb6f529cf76d4b85f"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4c075728a1095efd0634a7dccb06204919a2f67d1893b6aa8e00497258bf926c"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:f933bbda5a3ee63b8834179096923b094b76f0c7a73c1cfe8f07ad608c58844b"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:36961b0568c36027c76e2ae3ca1132e35123dcec0706c4b7992683cc26c1320c"}, + {file = "msgpack-1.0.5-cp36-cp36m-win32.whl", hash = "sha256:b5ef2f015b95f912c2fcab19c36814963b5463f1fb9049846994b007962743e9"}, + {file = "msgpack-1.0.5-cp36-cp36m-win_amd64.whl", hash = "sha256:288e32b47e67f7b171f86b030e527e302c91bd3f40fd9033483f2cacc37f327a"}, + {file = "msgpack-1.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:137850656634abddfb88236008339fdaba3178f4751b28f270d2ebe77a563b6c"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c05a4a96585525916b109bb85f8cb6511db1c6f5b9d9cbcbc940dc6b4be944b"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a62ec00b636583e5cb6ad313bbed36bb7ead5fa3a3e38938503142c72cba4f"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef8108f8dedf204bb7b42994abf93882da1159728a2d4c5e82012edd92c9da9f"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1835c84d65f46900920b3708f5ba829fb19b1096c1800ad60bae8418652a951d"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e57916ef1bd0fee4f21c4600e9d1da352d8816b52a599c46460e93a6e9f17086"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:17358523b85973e5f242ad74aa4712b7ee560715562554aa2134d96e7aa4cbbf"}, + {file = "msgpack-1.0.5-cp37-cp37m-win32.whl", hash = "sha256:cb5aaa8c17760909ec6cb15e744c3ebc2ca8918e727216e79607b7bbce9c8f77"}, + {file = "msgpack-1.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:ab31e908d8424d55601ad7075e471b7d0140d4d3dd3272daf39c5c19d936bd82"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b72d0698f86e8d9ddf9442bdedec15b71df3598199ba33322d9711a19f08145c"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:379026812e49258016dd84ad79ac8446922234d498058ae1d415f04b522d5b2d"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:332360ff25469c346a1c5e47cbe2a725517919892eda5cfaffe6046656f0b7bb"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:476a8fe8fae289fdf273d6d2a6cb6e35b5a58541693e8f9f019bfe990a51e4ba"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9985b214f33311df47e274eb788a5893a761d025e2b92c723ba4c63936b69b1"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48296af57cdb1d885843afd73c4656be5c76c0c6328db3440c9601a98f303d87"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:addab7e2e1fcc04bd08e4eb631c2a90960c340e40dfc4a5e24d2ff0d5a3b3edb"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:916723458c25dfb77ff07f4c66aed34e47503b2eb3188b3adbec8d8aa6e00f48"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:821c7e677cc6acf0fd3f7ac664c98803827ae6de594a9f99563e48c5a2f27eb0"}, + {file = "msgpack-1.0.5-cp38-cp38-win32.whl", hash = "sha256:1c0f7c47f0087ffda62961d425e4407961a7ffd2aa004c81b9c07d9269512f6e"}, + {file = "msgpack-1.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:bae7de2026cbfe3782c8b78b0db9cbfc5455e079f1937cb0ab8d133496ac55e1"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:20c784e66b613c7f16f632e7b5e8a1651aa5702463d61394671ba07b2fc9e025"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:266fa4202c0eb94d26822d9bfd7af25d1e2c088927fe8de9033d929dd5ba24c5"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18334484eafc2b1aa47a6d42427da7fa8f2ab3d60b674120bce7a895a0a85bdd"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57e1f3528bd95cc44684beda696f74d3aaa8a5e58c816214b9046512240ef437"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:586d0d636f9a628ddc6a17bfd45aa5b5efaf1606d2b60fa5d87b8986326e933f"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a740fa0e4087a734455f0fc3abf5e746004c9da72fbd541e9b113013c8dc3282"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3055b0455e45810820db1f29d900bf39466df96ddca11dfa6d074fa47054376d"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a61215eac016f391129a013c9e46f3ab308db5f5ec9f25811e811f96962599a8"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:362d9655cd369b08fda06b6657a303eb7172d5279997abe094512e919cf74b11"}, + {file = "msgpack-1.0.5-cp39-cp39-win32.whl", hash = "sha256:ac9dd47af78cae935901a9a500104e2dea2e253207c924cc95de149606dc43cc"}, + {file = "msgpack-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:06f5174b5f8ed0ed919da0e62cbd4ffde676a374aba4020034da05fab67b9164"}, + {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, +] + [[package]] name = "mypy" -version = "1.3.0" +version = "1.0.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, - {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, - {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, - {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, - {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, - {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, - {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, - {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, - {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, - {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, - {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, - {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, - {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, - {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, - {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, - {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, - {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, - {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, - {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, - {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" + {file = "mypy-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf"}, + {file = "mypy-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0"}, + {file = "mypy-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b"}, + {file = "mypy-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8"}, + {file = "mypy-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8"}, + {file = "mypy-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65"}, + {file = "mypy-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994"}, + {file = "mypy-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919"}, + {file = "mypy-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4"}, + {file = "mypy-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff"}, + {file = "mypy-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c"}, + {file = "mypy-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6"}, + {file = "mypy-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88"}, + {file = "mypy-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5"}, + {file = "mypy-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407"}, + {file = "mypy-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd"}, + {file = "mypy-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3"}, + {file = "mypy-1.0.1-py3-none-any.whl", hash = "sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"}, + {file = "mypy-1.0.1.tar.gz", hash = "sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d"}, +] + +[package.dependencies] +mypy-extensions = ">=0.4.3" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=3.10" @@ -1141,41 +1774,49 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nest-asyncio" +version = "1.5.7" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.5.7-py3-none-any.whl", hash = "sha256:5301c82941b550b3123a1ea772ba9a1c80bad3a182be8c1a5ae6ad3be57a9657"}, + {file = "nest_asyncio-1.5.7.tar.gz", hash = "sha256:6a80f7b98f24d9083ed24608977c09dd608d83f91cccc24c9d2cba6d10e01c10"}, +] + [[package]] name = "numpy" -version = "1.24.3" +version = "1.25.2" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, - {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, - {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, - {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, - {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, - {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, - {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, - {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, - {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, - {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, - {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, ] [[package]] @@ -1194,39 +1835,39 @@ et-xmlfile = "*" [[package]] name = "oracledb" -version = "1.3.1" +version = "1.4.0" description = "Python interface to Oracle Database" optional = false python-versions = ">=3.6" files = [ - {file = "oracledb-1.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ae37b751ec1a1195e731d9f28eedb6abcf233b84436c0edda6e7163ad2a24ab0"}, - {file = "oracledb-1.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48fabce88c674566e1c87e9f743cdae85bc178239ccdfedf6f4af21e9d6840bb"}, - {file = "oracledb-1.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e65c4598ef0390fa2e214ade63da19233553303812bdd9da84a764adf8e8962a"}, - {file = "oracledb-1.3.1-cp310-cp310-win32.whl", hash = "sha256:e811ed3579dcb4dbf768c5af591ad70474e6dcc49a27472d24851a91a71147fc"}, - {file = "oracledb-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:3addbdf7c5d110b8d31e132f2e1263f151ade950288d9ceea9ae01acefe563d4"}, - {file = "oracledb-1.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dab0b5c01346cdc237adbb33dcced0a1286e51506f697c654089630cec1ee8bd"}, - {file = "oracledb-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10a4ed0b046cc36421380b2e9e4b8052c25209fa199e58c244190571997583d4"}, - {file = "oracledb-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2173ef1edce4a66009f9d1af33fe2fac9a70c0d03c833cf373d6b54402c07a8"}, - {file = "oracledb-1.3.1-cp311-cp311-win32.whl", hash = "sha256:84775f9441f0975a54407e642a923f7b13d06b993b8b656168892718599d3573"}, - {file = "oracledb-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:860e69c31a5f45bf83c6f76728cdefd6f6cd72931e8657594a3cf09d6b3c0a48"}, - {file = "oracledb-1.3.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:babab331ae31fca8b7a7a3d5cdf0bb0cb70ec1893283d81acd1bc429b9796ba5"}, - {file = "oracledb-1.3.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09fe99fe47054199942557dc822bc9ccd277b1e20b4caafc35dd16cca59edcca"}, - {file = "oracledb-1.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aa3a1d2222be20c8c778fb735d871123e2220d8c66d17d9cbcebd31a4d0b27fd"}, - {file = "oracledb-1.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9728424d64064e31c79137539f69f3bcf50fe861a8833d2dc04c2fe6fa6f9711"}, - {file = "oracledb-1.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3d074b76e2cf459554c25b38c13962003112ae3de939a6da0a6ab37711c5379"}, - {file = "oracledb-1.3.1-cp37-cp37m-win32.whl", hash = "sha256:46e2b01b10fe547f6d1ccb4f57d8596bf982caf876cb1c7006892ddb7fd3896a"}, - {file = "oracledb-1.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:edfb982e562d11fb14242c23c80d5a82fe0606ac4aeedcc987c85eeb3d2ff131"}, - {file = "oracledb-1.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:93d9321cbaee556809da35a8facd45eb846f31df70c267758305fa25a1e3ce33"}, - {file = "oracledb-1.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29b4fbc90c0dbcacdf3f83bc4a9f34defd04c56ffa732998ed78a36f5d7f4c8d"}, - {file = "oracledb-1.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f6021a4aa3430e7afc59b8bfcbddacb223f5cb59bd35eba72bdba7e2949251"}, - {file = "oracledb-1.3.1-cp38-cp38-win32.whl", hash = "sha256:ec0857b5120ac07b8325c84e2ec86b3455a7cbc2fb59896857f6a3ff31a63a23"}, - {file = "oracledb-1.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:c653b820602ff5cd11a40f0666af1e451e5c5324cf15acf37ad0088051c90490"}, - {file = "oracledb-1.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d264eac7cbbc6fdacd8eb91e812110ff8a63fde32306173dfb610064162ca609"}, - {file = "oracledb-1.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f3d01681a2208bcdf4a510277b216977c328d2d00478a943b4dbf777d751e6"}, - {file = "oracledb-1.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3cb7940030c86d158231cddfbb1bb7dc95f71c786d8fb1772b95b4141e6923c"}, - {file = "oracledb-1.3.1-cp39-cp39-win32.whl", hash = "sha256:792a80d4f7579578ac5432e1408b13e45cf3d43c1ccda19e71d860dbd8cc98e5"}, - {file = "oracledb-1.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:d8a2c1833294a53f4b0dd26c7b74fa553c5e959dbb4c57b647910096f43aa8e2"}, - {file = "oracledb-1.3.1.tar.gz", hash = "sha256:fce1bebdb0d8b88f908e0e1d0d8e5c24ce44e1be041b36032c28c3ba88e21314"}, + {file = "oracledb-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3893da5f390a2ff8cb0914c025c33255cda6e0c9da506b26c3da6c309a2e9b2a"}, + {file = "oracledb-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38c0ad3cf563123080d0c36bf1e7b28884663b297e4269b69a3f597891808707"}, + {file = "oracledb-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:117e8b33bcb9de98912e13a25d1fed28db3510e7229b27b295b413ba03e2b176"}, + {file = "oracledb-1.4.0-cp310-cp310-win32.whl", hash = "sha256:e9c205e69bafaf8f16ea5f1d06ab713f3f75cab1a4e22995d688f380c92f7aeb"}, + {file = "oracledb-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:411acaf2f11076485a66efb42273ec25ed97cb060df191e0d309f02455f2abbd"}, + {file = "oracledb-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1fc16c738c2287cbc26b2fe5e6292508f78f6b7ae833f3f371c804cc4fd01027"}, + {file = "oracledb-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44a1f44bdc068a0051058dcb639bb504c78167cc48c6d5181b1c066cba1e5050"}, + {file = "oracledb-1.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eec1b828a6bb1d626c1555746ea411a9d853ed8428aafed8eef0aff6d90b66c9"}, + {file = "oracledb-1.4.0-cp311-cp311-win32.whl", hash = "sha256:5a452671d4c079a35c4086fed2f4635f4a902d607c05bab48ea2eb919794f0d0"}, + {file = "oracledb-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:f1ed9b6f857ec70cf33ace4ab16403ce00232d875e68922168ac5e96c9fbea65"}, + {file = "oracledb-1.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52d6184a161508e759797857ebd6fdc8ba1439072c9572718dde9a196924856"}, + {file = "oracledb-1.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b236339d2cd502a6637b462adeef14616afd358a6393608d83cf71e502495b28"}, + {file = "oracledb-1.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:72165e6e84f7d6b2c3c290f4fadd123cd03c11f715d99f9a3f0117569bf40f3e"}, + {file = "oracledb-1.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a55c509ec54661901b2ae2a60169b8997de480d0646bb458ac92a05fbb77441"}, + {file = "oracledb-1.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b9fe90ec793ce13f72e2051e4734ad0002cd12dd009141f585c13dc51c314a9"}, + {file = "oracledb-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:be54c63a9424964a4bdccdfa2368188b77e1b00e065b81776b762cbb8559ff2f"}, + {file = "oracledb-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c7272f60f6da7a921a3597db91c323c7efdd44a9682ec4bbfb4483f6c039c810"}, + {file = "oracledb-1.4.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:473fab2bf20092690c3bf87e3d966e3a6fb9186b8cea40e65a73b5980f4f5bd4"}, + {file = "oracledb-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7890bb93137b6ed369fd25fb54ccdff64e41dccac65b3eaca18f08b4f3dffd4"}, + {file = "oracledb-1.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf5d1b0ea16e0f5168819fbb25b045c6f82f2c019bebddee18c0a8967946f681"}, + {file = "oracledb-1.4.0-cp38-cp38-win32.whl", hash = "sha256:64574cb4f69c3dd2767779c0f71f7b8c4307688b50183027740c6e3ceb2440f6"}, + {file = "oracledb-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:0dcd691da66b7ee34725cfd55d059360b5474e624f0eb18886d3fc9cefd3bf33"}, + {file = "oracledb-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6432d1d2609c0a65ad23c074c0136025f29c5aa47a7093554481de0447f087e9"}, + {file = "oracledb-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadab02421f76c6e2affc72e1719c8ea0c52022dad391fd46024e76f91ac3a02"}, + {file = "oracledb-1.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25aa5299b981fb52dee19011282dacbd865e5d616e942435763a2a1b76614da2"}, + {file = "oracledb-1.4.0-cp39-cp39-win32.whl", hash = "sha256:269e4f58d874f067605d12f35e701838d58aff4cac05890be6549deec09fe6ae"}, + {file = "oracledb-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:e6a3c8b8c526f6b10af47951f30bee5a599286dfe18073b053cae1a9d9b1bdec"}, + {file = "oracledb-1.4.0.tar.gz", hash = "sha256:96ba508f783892c7ca648f268acbcb8a4a9c8037c7dd4a509f05f2c89d6231be"}, ] [package.dependencies] @@ -1245,36 +1886,36 @@ files = [ [[package]] name = "pandas" -version = "2.0.2" +version = "2.0.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.8" files = [ - {file = "pandas-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ebb9f1c22ddb828e7fd017ea265a59d80461d5a79154b49a4207bd17514d122"}, - {file = "pandas-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eb09a242184092f424b2edd06eb2b99d06dc07eeddff9929e8667d4ed44e181"}, - {file = "pandas-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7319b6e68de14e6209460f72a8d1ef13c09fb3d3ef6c37c1e65b35d50b5c145"}, - {file = "pandas-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd46bde7309088481b1cf9c58e3f0e204b9ff9e3244f441accd220dd3365ce7c"}, - {file = "pandas-2.0.2-cp310-cp310-win32.whl", hash = "sha256:51a93d422fbb1bd04b67639ba4b5368dffc26923f3ea32a275d2cc450f1d1c86"}, - {file = "pandas-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:66d00300f188fa5de73f92d5725ced162488f6dc6ad4cecfe4144ca29debe3b8"}, - {file = "pandas-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02755de164da6827764ceb3bbc5f64b35cb12394b1024fdf88704d0fa06e0e2f"}, - {file = "pandas-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a1e0576611641acde15c2322228d138258f236d14b749ad9af498ab69089e2d"}, - {file = "pandas-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6b5f14cd24a2ed06e14255ff40fe2ea0cfaef79a8dd68069b7ace74bd6acbba"}, - {file = "pandas-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50e451932b3011b61d2961b4185382c92cc8c6ee4658dcd4f320687bb2d000ee"}, - {file = "pandas-2.0.2-cp311-cp311-win32.whl", hash = "sha256:7b21cb72958fc49ad757685db1919021d99650d7aaba676576c9e88d3889d456"}, - {file = "pandas-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:c4af689352c4fe3d75b2834933ee9d0ccdbf5d7a8a7264f0ce9524e877820c08"}, - {file = "pandas-2.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:69167693cb8f9b3fc060956a5d0a0a8dbfed5f980d9fd2c306fb5b9c855c814c"}, - {file = "pandas-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:30a89d0fec4263ccbf96f68592fd668939481854d2ff9da709d32a047689393b"}, - {file = "pandas-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a18e5c72b989ff0f7197707ceddc99828320d0ca22ab50dd1b9e37db45b010c0"}, - {file = "pandas-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7376e13d28eb16752c398ca1d36ccfe52bf7e887067af9a0474de6331dd948d2"}, - {file = "pandas-2.0.2-cp38-cp38-win32.whl", hash = "sha256:6d6d10c2142d11d40d6e6c0a190b1f89f525bcf85564707e31b0a39e3b398e08"}, - {file = "pandas-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e69140bc2d29a8556f55445c15f5794490852af3de0f609a24003ef174528b79"}, - {file = "pandas-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b42b120458636a981077cfcfa8568c031b3e8709701315e2bfa866324a83efa8"}, - {file = "pandas-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f908a77cbeef9bbd646bd4b81214cbef9ac3dda4181d5092a4aa9797d1bc7774"}, - {file = "pandas-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:713f2f70abcdade1ddd68fc91577cb090b3544b07ceba78a12f799355a13ee44"}, - {file = "pandas-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf3f0c361a4270185baa89ec7ab92ecaa355fe783791457077473f974f654df5"}, - {file = "pandas-2.0.2-cp39-cp39-win32.whl", hash = "sha256:598e9020d85a8cdbaa1815eb325a91cfff2bb2b23c1442549b8a3668e36f0f77"}, - {file = "pandas-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:77550c8909ebc23e56a89f91b40ad01b50c42cfbfab49b3393694a50549295ea"}, - {file = "pandas-2.0.2.tar.gz", hash = "sha256:dd5476b6c3fe410ee95926873f377b856dbc4e81a9c605a0dc05aaccc6a7c6c6"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, ] [package.dependencies] @@ -1284,7 +1925,7 @@ pytz = ">=2020.1" tzdata = ">=2022.1" [package.extras] -all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] aws = ["s3fs (>=2021.08.0)"] clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] @@ -1303,7 +1944,7 @@ plot = ["matplotlib (>=3.6.1)"] postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] spss = ["pyreadstat (>=1.1.2)"] sql-other = ["SQLAlchemy (>=1.4.16)"] -test = ["hypothesis (>=6.34.2)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +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]] @@ -1339,6 +1980,21 @@ mypy = ["pandas-stubs (<=1.4.3.220807)"] pyspark = ["pyspark (>=3.2.0)"] strategies = ["hypothesis (>=5.41.1)"] +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + [[package]] name = "partd" version = "1.4.0" @@ -1358,14 +2014,39 @@ toolz = "*" complete = ["blosc", "numpy (>=1.9.0)", "pandas (>=0.19.0)", "pyzmq"] [[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pickleshare" +version = "0.7.5" +description = "Tiny 'shelve'-like database with concurrency support" optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, ] [[package]] @@ -1379,36 +2060,176 @@ files = [ {file = "picobox-3.0.0.tar.gz", hash = "sha256:59d665ee82cafe2de80a6bf9dff407d502bb4688125398eaca05dbe02dbfb07a"}, ] +[[package]] +name = "pkginfo" +version = "1.9.6" +description = "Query metadata from sdists / bdists / installed packages." +optional = false +python-versions = ">=3.6" +files = [ + {file = "pkginfo-1.9.6-py3-none-any.whl", hash = "sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546"}, + {file = "pkginfo-1.9.6.tar.gz", hash = "sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046"}, +] + +[package.extras] +testing = ["pytest", "pytest-cov"] + [[package]] name = "platformdirs" -version = "3.5.3" +version = "3.10.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.3-py3-none-any.whl", hash = "sha256:0ade98a4895e87dc51d47151f7d2ec290365a585151d97b4d8d6312ed6132fed"}, - {file = "platformdirs-3.5.3.tar.gz", hash = "sha256:e48fabd87db8f3a7df7150a4a5ea22c546ee8bc39bc2473244730d4b56d2cc4e"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [package.extras] -docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.2.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "poetry" +version = "1.5.1" +description = "Python dependency management and packaging made easy." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "poetry-1.5.1-py3-none-any.whl", hash = "sha256:dfc7ce3a38ae216c0465694e2e674bef6eb1a2ba81aa47a26f9dc03362fe2f5f"}, + {file = "poetry-1.5.1.tar.gz", hash = "sha256:cc7ea4524d1a11558006224bfe8ba8ed071417d4eb5ef6c89decc6a37d437eeb"}, +] + +[package.dependencies] +build = ">=0.10.0,<0.11.0" +cachecontrol = {version = ">=0.12.9,<0.13.0", extras = ["filecache"]} +cleo = ">=2.0.0,<3.0.0" +crashtest = ">=0.4.1,<0.5.0" +dulwich = ">=0.21.2,<0.22.0" +filelock = ">=3.8.0,<4.0.0" +html5lib = ">=1.0,<2.0" +installer = ">=0.7.0,<0.8.0" +jsonschema = ">=4.10.0,<5.0.0" +keyring = ">=23.9.0,<24.0.0" +lockfile = ">=0.12.2,<0.13.0" +packaging = ">=20.4" +pexpect = ">=4.7.0,<5.0.0" +pkginfo = ">=1.9.4,<2.0.0" +platformdirs = ">=3.0.0,<4.0.0" +poetry-core = "1.6.1" +poetry-plugin-export = ">=1.4.0,<2.0.0" +pyproject-hooks = ">=1.0.0,<2.0.0" +requests = ">=2.18,<3.0" +requests-toolbelt = ">=0.9.1,<2" +shellingham = ">=1.5,<2.0" +tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.11.4,<1.0.0" +trove-classifiers = ">=2022.5.19" +urllib3 = ">=1.26.0,<2.0.0" +virtualenv = ">=20.22.0,<21.0.0" +xattr = {version = ">=0.10.0,<0.11.0", markers = "sys_platform == \"darwin\""} + +[[package]] +name = "poetry-core" +version = "1.6.1" +description = "Poetry PEP 517 Build Backend" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "poetry_core-1.6.1-py3-none-any.whl", hash = "sha256:70707340447dee0e7f334f9495ae652481c67b32d8d218f296a376ac2ed73573"}, + {file = "poetry_core-1.6.1.tar.gz", hash = "sha256:0f9b0de39665f36d6594657e7d57b6f463cc10f30c28e6d1c3b9ff54c26c9ac3"}, +] + +[[package]] +name = "poetry-dynamic-versioning" +version = "1.0.1" +description = "Plugin for Poetry to enable dynamic versioning based on VCS tags" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "poetry_dynamic_versioning-1.0.1-py3-none-any.whl", hash = "sha256:d0c07bf6a3cdd968e9a50882e862a58f5e71b582705ce19366ff5535c89217a0"}, + {file = "poetry_dynamic_versioning-1.0.1.tar.gz", hash = "sha256:d6a8c103bfea7f5d5bfc9330cb596fab6b26c3bd42d76f942dfa7e98acf76007"}, +] + +[package.dependencies] +dunamai = ">=1.18.0,<2.0.0" +jinja2 = ">=2.11.1,<4" +poetry = {version = ">=1.2.0,<2.0.0", optional = true, markers = "extra == \"plugin\""} +tomlkit = ">=0.4" + +[package.extras] +plugin = ["poetry (>=1.2.0,<2.0.0)"] + +[[package]] +name = "poetry-plugin-export" +version = "1.5.0" +description = "Poetry plugin to export the dependencies to various formats" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "poetry_plugin_export-1.5.0-py3-none-any.whl", hash = "sha256:cd8267597970375ca29868daec5e7718bad500c7584663af3eeb0ed16f24e2bd"}, + {file = "poetry_plugin_export-1.5.0.tar.gz", hash = "sha256:ecc8738da0c81c3758e36b4e72e04ae59648a547492af2ffe6245af3594bb00f"}, +] + +[package.dependencies] +poetry = ">=1.5.0,<2.0.0" +poetry-core = ">=1.6.0,<2.0.0" + +[[package]] +name = "prompt-toolkit" +version = "3.0.39" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "5.9.5" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + [[package]] name = "psycopg2" version = "2.9.7" @@ -1463,6 +2284,31 @@ files = [ {file = "ptvsd-4.3.2.zip", hash = "sha256:3b05c06018fdbce5943c50fb0baac695b5c11326f9e21a5266c854306bda28ab"}, ] +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + [[package]] name = "py" version = "1.11.0" @@ -1521,13 +2367,13 @@ pybtex = ">=0.16" [[package]] name = "pycodestyle" -version = "2.10.0" +version = "2.11.0" description = "Python style guide checker" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, - {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, + {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, + {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, ] [[package]] @@ -1543,47 +2389,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.9" +version = "1.10.12" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e692dec4a40bfb40ca530e07805b1208c1de071a18d26af4a2a0d79015b352ca"}, - {file = "pydantic-1.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c52eb595db83e189419bf337b59154bdcca642ee4b2a09e5d7797e41ace783f"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939328fd539b8d0edf244327398a667b6b140afd3bf7e347cf9813c736211896"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b48d3d634bca23b172f47f2335c617d3fcb4b3ba18481c96b7943a4c634f5c8d"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b7628fb8efe60fe66fd4adadd7ad2304014770cdc1f4934db41fe46cc8825f"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1aa5c2410769ca28aa9a7841b80d9d9a1c5f223928ca8bec7e7c9a34d26b1d4"}, - {file = "pydantic-1.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:eec39224b2b2e861259d6f3c8b6290d4e0fbdce147adb797484a42278a1a486f"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d111a21bbbfd85c17248130deac02bbd9b5e20b303338e0dbe0faa78330e37e0"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e9aec8627a1a6823fc62fb96480abe3eb10168fd0d859ee3d3b395105ae19a7"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07293ab08e7b4d3c9d7de4949a0ea571f11e4557d19ea24dd3ae0c524c0c334d"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee829b86ce984261d99ff2fd6e88f2230068d96c2a582f29583ed602ef3fc2c"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b466a23009ff5cdd7076eb56aca537c745ca491293cc38e72bf1e0e00de5b91"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7847ca62e581e6088d9000f3c497267868ca2fa89432714e21a4fb33a04d52e8"}, - {file = "pydantic-1.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:7845b31959468bc5b78d7b95ec52fe5be32b55d0d09983a877cca6aedc51068f"}, - {file = "pydantic-1.10.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:517a681919bf880ce1dac7e5bc0c3af1e58ba118fd774da2ffcd93c5f96eaece"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67195274fd27780f15c4c372f4ba9a5c02dad6d50647b917b6a92bf00b3d301a"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2196c06484da2b3fded1ab6dbe182bdabeb09f6318b7fdc412609ee2b564c49a"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6257bb45ad78abacda13f15bde5886efd6bf549dd71085e64b8dcf9919c38b60"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3283b574b01e8dbc982080d8287c968489d25329a463b29a90d4157de4f2baaf"}, - {file = "pydantic-1.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8bbaf4013b9a50e8100333cc4e3fa2f81214033e05ac5aa44fa24a98670a29"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9cd67fb763248cbe38f0593cd8611bfe4b8ad82acb3bdf2b0898c23415a1f82"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f50e1764ce9353be67267e7fd0da08349397c7db17a562ad036aa7c8f4adfdb6"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ef93e5e1d3c8e83f1ff2e7fdd026d9e063c7e089394869a6e2985696693766"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128d9453d92e6e81e881dd7e2484e08d8b164da5507f62d06ceecf84bf2e21d3"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad428e92ab68798d9326bb3e5515bc927444a3d71a93b4a2ca02a8a5d795c572"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fab81a92f42d6d525dd47ced310b0c3e10c416bbfae5d59523e63ea22f82b31e"}, - {file = "pydantic-1.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:963671eda0b6ba6926d8fc759e3e10335e1dc1b71ff2a43ed2efd6996634dafb"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:970b1bdc6243ef663ba5c7e36ac9ab1f2bfecb8ad297c9824b542d41a750b298"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e1d5290044f620f80cf1c969c542a5468f3656de47b41aa78100c5baa2b8276"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fcff3c7df7adff880622a98022626f4f6dbce6639a88a15a3ce0f96466cb60"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0da48717dc9495d3a8f215e0d012599db6b8092db02acac5e0d58a65248ec5bc"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0a2aabdc73c2a5960e87c3ffebca6ccde88665616d1fd6d3db3178ef427b267a"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9863b9420d99dfa9c064042304868e8ba08e89081428a1c471858aa2af6f57c4"}, - {file = "pydantic-1.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:e7c9900b43ac14110efa977be3da28931ffc74c27e96ee89fbcaaf0b0fe338e1"}, - {file = "pydantic-1.10.9-py3-none-any.whl", hash = "sha256:6cafde02f6699ce4ff643417d1a9223716ec25e228ddc3b436fe7e2d25a1f305"}, - {file = "pydantic-1.10.9.tar.gz", hash = "sha256:95c70da2cd3b6ddf3b9645ecaa8d98f3d80c606624b6d245558d202cd23ea3be"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, + {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, + {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, + {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, + {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, + {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, + {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, + {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, + {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, ] [package.dependencies] @@ -1595,24 +2441,24 @@ email = ["email-validator (>=1.0.3)"] [[package]] name = "pyflakes" -version = "3.0.1" +version = "3.1.0" description = "passive checker of Python programs" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"}, - {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, + {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, + {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, ] [[package]] name = "pygments" -version = "2.15.1" +version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, ] [package.extras] @@ -1620,13 +2466,13 @@ plugins = ["importlib-metadata"] [[package]] name = "pyjwt" -version = "2.7.0" +version = "2.8.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.7" files = [ - {file = "PyJWT-2.7.0-py3-none-any.whl", hash = "sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1"}, - {file = "PyJWT-2.7.0.tar.gz", hash = "sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074"}, + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, ] [package.extras] @@ -1636,41 +2482,19 @@ docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" +name = "pyproject-hooks" +version = "1.0.0" +description = "Wrappers to call pyproject.toml-based build backend hooks." optional = false python-versions = ">=3.7" files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, + {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"}, + {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"}, ] +[package.dependencies] +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "pytest" version = "6.2.5" @@ -1787,55 +2611,323 @@ files = [ {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, ] +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.2" +description = "A (partial) reimplementation of pywin32 using ctypes/cffi" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, + {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, +] + [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.6" files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyzmq" +version = "25.1.1" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"}, + {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"}, + {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"}, + {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"}, + {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"}, + {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"}, + {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"}, + {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"}, + {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"}, + {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"}, + {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"}, + {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"}, + {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"}, + {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"}, + {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"}, + {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"}, + {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"}, + {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"}, + {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"}, + {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"}, + {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"}, + {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"}, + {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"}, + {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"}, + {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"}, + {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"}, + {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "rapidfuzz" +version = "2.15.1" +description = "rapid fuzzy string matching" +optional = false +python-versions = ">=3.7" +files = [ + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc0bc259ebe3b93e7ce9df50b3d00e7345335d35acbd735163b7c4b1957074d3"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d59fb3a410d253f50099d7063855c2b95df1ef20ad93ea3a6b84115590899f25"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c525a3da17b6d79d61613096c8683da86e3573e807dfaecf422eea09e82b5ba6"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4deae6a918ecc260d0c4612257be8ba321d8e913ccb43155403842758c46fbe"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2577463d10811386e704a3ab58b903eb4e2a31b24dfd9886d789b0084d614b01"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f67d5f56aa48c0da9de4ab81bffb310683cf7815f05ea38e5aa64f3ba4368339"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7927722ff43690e52b3145b5bd3089151d841d350c6f8378c3cfac91f67573a"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6534afc787e32c4104f65cdeb55f6abe4d803a2d0553221d00ef9ce12788dcde"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d0ae6ec79a1931929bb9dd57bc173eb5ba4c7197461bf69e3a34b6dd314feed2"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be7ccc45c4d1a7dfb595f260e8022a90c6cb380c2a346ee5aae93f85c96d362b"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:8ba013500a2b68c64b2aecc5fb56a2dad6c2872cf545a0308fd044827b6e5f6a"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4d9f7d10065f657f960b48699e7dddfce14ab91af4bab37a215f0722daf0d716"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7e24a1b802cea04160b3fccd75d2d0905065783ebc9de157d83c14fb9e1c6ce2"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win32.whl", hash = "sha256:dffdf03499e0a5b3442951bb82b556333b069e0661e80568752786c79c5b32de"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d150d90a7c6caae7962f29f857a4e61d42038cfd82c9df38508daf30c648ae7"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win_arm64.whl", hash = "sha256:87c30e9184998ff6eb0fa9221f94282ce7c908fd0da96a1ef66ecadfaaa4cdb7"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6986413cb37035eb796e32f049cbc8c13d8630a4ac1e0484e3e268bb3662bd1b"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a72f26e010d4774b676f36e43c0fc8a2c26659efef4b3be3fd7714d3491e9957"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5cd54c98a387cca111b3b784fc97a4f141244bbc28a92d4bde53f164464112e"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7fac7c3da39f93e6b2ebe386ed0ffe1cefec91509b91857f6e1204509e931f"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f976e76ac72f650790b3a5402431612175b2ac0363179446285cb3c901136ca9"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:abde47e1595902a490ed14d4338d21c3509156abb2042a99e6da51f928e0c117"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca8f1747007a3ce919739a60fa95c5325f7667cccf6f1c1ef18ae799af119f5e"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c35da09ab9797b020d0d4f07a66871dfc70ea6566363811090353ea971748b5a"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3a769ca7580686a66046b77df33851b3c2d796dc1eb60c269b68f690f3e1b65"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d50622efefdb03a640a51a6123748cd151d305c1f0431af762e833d6ffef71f0"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b7461b0a7651d68bc23f0896bffceea40f62887e5ab8397bf7caa883592ef5cb"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:074ee9e17912e025c72a5780ee4c7c413ea35cd26449719cc399b852d4e42533"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7025fb105a11f503943f17718cdb8241ea3bb4d812c710c609e69bead40e2ff0"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win32.whl", hash = "sha256:2084d36b95139413cef25e9487257a1cc892b93bd1481acd2a9656f7a1d9930c"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:5a738fcd24e34bce4b19126b92fdae15482d6d3a90bd687fd3d24ce9d28ce82d"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:dc3cafa68cfa54638632bdcadf9aab89a3d182b4a3f04d2cad7585ed58ea8731"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c53d57ba7a88f7bf304d4ea5a14a0ca112db0e0178fff745d9005acf2879f7d"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6ee758eec4cf2215dc8d8eafafcea0d1f48ad4b0135767db1b0f7c5c40a17dd"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d93ba3ae59275e7a3a116dac4ffdb05e9598bf3ee0861fecc5b60fb042d539e"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c3ff75e647908ddbe9aa917fbe39a112d5631171f3fcea5809e2363e525a59d"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d89c421702474c6361245b6b199e6e9783febacdbfb6b002669e6cb3ef17a09"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f69e6199fec0f58f9a89afbbaea78d637c7ce77f656a03a1d6ea6abdc1d44f8"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:41dfea282844d0628279b4db2929da0dacb8ac317ddc5dcccc30093cf16357c1"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2dd03477feefeccda07b7659dd614f6738cfc4f9b6779dd61b262a73b0a9a178"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5efe035aa76ff37d1b5fa661de3c4b4944de9ff227a6c0b2e390a95c101814c0"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ed2cf7c69102c7a0a06926d747ed855bc836f52e8d59a5d1e3adfd980d1bd165"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a0e441d4c2025110ec3eba5d54f11f78183269a10152b3a757a739ffd1bb12bf"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-win32.whl", hash = "sha256:a4a54efe17cc9f53589c748b53f28776dfdfb9bc83619685740cb7c37985ac2f"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bb8318116ecac4dfb84841d8b9b461f9bb0c3be5b616418387d104f72d2a16d1"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e9296c530e544f68858c3416ad1d982a1854f71e9d2d3dcedb5b216e6d54f067"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:49c4bcdb9238f11f8c4eba1b898937f09b92280d6f900023a8216008f299b41a"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebb40a279e134bb3fef099a8b58ed5beefb201033d29bdac005bddcdb004ef71"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7381c11cb590bbd4e6f2d8779a0b34fdd2234dfa13d0211f6aee8ca166d9d05"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfdcdedfd12a0077193f2cf3626ff6722c5a184adf0d2d51f1ec984bf21c23c3"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85bece1ec59bda8b982bd719507d468d4df746dfb1988df11d916b5e9fe19e8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1b393f4a1eaa6867ffac6aef58cfb04bab2b3d7d8e40b9fe2cf40dd1d384601"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53de456ef020a77bf9d7c6c54860a48e2e902584d55d3001766140ac45c54bc7"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2492330bc38b76ed967eab7bdaea63a89b6ceb254489e2c65c3824efcbf72993"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:099e4c6befaa8957a816bdb67ce664871f10aaec9bebf2f61368cf7e0869a7a1"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:46599b2ad4045dd3f794a24a6db1e753d23304699d4984462cf1ead02a51ddf3"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:591f19d16758a3c55c9d7a0b786b40d95599a5b244d6eaef79c7a74fcf5104d8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed17359061840eb249f8d833cb213942e8299ffc4f67251a6ed61833a9f2ea20"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-win32.whl", hash = "sha256:aa1e5aad325168e29bf8e17006479b97024aa9d2fdbe12062bd2f8f09080acf8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:c2bb68832b140c551dbed691290bef4ee6719d4e8ce1b7226a3736f61a9d1a83"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fac40972cf7b6c14dded88ae2331eb50dfbc278aa9195473ef6fc6bfe49f686"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0e456cbdc0abf39352800309dab82fd3251179fa0ff6573fa117f51f4e84be8"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:22b9d22022b9d09fd4ece15102270ab9b6a5cfea8b6f6d1965c1df7e3783f5ff"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46754fe404a9a6f5cbf7abe02d74af390038d94c9b8c923b3f362467606bfa28"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91abb8bf7610efe326394adc1d45e1baca8f360e74187f3fa0ef3df80cdd3ba6"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e40a2f60024f9d3c15401e668f732800114a023f3f8d8c40f1521a62081ff054"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a48ee83916401ac73938526d7bd804e01d2a8fe61809df7f1577b0b3b31049a3"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71580052f9dbac443c02f60484e5a2e5f72ad4351b84b2009fbe345b1f38422"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:82b86d5b8c1b9bcbc65236d75f81023c78d06a721c3e0229889ff4ed5c858169"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fc4528b7736e5c30bc954022c2cf410889abc19504a023abadbc59cdf9f37cae"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e1e0e569108a5760d8f01d0f2148dd08cc9a39ead79fbefefca9e7c7723c7e88"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94e1c97f0ad45b05003806f8a13efc1fc78983e52fa2ddb00629003acf4676ef"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47e81767a962e41477a85ad7ac937e34d19a7d2a80be65614f008a5ead671c56"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win32.whl", hash = "sha256:79fc574aaf2d7c27ec1022e29c9c18f83cdaf790c71c05779528901e0caad89b"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:f3dd4bcef2d600e0aa121e19e6e62f6f06f22a89f82ef62755e205ce14727874"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win_arm64.whl", hash = "sha256:cac095cbdf44bc286339a77214bbca6d4d228c9ebae3da5ff6a80aaeb7c35634"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b89d1126be65c85763d56e3b47d75f1a9b7c5529857b4d572079b9a636eaa8a7"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7460e91168229768be882ea365ba0ac7da43e57f9416e2cfadc396a7df3c2"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c33c03e7092642c38f8a15ca2d8fc38da366f2526ec3b46adf19d5c7aa48ba"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040faca2e26d9dab5541b45ce72b3f6c0e36786234703fc2ac8c6f53bb576743"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6e2a3b23e1e9aa13474b3c710bba770d0dcc34d517d3dd6f97435a32873e3f28"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e597b9dfd6dd180982684840975c458c50d447e46928efe3e0120e4ec6f6686"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14752c9dd2036c5f36ebe8db5f027275fa7d6b3ec6484158f83efb674bab84e"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558224b6fc6124d13fa32d57876f626a7d6188ba2a97cbaea33a6ee38a867e31"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c89cfa88dc16fd8c9bcc0c7f0b0073f7ef1e27cceb246c9f5a3f7004fa97c4d"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:509c5b631cd64df69f0f011893983eb15b8be087a55bad72f3d616b6ae6a0f96"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0f73a04135a03a6e40393ecd5d46a7a1049d353fc5c24b82849830d09817991f"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c99d53138a2dfe8ada67cb2855719f934af2733d726fbf73247844ce4dd6dd5"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f01fa757f0fb332a1f045168d29b0d005de6c39ee5ce5d6c51f2563bb53c601b"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60368e1add6e550faae65614844c43f8a96e37bf99404643b648bf2dba92c0fb"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785744f1270828cc632c5a3660409dee9bcaac6931a081bae57542c93e4d46c4"}, + {file = "rapidfuzz-2.15.1.tar.gz", hash = "sha256:d62137c2ca37aea90a11003ad7dc109c8f1739bfbe5a9a217f3cdb07d7ac00f6"}, +] + +[package.extras] +full = ["numpy"] + +[[package]] +name = "referencing" +version = "0.30.2" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, + {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, ] +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "requests" version = "2.31.0" @@ -1857,6 +2949,20 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +description = "A utility belt for advanced users of python-requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, + {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, +] + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + [[package]] name = "rfc3986" version = "1.5.0" @@ -1875,66 +2981,166 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} idna2008 = ["idna"] [[package]] -name = "rtoml" -version = "0.8.0" -description = "A better TOML library for python implemented in rust." +name = "rpds-py" +version = "0.9.2" +description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.9.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7"}, + {file = "rpds_py-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f"}, + {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f"}, + {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f"}, + {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe"}, + {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6"}, + {file = "rpds_py-0.9.2-cp310-none-win32.whl", hash = "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764"}, + {file = "rpds_py-0.9.2-cp310-none-win_amd64.whl", hash = "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e"}, + {file = "rpds_py-0.9.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3"}, + {file = "rpds_py-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f"}, + {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d"}, + {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c"}, + {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae"}, + {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de"}, + {file = "rpds_py-0.9.2-cp311-none-win32.whl", hash = "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab"}, + {file = "rpds_py-0.9.2-cp311-none-win_amd64.whl", hash = "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298"}, + {file = "rpds_py-0.9.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386"}, + {file = "rpds_py-0.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238"}, + {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1"}, + {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b"}, + {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90"}, + {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d"}, + {file = "rpds_py-0.9.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d"}, + {file = "rpds_py-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55"}, + {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55"}, + {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d"}, + {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32"}, + {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e"}, + {file = "rpds_py-0.9.2-cp38-none-win32.whl", hash = "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920"}, + {file = "rpds_py-0.9.2-cp38-none-win_amd64.whl", hash = "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044"}, + {file = "rpds_py-0.9.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260"}, + {file = "rpds_py-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f"}, + {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324"}, + {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3"}, + {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535"}, + {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26"}, + {file = "rpds_py-0.9.2-cp39-none-win32.whl", hash = "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0"}, + {file = "rpds_py-0.9.2-cp39-none-win_amd64.whl", hash = "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67"}, + {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8"}, + {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03"}, + {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe"}, + {file = "rpds_py-0.9.2.tar.gz", hash = "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945"}, +] + +[[package]] +name = "secretstorage" +version = "3.3.3" +description = "Python bindings to FreeDesktop.org Secret Service API" +optional = false +python-versions = ">=3.6" +files = [ + {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, + {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, +] + +[package.dependencies] +cryptography = ">=2.0" +jeepney = ">=0.6" + +[[package]] +name = "self" +version = "2020.12.3" +description = "@self decorator makes method return self (jQuery-like chaining)" +optional = false +python-versions = "*" files = [ - {file = "rtoml-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e924ae37aeafd60d09b888ea30ae18bceac5086689216ab3ae16dd93692202a9"}, - {file = "rtoml-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:715bf814144f47306752b0ddf0965a1cf2e36410c3edc05fafe1363ba57fa2b6"}, - {file = "rtoml-0.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b11aefaaeab294bb98b3afa3a47d3f898378904e6a2b62fa1eca48caf1cfe878"}, - {file = "rtoml-0.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87da140716797198c9d011896c2b092ea5662d48d94059e705504b37131255a8"}, - {file = "rtoml-0.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b77916b8d0cea069b0b7b59eb40a7948fa2289eb7938546749b801290785632a"}, - {file = "rtoml-0.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c7fca6d6cd6182cf758c3b4b8554f6d548f9d921ba1cb91adb4aca779010cdfa"}, - {file = "rtoml-0.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9cbd99d158e440951f851613ce3b6f29c201676124900876937ebf65307c3a1"}, - {file = "rtoml-0.8.0-cp310-cp310-win32.whl", hash = "sha256:9708df41c348fa570cfaa9d62bfb46d14a1e7f3fe08203dab55fa22c1cd81a9f"}, - {file = "rtoml-0.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:9d93a2e9197ecda83765ed14661a933abf616de37442a8705ef6f1a897fa3299"}, - {file = "rtoml-0.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f494155b5321718d3e9afecf94c0ca02bba03fbae7ec1922ab14543694c1603"}, - {file = "rtoml-0.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc6d82e5a28fffd3910a54d511ba7adc66f668b0c25d0ee75685aeb24ce4a730"}, - {file = "rtoml-0.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d0f46641b4ac2e6934801d29c6c4c6f2bda017b34482aeb8f8170b977a60b17"}, - {file = "rtoml-0.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb2a996587e39359ec1b638fa74d1247b7adebe4f804d03d1c681c064b0ae24c"}, - {file = "rtoml-0.8.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a7846ed05136de9ec60f5ee5bb6a53c640f7e0504bd9ec3586016cb6cf36ea2b"}, - {file = "rtoml-0.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2883cd30caac29c8f00dd8c7f20ee7cade778aba1413bea3c8e0fa6013581c9c"}, - {file = "rtoml-0.8.0-cp37-cp37m-win32.whl", hash = "sha256:4ce8bb6ea93ce1ce2de7a48bed47a290fcf6adf8d427768397512f4d9a107461"}, - {file = "rtoml-0.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0eea2ed0d724df91b230c89653a021fc0e22b1353d9a567d166093104cbe8e0c"}, - {file = "rtoml-0.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:71a6ed08313755891a8341007892f4738e624a25f757136deea7a1c75862254e"}, - {file = "rtoml-0.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77173831317fc493752ddcc3c4ce20d6c322bbffbe4bcb3131a78fc6ca63a8a9"}, - {file = "rtoml-0.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffbfa5ae5b88991f88a8a8f06aeb572f7d5ec4811ee101ba90493754be3df677"}, - {file = "rtoml-0.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5502507da47e142013e316133eaa0c0312c351aed9c02e51104dd9fc725b0925"}, - {file = "rtoml-0.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97fc53d7bb277ef379c919a5972e5faa403c7d41951c0e6fd57e00ad470ea992"}, - {file = "rtoml-0.8.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:617b57d9254c83d09646b8f6062a7da066c23b1999a63788f894a16707b710a7"}, - {file = "rtoml-0.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3773957d1a67d5620d64f73e855fd81de01fac5aff14d643cb5821854633c6d4"}, - {file = "rtoml-0.8.0-cp38-cp38-win32.whl", hash = "sha256:a2a743456652d881f4baf61e593f1b131500f03d7d9aa55c41812d8737624aa0"}, - {file = "rtoml-0.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:1cc362b02d586721ec3b24cf1f6e9da0223fc2009dfa5b49b929e7d2c6fbaaf7"}, - {file = "rtoml-0.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:10d0f771558b8f8c0940e517f089cbea5f1ddfa8d684c176ac6c3a1797b50f19"}, - {file = "rtoml-0.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a42c8faf9d7ea40a86ac8cb73d0e485467d4702fcc3b763276a046d9b6cd738e"}, - {file = "rtoml-0.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f84b83a852ac8f8efca56490cd21eb53c55a116dd2485658f0ced2ee99e0b09f"}, - {file = "rtoml-0.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9de660acc172db507321498275c8c8f052c6d3261331eb5aa964447bfecc90d1"}, - {file = "rtoml-0.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccc9fdd7064b1c8a990548956e27a3217c7a692e8bae222af8cdb3d0750dddf6"}, - {file = "rtoml-0.8.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ce59d9e077030a2bfc915ebb872d15532e61e57d967075ab978b76b933b9634"}, - {file = "rtoml-0.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:88a2187059be67a94e59519a91785f43db3159f2963ea8e15c31808a95b58c9f"}, - {file = "rtoml-0.8.0-cp39-cp39-win32.whl", hash = "sha256:fb106a90e1dc55e9fe2774b41d57074f02a716aac864a58fedca2cf399114f29"}, - {file = "rtoml-0.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:333e5e1fc257b1302f589b662fd2405ec4b3b68a032e125011bcf86ea52b19eb"}, - {file = "rtoml-0.8.0.tar.gz", hash = "sha256:6d55fa9df88256c6762f01f18b8bd3f6dc1836600ea8655eb3719a2b8f3df764"}, + {file = "self-2020.12.3.tar.gz", hash = "sha256:a0c408138257e0ba6188f2a7ad80cb3f61c3e48c3f85d1f973a160f6f887dc53"}, ] +[package.dependencies] +decorator = "*" + [[package]] name = "setuptools" -version = "67.8.0" +version = "68.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, - {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, + {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, + {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "shellingham" +version = "1.5.3" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.3-py2.py3-none-any.whl", hash = "sha256:419c6a164770c9c7cfcaeddfacb3d31ac7a8db0b0f3e9c1287679359734107e9"}, + {file = "shellingham-1.5.3.tar.gz", hash = "sha256:cb4a6fec583535bc6da17b647dd2330cf7ef30239e05d547d99ae3705fd0f7f8"}, +] + [[package]] name = "six" version = "1.16.0" @@ -2067,15 +3273,18 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.4" +version = "1.0.7" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, - {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, + {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, + {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, ] +[package.dependencies] +Sphinx = ">=5" + [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] @@ -2099,30 +3308,36 @@ Sphinx = ">=2.1" [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +version = "1.0.5" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, + {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, + {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, ] +[package.dependencies] +Sphinx = ">=5" + [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.1" +version = "2.0.4" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, - {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, + {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, + {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, ] +[package.dependencies] +Sphinx = ">=5" + [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["html5lib", "pytest"] @@ -2192,91 +3407,97 @@ sphinxcontrib-httpdomain = ">=1.5.0" [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +version = "1.0.6" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, + {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, + {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, ] +[package.dependencies] +Sphinx = ">=5" + [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.5" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +version = "1.1.9" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, + {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"}, + {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"}, ] +[package.dependencies] +Sphinx = ">=5" + [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sqlalchemy" -version = "2.0.16" +version = "2.0.20" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7641f6ed2682de84d77c4894cf2e43700f3cf7a729361d7f9cac98febf3d8614"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8d3cbdb2f07fb0e4b897dc1df39166735e194fb946f28f26f4c9f9801c8b24f7"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08a791c75d6154d46914d1e23bd81d9455f2950ec1de81f2723848c593d2c8b"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91eb8f89fcce8f709f8a4d65d265bc48a80264ee14c7c9e955f3222f19b4b39c"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fc1dae11bd5167f9eb53b3ccad24a79813004612141e76de21cf4c028dc30b34"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b2801f85c5c0293aa710f8aa5262c707a83c1c203962ae5a22b4d9095e71aa9d"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-win32.whl", hash = "sha256:c5e333b81fe10d14efebd4e9429b7bb865ed9463ca8bef07a7136dfa1fd4a37b"}, - {file = "SQLAlchemy-2.0.16-cp310-cp310-win_amd64.whl", hash = "sha256:f387b496a4c9474d8580195bb2660264a3f295a04d3a9d00f4fa15e9e597427e"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7be04dbe3470fe8dd332fdb48c979887c381ef6c635eddf2dec43d2766111be4"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2938edc512dd1fa48653e14c1655ab46144d4450f0e6b33da7acd8ba77fbfd7"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a2856e12cf5f54301ddf043bcbf0552561d61555e1bcf348b63f42b8e1eec2"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d320fde566b864adbc19abb40ecb80f4e25d6f084639969bb972d5cca16858"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e85e315725807c127ad8ba3d628fdb861cf9ebfb0e10c39a97c01e257cdd71b"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:63ea36c08792a7a8a08958bc806ecff6b491386feeaf14607c3d9d2d9325e67f"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-win32.whl", hash = "sha256:bdaf89dd82f4a0e1b8b5ffc9cdc0c9551be6175f7eee5af6a838e92ba2e57100"}, - {file = "SQLAlchemy-2.0.16-cp311-cp311-win_amd64.whl", hash = "sha256:5a934eff1a2882137be3384826f997db8441d43b61fda3094923e69fffe474be"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fbcc51fdbc89fafe4f4fe66f59372a8be88ded04de34ef438ab04f980beb12d4"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff6496ad5e9dc8baeb93a151cc2f599d01e5f8928a2aaf0b09a06428fdbaf553"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d6ef848e5afcd1bda3e9a843751f845c0ca888b61e669237680e913d84ec206"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3ef876615ff4b53e2033022195830ec4941a6e21068611f8d77de60203b90a98"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8544c6e62eacb77d5106e2055ef10f2407fc0dbd547e879f8745b2032eefd2bc"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-win32.whl", hash = "sha256:2f3b6c31b915159b96b68372212fa77f69230b0a32acab40cf539d2823954f5a"}, - {file = "SQLAlchemy-2.0.16-cp37-cp37m-win_amd64.whl", hash = "sha256:d0c96592f54edd571e00ba6b1ed5df8263328ca1da9e78088c0ebc93c2e6562c"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a2e9f50a906d0b81292576a9fb458f8cace904c81a67088f4a2ca9ff2856f55d"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dc97238fa44be86971270943a0c21c19ce18b8d1596919048e57912e8abc02cc"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0db6734cb5644c55d0262a813b764c6e2cda1e66e939a488b3d6298cdc7344c2"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:131f0c894c6572cb1bdcf97c92d999d3128c4ff1ca13061296057072f61afe13"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f662cf69484c59f8a3435902c40dfc34d86050bdb15e23d437074ce9f153306b"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b72f4e4def50414164a1d899f2ce4e782a029fad0ed5585981d1611e8ae29a74"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-win32.whl", hash = "sha256:0e4645b260cfe375a0603aa117f0a47680864cf37833129da870919e88b08d8f"}, - {file = "SQLAlchemy-2.0.16-cp38-cp38-win_amd64.whl", hash = "sha256:f409f35a0330ab0cb18ece736b86d8b8233c64f4461fcb10993f67afc0ac7e5a"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e19546924f0cf2ec930d1faf318b7365e5827276410a513340f31a2b423e96a4"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ce1fc3f64fd42d5f763d6b83651471f32920338a1ba107a3186211474861af57"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e2569dac4e3cb85365b91ab569d06a221e0e17e65ce59949d00c3958946282b"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61f2035dea56ff1a429077e481496f813378beb02b823d2e3e7eb05bc1a7a8ca"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:81d867c1be5abd49f7e547c108391f371a9d980ba7ec34666c50d683f782b754"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2de1477af7f48c633b8ecb88245aedd811dca88e88aee9e9d787b388abe74c44"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-win32.whl", hash = "sha256:5e8522b49e0e640287308b68f71cc338446bbe1c226c8f81743baa91b0246e92"}, - {file = "SQLAlchemy-2.0.16-cp39-cp39-win_amd64.whl", hash = "sha256:43e69c8c1cea0188b7094e22fb93ae1a1890aac748628b7e925024a206f75368"}, - {file = "SQLAlchemy-2.0.16-py3-none-any.whl", hash = "sha256:53081c6fce0d49bb36d05f12dc87e008c9b0df58a163b792c5fc4ac638925f98"}, - {file = "SQLAlchemy-2.0.16.tar.gz", hash = "sha256:1e2caba78e7d1f5003e88817b7a1754d4e58f4a8f956dc423bf8e304c568ab09"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} + {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759b51346aa388c2e606ee206c0bc6f15a5299f6174d1e10cadbe4530d3c7a98"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1506e988ebeaaf316f183da601f24eedd7452e163010ea63dbe52dc91c7fc70e"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5768c268df78bacbde166b48be788b83dddaa2a5974b8810af422ddfe68a9bc8"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3f0dd6d15b6dc8b28a838a5c48ced7455c3e1fb47b89da9c79cc2090b072a50"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:243d0fb261f80a26774829bc2cee71df3222587ac789b7eaf6555c5b15651eed"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb6d77c31e1bf4268b4d61b549c341cbff9842f8e115ba6904249c20cb78a61"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-win32.whl", hash = "sha256:bcb04441f370cbe6e37c2b8d79e4af9e4789f626c595899d94abebe8b38f9a4d"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-win_amd64.whl", hash = "sha256:d32b5ffef6c5bcb452723a496bad2d4c52b346240c59b3e6dba279f6dcc06c14"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd81466bdbc82b060c3c110b2937ab65ace41dfa7b18681fdfad2f37f27acdd7"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6fe7d61dc71119e21ddb0094ee994418c12f68c61b3d263ebaae50ea8399c4d4"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4e571af672e1bb710b3cc1a9794b55bce1eae5aed41a608c0401885e3491179"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3364b7066b3c7f4437dd345d47271f1251e0cfb0aba67e785343cdbdb0fff08c"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1be86ccea0c965a1e8cd6ccf6884b924c319fcc85765f16c69f1ae7148eba64b"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1d35d49a972649b5080557c603110620a86aa11db350d7a7cb0f0a3f611948a0"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-win32.whl", hash = "sha256:27d554ef5d12501898d88d255c54eef8414576f34672e02fe96d75908993cf53"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-win_amd64.whl", hash = "sha256:411e7f140200c02c4b953b3dbd08351c9f9818d2bd591b56d0fa0716bd014f1e"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c6aceebbc47db04f2d779db03afeaa2c73ea3f8dcd3987eb9efdb987ffa09a3"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d3f175410a6db0ad96b10bfbb0a5530ecd4fcf1e2b5d83d968dd64791f810ed"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8186be85da6587456c9ddc7bf480ebad1a0e6dcbad3967c4821233a4d4df57"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c3d99ba99007dab8233f635c32b5cd24fb1df8d64e17bc7df136cedbea427897"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:76fdfc0f6f5341987474ff48e7a66c3cd2b8a71ddda01fa82fedb180b961630a"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-win32.whl", hash = "sha256:d3793dcf5bc4d74ae1e9db15121250c2da476e1af8e45a1d9a52b1513a393459"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-win_amd64.whl", hash = "sha256:79fde625a0a55220d3624e64101ed68a059c1c1f126c74f08a42097a72ff66a9"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:599ccd23a7146e126be1c7632d1d47847fa9f333104d03325c4e15440fc7d927"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1a58052b5a93425f656675673ef1f7e005a3b72e3f2c91b8acca1b27ccadf5f4"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79543f945be7a5ada9943d555cf9b1531cfea49241809dd1183701f94a748624"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63e73da7fb030ae0a46a9ffbeef7e892f5def4baf8064786d040d45c1d6d1dc5"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ce5e81b800a8afc870bb8e0a275d81957e16f8c4b62415a7b386f29a0cb9763"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb0d3e94c2a84215532d9bcf10229476ffd3b08f481c53754113b794afb62d14"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-win32.whl", hash = "sha256:8dd77fd6648b677d7742d2c3cc105a66e2681cc5e5fb247b88c7a7b78351cf74"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-win_amd64.whl", hash = "sha256:6f8a934f9dfdf762c844e5164046a9cea25fabbc9ec865c023fe7f300f11ca4a"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:26a3399eaf65e9ab2690c07bd5cf898b639e76903e0abad096cd609233ce5208"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4cde2e1096cbb3e62002efdb7050113aa5f01718035ba9f29f9d89c3758e7e4e"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b09ba72e4e6d341bb5bdd3564f1cea6095d4c3632e45dc69375a1dbe4e26ec"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b74eeafaa11372627ce94e4dc88a6751b2b4d263015b3523e2b1e57291102f0"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:77d37c1b4e64c926fa3de23e8244b964aab92963d0f74d98cbc0783a9e04f501"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eefebcc5c555803065128401a1e224a64607259b5eb907021bf9b175f315d2a6"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-win32.whl", hash = "sha256:3423dc2a3b94125094897118b52bdf4d37daf142cbcf26d48af284b763ab90e9"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-win_amd64.whl", hash = "sha256:5ed61e3463021763b853628aef8bc5d469fe12d95f82c74ef605049d810f3267"}, + {file = "SQLAlchemy-2.0.20-py3-none-any.whl", hash = "sha256:63a368231c53c93e2b67d0c5556a9836fdcd383f7e3026a39602aad775b14acf"}, + {file = "SQLAlchemy-2.0.20.tar.gz", hash = "sha256:ca8a5ff2aa7f3ade6c498aaafce25b1eaeabe4e42b73e25519183e4566a16fc6"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} mypy = {version = ">=0.910", optional = true, markers = "extra == \"mypy\""} typing-extensions = ">=4.2.0" [package.extras] -aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] @@ -2327,6 +3548,25 @@ test-all = ["Babel (>=1.3)", "Jinja2 (>=2.3)", "Pygments (>=1.2)", "arrow (>=0.3 timezone = ["python-dateutil"] url = ["furl (>=0.4.1)"] +[[package]] +name = "stack-data" +version = "0.6.2" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, + {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + [[package]] name = "starlette" version = "0.26.1" @@ -2366,6 +3606,17 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tomlkit" +version = "0.12.1" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, +] + [[package]] name = "toolz" version = "0.12.0" @@ -2379,22 +3630,48 @@ files = [ [[package]] name = "tornado" -version = "6.3.2" +version = "6.3.3" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">= 3.8" files = [ - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"}, - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"}, - {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"}, - {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"}, - {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, + {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, + {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, + {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, +] + +[[package]] +name = "traitlets" +version = "5.9.0" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.7" +files = [ + {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, + {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] + +[[package]] +name = "trove-classifiers" +version = "2023.8.7" +description = "Canonical source for classifiers on PyPI (pypi.org)." +optional = false +python-versions = "*" +files = [ + {file = "trove-classifiers-2023.8.7.tar.gz", hash = "sha256:c9f2a0a85d545e5362e967e4f069f56fddfd91215e22ffa48c66fb283521319a"}, + {file = "trove_classifiers-2023.8.7-py3-none-any.whl", hash = "sha256:a676626a31286130d56de2ea1232484df97c567eb429d56cfcb0637e681ecf09"}, ] [[package]] @@ -2417,15 +3694,26 @@ dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2 doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"] test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +[[package]] +name = "types-toml" +version = "0.10.8.7" +description = "Typing stubs for toml" +optional = false +python-versions = "*" +files = [ + {file = "types-toml-0.10.8.7.tar.gz", hash = "sha256:58b0781c681e671ff0b5c0319309910689f4ab40e8a2431e205d70c94bb6efb1"}, + {file = "types_toml-0.10.8.7-py3-none-any.whl", hash = "sha256:61951da6ad410794c97bec035d59376ce1cbf4453dc9b6f90477e81e4442d631"}, +] + [[package]] name = "typing-extensions" -version = "4.6.3" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] @@ -2456,20 +3744,19 @@ files = [ [[package]] name = "urllib3" -version = "2.0.3" +version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"}, - {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"}, + {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, + {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "uvicorn" @@ -2541,6 +3828,26 @@ dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flak docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"] +[[package]] +name = "virtualenv" +version = "20.24.3" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"}, + {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<4" + +[package.extras] +docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "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 = "watchgod" version = "0.8.2" @@ -2555,6 +3862,28 @@ files = [ [package.dependencies] anyio = ">=3.0.0,<4" +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + [[package]] name = "websockets" version = "11.0.3" @@ -2718,22 +4047,106 @@ files = [ {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, ] +[[package]] +name = "xattr" +version = "0.10.1" +description = "Python wrapper for extended filesystem attributes" +optional = false +python-versions = "*" +files = [ + {file = "xattr-0.10.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:16a660a883e703b311d1bbbcafc74fa877585ec081cd96e8dd9302c028408ab1"}, + {file = "xattr-0.10.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1e2973e72faa87ca29d61c23b58c3c89fe102d1b68e091848b0e21a104123503"}, + {file = "xattr-0.10.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:13279fe8f7982e3cdb0e088d5cb340ce9cbe5ef92504b1fd80a0d3591d662f68"}, + {file = "xattr-0.10.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1dc9b9f580ef4b8ac5e2c04c16b4d5086a611889ac14ecb2e7e87170623a0b75"}, + {file = "xattr-0.10.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:485539262c2b1f5acd6b6ea56e0da2bc281a51f74335c351ea609c23d82c9a79"}, + {file = "xattr-0.10.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:295b3ab335fcd06ca0a9114439b34120968732e3f5e9d16f456d5ec4fa47a0a2"}, + {file = "xattr-0.10.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:a126eb38e14a2f273d584a692fe36cff760395bf7fc061ef059224efdb4eb62c"}, + {file = "xattr-0.10.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:b0e919c24f5b74428afa91507b15e7d2ef63aba98e704ad13d33bed1288dca81"}, + {file = "xattr-0.10.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:e31d062cfe1aaeab6ba3db6bd255f012d105271018e647645941d6609376af18"}, + {file = "xattr-0.10.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:209fb84c09b41c2e4cf16dd2f481bb4a6e2e81f659a47a60091b9bcb2e388840"}, + {file = "xattr-0.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c4120090dac33eddffc27e487f9c8f16b29ff3f3f8bcb2251b2c6c3f974ca1e1"}, + {file = "xattr-0.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3e739d624491267ec5bb740f4eada93491de429d38d2fcdfb97b25efe1288eca"}, + {file = "xattr-0.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2677d40b95636f3482bdaf64ed9138fb4d8376fb7933f434614744780e46e42d"}, + {file = "xattr-0.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40039f1532c4456fd0f4c54e9d4e01eb8201248c321c6c6856262d87e9a99593"}, + {file = "xattr-0.10.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:148466e5bb168aba98f80850cf976e931469a3c6eb11e9880d9f6f8b1e66bd06"}, + {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0aedf55b116beb6427e6f7958ccd80a8cbc80e82f87a4cd975ccb61a8d27b2ee"}, + {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c3024a9ff157247c8190dd0eb54db4a64277f21361b2f756319d9d3cf20e475f"}, + {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f1be6e733e9698f645dbb98565bb8df9b75e80e15a21eb52787d7d96800e823b"}, + {file = "xattr-0.10.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7880c8a54c18bc091a4ce0adc5c6d81da1c748aec2fe7ac586d204d6ec7eca5b"}, + {file = "xattr-0.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:89c93b42c3ba8aedbc29da759f152731196c2492a2154371c0aae3ef8ba8301b"}, + {file = "xattr-0.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b905e808df61b677eb972f915f8a751960284358b520d0601c8cbc476ba2df6"}, + {file = "xattr-0.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ef954d0655f93a34d07d0cc7e02765ec779ff0b59dc898ee08c6326ad614d5"}, + {file = "xattr-0.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:199b20301b6acc9022661412346714ce764d322068ef387c4de38062474db76c"}, + {file = "xattr-0.10.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec0956a8ab0f0d3f9011ba480f1e1271b703d11542375ef73eb8695a6bd4b78b"}, + {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffcb57ca1be338d69edad93cf59aac7c6bb4dbb92fd7bf8d456c69ea42f7e6d2"}, + {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f0563196ee54756fe2047627d316977dc77d11acd7a07970336e1a711e934db"}, + {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc354f086f926a1c7f04886f97880fed1a26d20e3bc338d0d965fd161dbdb8ab"}, + {file = "xattr-0.10.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c0cd2d02ef2fb45ecf2b0da066a58472d54682c6d4f0452dfe7ae2f3a76a42ea"}, + {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49626096ddd72dcc1654aadd84b103577d8424f26524a48d199847b5d55612d0"}, + {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ceaa26bef8fcb17eb59d92a7481c2d15d20211e217772fb43c08c859b01afc6a"}, + {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c014c371391f28f8cd27d73ea59f42b30772cd640b5a2538ad4f440fd9190b"}, + {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:46c32cd605673606b9388a313b0050ee7877a0640d7561eea243ace4fa2cc5a6"}, + {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:772b22c4ff791fe5816a7c2a1c9fcba83f9ab9bea138eb44d4d70f34676232b4"}, + {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:183ad611a2d70b5a3f5f7aadef0fcef604ea33dcf508228765fd4ddac2c7321d"}, + {file = "xattr-0.10.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8068df3ebdfa9411e58d5ae4a05d807ec5994645bb01af66ec9f6da718b65c5b"}, + {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bc40570155beb85e963ae45300a530223d9822edfdf09991b880e69625ba38a"}, + {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:436e1aaf23c07e15bed63115f1712d2097e207214fc6bcde147c1efede37e2c5"}, + {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7298455ccf3a922d403339781b10299b858bb5ec76435445f2da46fb768e31a5"}, + {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:986c2305c6c1a08f78611eb38ef9f1f47682774ce954efb5a4f3715e8da00d5f"}, + {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5dc6099e76e33fa3082a905fe59df766b196534c705cf7a2e3ad9bed2b8a180e"}, + {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:042ad818cda6013162c0bfd3816f6b74b7700e73c908cde6768da824686885f8"}, + {file = "xattr-0.10.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9d4c306828a45b41b76ca17adc26ac3dc00a80e01a5ba85d71df2a3e948828f2"}, + {file = "xattr-0.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a606280b0c9071ef52572434ecd3648407b20df3d27af02c6592e84486b05894"}, + {file = "xattr-0.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5b49d591cf34cda2079fd7a5cb2a7a1519f54dc2e62abe3e0720036f6ed41a85"}, + {file = "xattr-0.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8705ac6791426559c1a5c2b88bb2f0e83dc5616a09b4500899bfff6a929302"}, + {file = "xattr-0.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5ea974930e876bc5c146f54ac0f85bb39b7b5de2b6fc63f90364712ae368ebe"}, + {file = "xattr-0.10.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f55a2dd73a12a1ae5113c5d9cd4b4ab6bf7950f4d76d0a1a0c0c4264d50da61d"}, + {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:475c38da0d3614cc5564467c4efece1e38bd0705a4dbecf8deeb0564a86fb010"}, + {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:925284a4a28e369459b2b7481ea22840eed3e0573a4a4c06b6b0614ecd27d0a7"}, + {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa32f1b45fed9122bed911de0fcc654da349e1f04fa4a9c8ef9b53e1cc98b91e"}, + {file = "xattr-0.10.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c5d3d0e728bace64b74c475eb4da6148cd172b2d23021a1dcd055d92f17619ac"}, + {file = "xattr-0.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8faaacf311e2b5cc67c030c999167a78a9906073e6abf08eaa8cf05b0416515c"}, + {file = "xattr-0.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6b8d5ca452674e1a96e246a3d2db5f477aecbc7c945c73f890f56323e75203"}, + {file = "xattr-0.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3725746a6502f40f72ef27e0c7bfc31052a239503ff3eefa807d6b02a249be22"}, + {file = "xattr-0.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:789bd406d1aad6735e97b20c6d6a1701e1c0661136be9be862e6a04564da771f"}, + {file = "xattr-0.10.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9a7a807ab538210ff8532220d8fc5e2d51c212681f63dbd4e7ede32543b070f"}, + {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e5825b5fc99ecdd493b0cc09ec35391e7a451394fdf623a88b24726011c950d"}, + {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80638d1ce7189dc52f26c234cee3522f060fadab6a8bc3562fe0ddcbe11ba5a4"}, + {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3ff0dbe4a6ce2ce065c6de08f415bcb270ecfd7bf1655a633ddeac695ce8b250"}, + {file = "xattr-0.10.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5267e5f9435c840d2674194150b511bef929fa7d3bc942a4a75b9eddef18d8d8"}, + {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b27dfc13b193cb290d5d9e62f806bb9a99b00cd73bb6370d556116ad7bb5dc12"}, + {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:636ebdde0277bce4d12d2ef2550885804834418fee0eb456b69be928e604ecc4"}, + {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d60c27922ec80310b45574351f71e0dd3a139c5295e8f8b19d19c0010196544f"}, + {file = "xattr-0.10.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b34df5aad035d0343bd740a95ca30db99b776e2630dca9cc1ba8e682c9cc25ea"}, + {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f24a7c04ff666d0fe905dfee0a84bc899d624aeb6dccd1ea86b5c347f15c20c1"}, + {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3878e1aff8eca64badad8f6d896cb98c52984b1e9cd9668a3ab70294d1ef92d"}, + {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4abef557028c551d59cf2fb3bf63f2a0c89f00d77e54c1c15282ecdd56943496"}, + {file = "xattr-0.10.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0e14bd5965d3db173d6983abdc1241c22219385c22df8b0eb8f1846c15ce1fee"}, + {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f9be588a4b6043b03777d50654c6079af3da60cc37527dbb80d36ec98842b1e"}, + {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bc4ae264aa679aacf964abf3ea88e147eb4a22aea6af8c6d03ebdebd64cfd6"}, + {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:827b5a97673b9997067fde383a7f7dc67342403093b94ea3c24ae0f4f1fec649"}, + {file = "xattr-0.10.1.tar.gz", hash = "sha256:c12e7d81ffaa0605b3ac8c22c2994a8e18a9cf1c59287a1b7722a2289c952ec5"}, +] + +[package.dependencies] +cffi = ">=1.0" + [[package]] name = "zipp" -version = "3.15.0" +version = "3.16.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +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-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" python-versions = "~3.10" -content-hash = "1c38dacc453060c6bbdf7428f177403e9ce9fe68a0d7190f0b7762272afacb03" +content-hash = "e2658fa71a907ba3c9d21824a925fab2e2712ba654e8b8740a58ffc1d8bb3dbc" diff --git a/pyproject.toml b/pyproject.toml index 49134926..16512dc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,9 +31,11 @@ pydantic = "^1.10.5" python = "~3.10" python-dotenv = "^0.19.0" requests = "^2.27.1" -rtoml = "^0.8.0" typer = "^0.4.0" +toml = "^0.10.2" psycopg2 = "^2.9.7" +self = "^2020.12.3" +poetry-dynamic-versioning = {extras = ["plugin"], version = "^1.0.1"} [tool.poetry.group.docs] optional = true @@ -59,7 +61,7 @@ optional = true black = "^23.1.0" flake8 = "^6.0.0" flake8-bugbear = "^21.9.2" -mypy = "^1.0.1" +mypy = "~1.0.1" flake8-pyproject = "^1.2.2" ptvsd = "^4.3.2" pytest = "^6.2.5" @@ -67,6 +69,13 @@ pytest-benchmark = "^3.4.1" pytest-cov = "^2.12.1" pytest-lazy-fixture = "^0.6.3" snakeviz = "^2.1.1" +types-toml = "^0.10.8.7" + +[tool.poetry.group.tutorial] +optional = true + +[tool.poetry.group.tutorial.dependencies] +ipykernel = "^6.23.3" [tool.poetry.scripts] ixmp4 = "ixmp4.__main__:app" diff --git a/tests/conf/test_toml.py b/tests/conf/test_toml.py new file mode 100644 index 00000000..5013c823 --- /dev/null +++ b/tests/conf/test_toml.py @@ -0,0 +1,95 @@ +import tempfile +import pytest +from typing import Protocol +from pathlib import Path + +from ixmp4.conf.toml import TomlConfig +from ixmp4.conf.credentials import Credentials +from ixmp4.conf.user import local_user +from ixmp4.core.exceptions import PlatformNotUnique, PlatformNotFound + + +@pytest.fixture(scope="class") +def toml_config() -> TomlConfig: + tmp = tempfile.NamedTemporaryFile() + with tmp: + config = TomlConfig(Path(tmp.name), local_user) + yield config + + +class HasPath(Protocol): + path: Path + + +class TomlTest: + def assert_toml_file(self, toml_config: HasPath, expected_toml: str): + with toml_config.path.open() as f: + assert f.read() == expected_toml + + +class TestTomlPlatforms(TomlTest): + def test_add_platform(self, toml_config: TomlConfig): + toml_config.add_platform("test", "test://test/") + + expected_toml = '[test]\ndsn = "test://test/"\n' + self.assert_toml_file(toml_config, expected_toml) + + toml_config.add_platform("test2", "test2://test2/") + + expected_toml = ( + '[test]\ndsn = "test://test/"\n\n' '[test2]\ndsn = "test2://test2/"\n' + ) + self.assert_toml_file(toml_config, expected_toml) + + def test_platform_unique(self, toml_config: TomlConfig): + with pytest.raises(PlatformNotUnique): + toml_config.add_platform("test", "test://test/") + + def test_remove_platform(self, toml_config: TomlConfig): + toml_config.remove_platform("test") + expected_toml = '[test2]\ndsn = "test2://test2/"\n' + + with toml_config.path.open() as f: + assert f.read() == expected_toml + + toml_config.remove_platform("test2") + expected_toml = "" + + with toml_config.path.open() as f: + assert f.read() == expected_toml + + def test_remove_missing_platform(self, toml_config: TomlConfig): + with pytest.raises(PlatformNotFound): + toml_config.remove_platform("test") + + +@pytest.fixture(scope="class") +def credentials() -> Credentials: + tmp = tempfile.NamedTemporaryFile() + with tmp: + credentials = Credentials(Path(tmp.name)) + yield credentials + + +class TestTomlCredentials(TomlTest): + def test_set_credentials(self, credentials): + credentials.set("test", "user", "password") + expected_toml = '[test]\nusername = "user"\npassword = "password"\n' + self.assert_toml_file(credentials, expected_toml) + + def test_get_credentials(self, credentials): + ret = credentials.get("test") + assert ret == ("user", "password") + + def test_clear_credentials(self, credentials): + credentials.clear("test") + expected_toml = "" + self.assert_toml_file(credentials, expected_toml) + + # clearing non-exsistent credentials is fine + credentials.clear("test") + + def test_add_credentials(self, credentials): + credentials.set("test", "user", "password") + expected_toml = '[test]\nusername = "user"\npassword = "password"\n' + self.assert_toml_file(credentials, expected_toml) diff --git a/tests/conftest.py b/tests/conftest.py index 96c6668b..ca3e133e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,16 +1,17 @@ -from pathlib import Path -from datetime import datetime import contextlib import cProfile import pstats +from datetime import datetime +from pathlib import Path + import pandas as pd import pytest +from sqlalchemy.exc import OperationalError -from sqlalchemy.exc import OperationalError, DatabaseError from ixmp4 import Platform -from ixmp4.data.backend.db import OracleTestBackend, PostgresTestBackend from ixmp4.data.abstract import DataPoint -from ixmp4.data.backend import SqliteTestBackend, RestTestBackend +from ixmp4.data.backend import RestTestBackend, SqliteTestBackend +from ixmp4.data.backend.db import PostgresTestBackend def read_test_data(path): @@ -126,17 +127,6 @@ def test_pgsql_mp(): mp.backend.close() -@pytest.fixture -def test_oracle_mp(): - try: - mp = Platform(_backend=OracleTestBackend()) - except DatabaseError as e: - pytest.skip(f"Cannot connect to Oracle database service, skipping test: {e}") - - yield mp - mp.backend.close() - - @pytest.fixture def test_api_sqlite_mp(test_sqlite_mp): return Platform(_backend=RestTestBackend(test_sqlite_mp.backend)) diff --git a/tests/core/test_indexset.py b/tests/core/test_indexset.py new file mode 100644 index 00000000..82f2347a --- /dev/null +++ b/tests/core/test_indexset.py @@ -0,0 +1,47 @@ +import pytest + +from ..utils import all_platforms + + +@all_platforms +class TestCoreIndexSet: + def test_create_indexset(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + index_set_1 = run.optimization.IndexSet("IndexSet 1") + returned_index_set_1 = run.optimization.IndexSet("IndexSet 1") + assert index_set_1.id == returned_index_set_1.id + + index_set_2 = run.optimization.IndexSet("IndexSet 2") + assert index_set_1.id != index_set_2.id + + def test_add_elements(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + test_elements = ["foo", "bar"] + index_set_1 = run.optimization.IndexSet("IndexSet 1") + index_set_1.add(test_elements) + run.optimization.IndexSet("IndexSet 2").add(test_elements) + index_set_2 = run.optimization.IndexSet("IndexSet 2") + assert index_set_1.elements == index_set_2.elements + + with pytest.raises(ValueError): + index_set_1.add(["baz", "foo"]) + + with pytest.raises(ValueError): + index_set_2.add(["baz", "baz"]) + + index_set_1.add(1) + index_set_3 = run.optimization.IndexSet("IndexSet 1") + index_set_2.add("1") + index_set_4 = run.optimization.IndexSet("IndexSet 2") + assert index_set_3.elements != index_set_4.elements + assert len(index_set_3.elements) == len(index_set_4.elements) + + def test_indexset_docs(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + index_set_1 = run.optimization.IndexSet("IndexSet 1") + docs = "Documentation of IndexSet 1" + index_set_1.docs = docs + assert index_set_1.docs == docs + + index_set_1.docs = None + assert index_set_1.docs is None diff --git a/tests/core/test_model.py b/tests/core/test_model.py index e2e7b4c6..1a83e160 100644 --- a/tests/core/test_model.py +++ b/tests/core/test_model.py @@ -1,25 +1,9 @@ -import pytest import pandas as pd +import pytest from ixmp4 import Model -from ..utils import assert_unordered_equality, all_platforms - - -@all_platforms -def test_retrieve_model(test_mp): - model1 = test_mp.models.create("Model") - model2 = test_mp.models.get("Model") - - assert model1.id == model2.id - - -@all_platforms -def test_model_unqiue(test_mp): - test_mp.models.create("Model") - - with pytest.raises(Model.NotUnique): - test_mp.models.create("Model") +from ..utils import all_platforms, assert_unordered_equality def create_testcase_models(test_mp): @@ -28,20 +12,6 @@ def create_testcase_models(test_mp): return model, model2 -@all_platforms -def test_list_model(test_mp): - models = create_testcase_models(test_mp) - model, _ = models - - a = [m.id for m in models] - b = [m.id for m in test_mp.models.list()] - assert not (set(a) ^ set(b)) - - a = [model.id] - b = [m.id for m in test_mp.models.list(name="Model")] - assert not (set(a) ^ set(b)) - - def df_from_list(models): return pd.DataFrame( [[m.id, m.name, m.created_at, m.created_by] for m in models], @@ -50,50 +20,71 @@ def df_from_list(models): @all_platforms -def test_tabulate_model(test_mp): - models = create_testcase_models(test_mp) - model, _ = models +class TestCoreModel: + def test_retrieve_model(self, test_mp): + model1 = test_mp.models.create("Model") + model2 = test_mp.models.get("Model") - a = df_from_list(models) - b = test_mp.models.tabulate() - assert_unordered_equality(a, b, check_dtype=False) + assert model1.id == model2.id - a = df_from_list([model]) - b = test_mp.models.tabulate(name="Model") - assert_unordered_equality(a, b, check_dtype=False) + def test_model_unqiue(self, test_mp): + test_mp.models.create("Model") + with pytest.raises(Model.NotUnique): + test_mp.models.create("Model") -@all_platforms -def test_retrieve_docs(test_mp): - test_mp.models.create("Model") - docs_model1 = test_mp.models.set_docs("Model", "Description of test Model") - docs_model2 = test_mp.models.get_docs("Model") + def test_list_model(self, test_mp): + models = create_testcase_models(test_mp) + model, _ = models - assert docs_model1 == docs_model2 + a = [m.id for m in models] + b = [m.id for m in test_mp.models.list()] + assert not (set(a) ^ set(b)) - model2 = test_mp.models.create("Model2") + a = [model.id] + b = [m.id for m in test_mp.models.list(name="Model")] + assert not (set(a) ^ set(b)) - assert model2.docs is None + def test_tabulate_model(self, test_mp): + models = create_testcase_models(test_mp) + model, _ = models - model2.docs = "Description of test Model2" + a = df_from_list(models) + b = test_mp.models.tabulate() + assert_unordered_equality(a, b, check_dtype=False) - assert test_mp.models.get_docs("Model2") == model2.docs + a = df_from_list([model]) + b = test_mp.models.tabulate(name="Model") + assert_unordered_equality(a, b, check_dtype=False) + def test_retrieve_docs(self, test_mp): + test_mp.models.create("Model") + docs_model1 = test_mp.models.set_docs("Model", "Description of test Model") + docs_model2 = test_mp.models.get_docs("Model") -@all_platforms -def test_delete_docs(test_mp): - model = test_mp.models.create("Model") - model.docs = "Description of test Model" - model.docs = None + assert docs_model1 == docs_model2 + + model2 = test_mp.models.create("Model2") + + assert model2.docs is None + + model2.docs = "Description of test Model2" + + assert test_mp.models.get_docs("Model2") == model2.docs + + def test_delete_docs(self, test_mp): + model = test_mp.models.create("Model") + model.docs = "Description of test Model" + model.docs = None - assert model.docs is None + assert model.docs is None - model.docs = "Second description of test Model" - del model.docs + model.docs = "Second description of test Model" + del model.docs - assert model.docs is None + assert model.docs is None - model.docs = "Third description of test Model" - test_mp.models.delete_docs("Model") + model.docs = "Third description of test Model" + test_mp.models.delete_docs("Model") - assert model.docs is None + assert model.docs is None diff --git a/tests/core/test_region.py b/tests/core/test_region.py index dddb0550..193b8c90 100644 --- a/tests/core/test_region.py +++ b/tests/core/test_region.py @@ -1,150 +1,135 @@ -import pytest import pandas as pd +import pytest -from ixmp4 import Region, DataPoint - -from ..utils import add_regions, add_units, assert_unordered_equality, all_platforms - - -@all_platforms -def test_delete_region(test_mp, test_data_annual): - reg1 = test_mp.regions.create("Test 1", hierarchy="default") - reg2 = test_mp.regions.create("Test 2", hierarchy="default") - reg3 = test_mp.regions.create("Test 3", hierarchy="default") - test_mp.regions.create("Test 4", hierarchy="default") - - assert reg1.id != reg2.id != reg3.id - test_mp.regions.delete(reg1) - test_mp.regions.delete(reg2.id) - reg3.delete() - test_mp.regions.delete("Test 4") - - assert test_mp.regions.tabulate().empty - - add_regions(test_mp, test_data_annual["region"].unique()) - add_units(test_mp, test_data_annual["unit"].unique()) - - run = test_mp.Run("Model", "Scenario", version="new") - run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) +from ixmp4 import DataPoint, Region - with pytest.raises(Region.DeletionPrevented): - test_mp.regions.delete("World") +from ..utils import add_regions, add_units, all_platforms, assert_unordered_equality -@all_platforms -def test_region_has_hierarchy(test_mp): - with pytest.raises(TypeError): - test_mp.regions.create("Test") +def create_testcase_regions(test_mp): + reg = test_mp.regions.create("Test", hierarchy="default") + other = test_mp.regions.create("Test Other", hierarchy="other") + return reg, other - reg1 = test_mp.regions.create("Test", hierarchy="default") - reg2 = test_mp.regions.get("Test") - assert reg1.id == reg2.id +def df_from_list(regions): + return pd.DataFrame( + [[r.id, r.name, r.hierarchy, r.created_at, r.created_by] for r in regions], + columns=["id", "name", "hierarchy", "created_at", "created_by"], + ) @all_platforms -def test_get_region(test_mp): - reg1 = test_mp.regions.create("Test", hierarchy="default") - reg2 = test_mp.regions.get("Test") +class TestCoreRegion: + def test_delete_region(self, test_mp, test_data_annual): + reg1 = test_mp.regions.create("Test 1", hierarchy="default") + reg2 = test_mp.regions.create("Test 2", hierarchy="default") + reg3 = test_mp.regions.create("Test 3", hierarchy="default") + test_mp.regions.create("Test 4", hierarchy="default") - assert reg1.id == reg2.id + assert reg1.id != reg2.id != reg3.id + test_mp.regions.delete(reg1) + test_mp.regions.delete(reg2.id) + reg3.delete() + test_mp.regions.delete("Test 4") - with pytest.raises(Region.NotFound): - test_mp.regions.get("Does not exist") + assert test_mp.regions.tabulate().empty + add_regions(test_mp, test_data_annual["region"].unique()) + add_units(test_mp, test_data_annual["unit"].unique()) -@all_platforms -def test_region_unique(test_mp): - reg = test_mp.regions.create("Test", hierarchy="default") + run = test_mp.Run("Model", "Scenario", version="new") + run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) - with pytest.raises(Region.NotUnique): - test_mp.regions.create("Test", hierarchy="other") + with pytest.raises(Region.DeletionPrevented): + test_mp.regions.delete("World") + def test_region_has_hierarchy(self, test_mp): + with pytest.raises(TypeError): + test_mp.regions.create("Test") -@all_platforms -def test_region_unknown(test_mp, test_data_annual): - add_regions(test_mp, test_data_annual["region"].unique()) - add_units(test_mp, test_data_annual["unit"].unique()) + reg1 = test_mp.regions.create("Test", hierarchy="default") + reg2 = test_mp.regions.get("Test") - test_data_annual["region"] = "foo" + assert reg1.id == reg2.id - run = test_mp.Run("Model", "Scenario", version="new") - with pytest.raises(Region.NotFound): - run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) + def test_get_region(self, test_mp): + reg1 = test_mp.regions.create("Test", hierarchy="default") + reg2 = test_mp.regions.get("Test") + assert reg1.id == reg2.id -def create_testcase_regions(test_mp): - reg = test_mp.regions.create("Test", hierarchy="default") - other = test_mp.regions.create("Test Other", hierarchy="other") - return reg, other + with pytest.raises(Region.NotFound): + test_mp.regions.get("Does not exist") + def test_region_unique(self, test_mp): + test_mp.regions.create("Test", hierarchy="default") -@all_platforms -def test_list_region(test_mp): - regions = create_testcase_regions(test_mp) - reg, other = regions + with pytest.raises(Region.NotUnique): + test_mp.regions.create("Test", hierarchy="other") - a = [r.id for r in regions] - b = [r.id for r in test_mp.regions.list()] - assert not (set(a) ^ set(b)) + def test_region_unknown(self, test_mp, test_data_annual): + add_regions(test_mp, test_data_annual["region"].unique()) + add_units(test_mp, test_data_annual["unit"].unique()) - a = [other.id] - b = [r.id for r in test_mp.regions.list(hierarchy="other")] - assert not (set(a) ^ set(b)) + test_data_annual["region"] = "foo" + run = test_mp.Run("Model", "Scenario", version="new") + with pytest.raises(Region.NotFound): + run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) -def df_from_list(regions): - return pd.DataFrame( - [[r.id, r.name, r.hierarchy, r.created_at, r.created_by] for r in regions], - columns=["id", "name", "hierarchy", "created_at", "created_by"], - ) + def test_list_region(self, test_mp): + regions = create_testcase_regions(test_mp) + reg, other = regions + a = [r.id for r in regions] + b = [r.id for r in test_mp.regions.list()] + assert not (set(a) ^ set(b)) -@all_platforms -def test_tabulate_region(test_mp): - regions = create_testcase_regions(test_mp) - _, other = regions - - a = df_from_list(regions) - b = test_mp.regions.tabulate() - assert_unordered_equality(a, b, check_dtype=False) + a = [other.id] + b = [r.id for r in test_mp.regions.list(hierarchy="other")] + assert not (set(a) ^ set(b)) - a = df_from_list([other]) - b = test_mp.regions.tabulate(hierarchy="other") - assert_unordered_equality(a, b, check_dtype=False) + def test_tabulate_region(self, test_mp): + regions = create_testcase_regions(test_mp) + _, other = regions + a = df_from_list(regions) + b = test_mp.regions.tabulate() + assert_unordered_equality(a, b, check_dtype=False) -@all_platforms -def test_retrieve_docs(test_mp): - test_mp.regions.create("Region", "Hierarchy") - docs_region1 = test_mp.regions.set_docs("Region", "Description of test Region") - docs_region2 = test_mp.regions.get_docs("Region") + a = df_from_list([other]) + b = test_mp.regions.tabulate(hierarchy="other") + assert_unordered_equality(a, b, check_dtype=False) - assert docs_region1 == docs_region2 + def test_retrieve_docs(self, test_mp): + test_mp.regions.create("Region", "Hierarchy") + docs_region1 = test_mp.regions.set_docs("Region", "Description of test Region") + docs_region2 = test_mp.regions.get_docs("Region") - region2 = test_mp.regions.create("Region2", "Hierarchy") + assert docs_region1 == docs_region2 - assert region2.docs is None + region2 = test_mp.regions.create("Region2", "Hierarchy") - region2.docs = "Description of test region2" + assert region2.docs is None - assert test_mp.regions.get_docs("Region2") == region2.docs + region2.docs = "Description of test region2" + assert test_mp.regions.get_docs("Region2") == region2.docs -@all_platforms -def test_delete_docs(test_mp): - region = test_mp.regions.create("Region", "Hierarchy") - region.docs = "Description of test region" - region.docs = None + def test_delete_docs(self, test_mp): + region = test_mp.regions.create("Region", "Hierarchy") + region.docs = "Description of test region" + region.docs = None - assert region.docs is None + assert region.docs is None - region.docs = "Second description of test region" - del region.docs + region.docs = "Second description of test region" + del region.docs - assert region.docs is None + assert region.docs is None - region.docs = "Third description of test region" - test_mp.regions.delete_docs("Region") + region.docs = "Third description of test region" + test_mp.regions.delete_docs("Region") - assert region.docs is None + assert region.docs is None diff --git a/tests/core/test_run.py b/tests/core/test_run.py index 0e7b4da4..d7c754af 100644 --- a/tests/core/test_run.py +++ b/tests/core/test_run.py @@ -2,9 +2,9 @@ import pandas.testing as pdt import pytest -from ixmp4 import Run, IxmpError +from ixmp4 import DataPoint, InconsistentIamcType, IxmpError, Run -from ..utils import add_regions, add_units, assert_unordered_equality, all_platforms +from ..utils import add_regions, add_units, all_platforms, assert_unordered_equality def _expected_runs_table(*row_default): @@ -19,65 +19,203 @@ def _expected_runs_table(*row_default): @all_platforms -def test_run_versions(test_mp): - run1 = test_mp.Run("Model", "Scenario", version="new") - run2 = test_mp.Run("Model", "Scenario", version="new") - - assert run1.id != run2.id +class TestCoreRun: + def test_run_versions(self, test_mp): + run1 = test_mp.Run("Model", "Scenario", version="new") + run2 = test_mp.Run("Model", "Scenario", version="new") + + assert run1.id != run2.id + + # no default version is assigned, so list & tabulate are empty + with pytest.raises(Run.NoDefaultVersion): + run = test_mp.Run("Model", "Scenario") + assert test_mp.runs.list() == [] + assert test_mp.runs.tabulate().empty + + run_list = test_mp.runs.list(default_only=False) + assert len(run_list) == 2 + assert run_list[0].id == run1.id + pdt.assert_frame_equal( + test_mp.runs.tabulate(default_only=False), + pd.DataFrame(_expected_runs_table(False, False)), + ) + + # set default, so list & tabulate show default version only + run1.set_as_default() + run_list = test_mp.runs.list() + assert len(run_list) == 1 + assert run_list[0].id == run1.id + pdt.assert_frame_equal( + test_mp.runs.tabulate(), + pd.DataFrame(_expected_runs_table(True)), + ) + + # using default_only=False shows both versions + pdt.assert_frame_equal( + test_mp.runs.tabulate(default_only=False), + pd.DataFrame(_expected_runs_table(True, False)), + ) + + # default version can be retrieved directly + run = test_mp.Run("Model", "Scenario") + assert run1.id == run.id - # no default version is assigned, so list & tabulate are empty - with pytest.raises(Run.NoDefaultVersion): + # default version can be changed + run2.set_as_default() run = test_mp.Run("Model", "Scenario") - assert test_mp.runs.list() == [] - assert test_mp.runs.tabulate().empty - - run_list = test_mp.runs.list(default_only=False) - assert len(run_list) == 2 - assert run_list[0].id == run1.id - pdt.assert_frame_equal( - test_mp.runs.tabulate(default_only=False), - pd.DataFrame(_expected_runs_table(False, False)), - ) + assert run2.id == run.id + + # list shows changed default version only + run_list = test_mp.runs.list() + assert len(run_list) == 1 + assert run_list[0].id == run2.id + pdt.assert_frame_equal( + test_mp.runs.tabulate(), + pd.DataFrame(_expected_runs_table(None, True)), + ) + + # unsetting default means run cannot be retrieved directly + run2.unset_as_default() + with pytest.raises(Run.NoDefaultVersion): + test_mp.Run("Model", "Scenario") - # set default, so list & tabulate show default version only - run1.set_as_default() - run_list = test_mp.runs.list() - assert len(run_list) == 1 - assert run_list[0].id == run1.id - pdt.assert_frame_equal( - test_mp.runs.tabulate(), - pd.DataFrame(_expected_runs_table(True)), - ) + # non-default version cannot be again set as un-default + with pytest.raises(IxmpError): + run2.unset_as_default() - # using default_only=False shows both versions - pdt.assert_frame_equal( - test_mp.runs.tabulate(default_only=False), - pd.DataFrame(_expected_runs_table(True, False)), - ) + def test_run_annual_datapoints(self, test_mp, test_data_annual): + do_run_datapoints(test_mp, test_data_annual, DataPoint.Type.ANNUAL) - # default version can be retrieved directly - run = test_mp.Run("Model", "Scenario") - assert run1.id == run.id - - # default version can be changed - run2.set_as_default() - run = test_mp.Run("Model", "Scenario") - assert run2.id == run.id - - # list shows changed default version only - run_list = test_mp.runs.list() - assert len(run_list) == 1 - assert run_list[0].id == run2.id - pdt.assert_frame_equal( - test_mp.runs.tabulate(), - pd.DataFrame(_expected_runs_table(None, True)), + def test_run_annual_datapoints_from_pyam(self, test_mp, test_data_annual): + # convert to pyam.data format + df = test_data_annual.rename(columns={"step_year": "year"}) + do_run_datapoints(test_mp, test_data_annual, arg_data=df) + + @pytest.mark.parametrize( + "_type", (DataPoint.Type.CATEGORICAL, DataPoint.Type.DATETIME) ) + def test_run_inconsistent_annual_raises(self, test_mp, test_data_annual, _type): + with pytest.raises(InconsistentIamcType): + do_run_datapoints(test_mp, test_data_annual, _type) - # unsetting default means run cannot be retrieved directly - run2.unset_as_default() - with pytest.raises(Run.NoDefaultVersion): - test_mp.Run("Model", "Scenario") + def test_run_categorical_datapoints(self, test_mp, test_data_categorical): + do_run_datapoints(test_mp, test_data_categorical, DataPoint.Type.CATEGORICAL) - # non-default version cannot be again set as un-default - with pytest.raises(IxmpError): - run2.unset_as_default() + @pytest.mark.parametrize("_type", (DataPoint.Type.ANNUAL, DataPoint.Type.DATETIME)) + def test_run_inconsistent_categorical_raises( + self, test_mp, test_data_categorical, _type + ): + with pytest.raises(InconsistentIamcType): + do_run_datapoints(test_mp, test_data_categorical, _type) + + def test_run_datetime_datapoints(self, test_mp, test_data_datetime): + do_run_datapoints(test_mp, test_data_datetime, DataPoint.Type.DATETIME) + + @pytest.mark.parametrize( + "_type", (DataPoint.Type.ANNUAL, DataPoint.Type.CATEGORICAL) + ) + def test_run_inconsistent_datetime_type_raises( + self, test_mp, test_data_datetime, _type + ): + with pytest.raises(InconsistentIamcType): + do_run_datapoints(test_mp, test_data_datetime, _type) + + def test_unit_dimensionless(self, test_mp, test_data_annual): + test_data_annual.loc[0, "unit"] = "" + do_run_datapoints(test_mp, test_data_annual, DataPoint.Type.ANNUAL) + + def test_unit_as_string_dimensionless_raises(self, test_mp, test_data_annual): + test_data_annual.loc[0, "unit"] = "dimensionless" + with pytest.raises(ValueError, match="Unit name 'dimensionless' is reserved,"): + do_run_datapoints(test_mp, test_data_annual, DataPoint.Type.ANNUAL) + + def test_run_tabulate_with_filter(self, test_mp, test_data_annual): + # Filter run directly + add_regions(test_mp, test_data_annual["region"].unique()) + add_units(test_mp, test_data_annual["unit"].unique()) + + run = test_mp.Run("Model", "Scenario", version="new") + run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) + obs = run.iamc.tabulate( + variable={"name": "Primary Energy"}, unit={"name": "EJ/yr"} + ).drop(["id", "type"], axis=1) + exp = test_data_annual[test_data_annual.variable == "Primary Energy"] + assert_unordered_equality(obs, exp, check_like=True) + + +def do_run_datapoints(test_mp, ixmp_data, type=None, arg_data=None): + # ixmp_data: expected return format from Run.iamc.tabulate() (column names 'step_*') + # arg_data: passed to Run.iamc.[add/remove](), + # can be ixmp4 or pyam format (column names 'year' or 'time') + + if arg_data is None: + arg_data = ixmp_data.copy() + + # Define required regions and units in the database + add_regions(test_mp, ixmp_data["region"].unique()) + add_units(test_mp, ixmp_data["unit"].unique()) + + run = test_mp.Run("Model", "Scenario", version="new") + + # == Full Addition == + # Save to database + run.iamc.add(arg_data, type=type) + + # Retrieve from database via Run + ret = run.iamc.tabulate() + ret = ret.drop(columns=["id", "type"]) + assert_unordered_equality(ixmp_data, ret, check_like=True) + + # If not set as default, retrieve from database via Platform returns an empty frame + ret = test_mp.iamc.tabulate() + assert ret.empty + + # Retrieve from database via Platform (including model, scenario, version columns) + ret = test_mp.iamc.tabulate(run={"default_only": False}) + ret = ret.drop(columns=["id", "type"]) + + test_mp_data = ixmp_data.copy() + test_mp_data["model"] = run.model.name + test_mp_data["scenario"] = run.scenario.name + test_mp_data["version"] = run.version + test_mp_data = test_mp_data[ret.columns] + assert_unordered_equality(test_mp_data, ret, check_like=True) + + # Retrieve from database after setting the run to default + run.set_as_default() + ret = test_mp.iamc.tabulate() + ret = ret.drop(columns=["id", "type"]) + assert_unordered_equality(test_mp_data, ret, check_like=True) + + # == Partial Removal == + # Remove half the data + remove_data = arg_data.head(len(ixmp_data) // 2).drop(columns=["value"]) + remaining_data = ixmp_data.tail(len(ixmp_data) // 2).reset_index(drop=True) + run.iamc.remove(remove_data, type=type) + + # Retrieve from database + ret = run.iamc.tabulate() + ret = ret.drop(columns=["id", "type"]) + assert_unordered_equality(remaining_data, ret, check_like=True) + + # == Partial Update / Partial Addition == + # Update all data values + ixmp_data["value"] = -9.9 + arg_data["value"] = -9.9 + + # Results in a half insert / half update + run.iamc.add(arg_data, type=type) + + # Retrieve from database + ret = run.iamc.tabulate() + ret = ret.drop(columns=["id", "type"]) + assert_unordered_equality(ixmp_data, ret, check_like=True) + + # == Full Removal == + # Remove all data + remove_data = arg_data.drop(columns=["value"]) + run.iamc.remove(remove_data, type=type) + + # Retrieve from database + ret = run.iamc.tabulate() + assert ret.empty diff --git a/tests/core/test_scenario.py b/tests/core/test_scenario.py index 892c960e..bb06b9fb 100644 --- a/tests/core/test_scenario.py +++ b/tests/core/test_scenario.py @@ -1,25 +1,9 @@ -import pytest import pandas as pd +import pytest from ixmp4 import Scenario -from ..utils import assert_unordered_equality, all_platforms - - -@all_platforms -def test_retrieve_scenario(test_mp): - scenario1 = test_mp.scenarios.create("Scenario") - scenario2 = test_mp.scenarios.get("Scenario") - - assert scenario1.id == scenario2.id - - -@all_platforms -def test_scenario_unqiue(test_mp): - test_mp.scenarios.create("Scenario") - - with pytest.raises(Scenario.NotUnique): - test_mp.scenarios.create("Scenario") +from ..utils import all_platforms, assert_unordered_equality def create_testcase_scenarios(test_mp): @@ -28,20 +12,6 @@ def create_testcase_scenarios(test_mp): return scenario, scenario2 -@all_platforms -def test_list_scenario(test_mp): - scenarios = create_testcase_scenarios(test_mp) - scenario, _ = scenarios - - a = [s.id for s in scenarios] - b = [s.id for s in test_mp.scenarios.list()] - assert not (set(a) ^ set(b)) - - a = [scenario.id] - b = [s.id for s in test_mp.scenarios.list(name="Scenario")] - assert not (set(a) ^ set(b)) - - def df_from_list(scenarios): return pd.DataFrame( [[s.id, s.name, s.created_at, s.created_by] for s in scenarios], @@ -50,52 +20,73 @@ def df_from_list(scenarios): @all_platforms -def test_tabulate_scenario(test_mp): - scenarios = create_testcase_scenarios(test_mp) - scenario, _ = scenarios +class TestCoreScenario: + def test_retrieve_scenario(self, test_mp): + scenario1 = test_mp.scenarios.create("Scenario") + scenario2 = test_mp.scenarios.get("Scenario") - a = df_from_list(scenarios) - b = test_mp.scenarios.tabulate() - assert_unordered_equality(a, b, check_dtype=False) + assert scenario1.id == scenario2.id - a = df_from_list([scenario]) - b = test_mp.scenarios.tabulate(name="Scenario") - assert_unordered_equality(a, b, check_dtype=False) + def test_scenario_unqiue(self, test_mp): + test_mp.scenarios.create("Scenario") + with pytest.raises(Scenario.NotUnique): + test_mp.scenarios.create("Scenario") -@all_platforms -def test_retrieve_docs(test_mp): - test_mp.scenarios.create("Scenario") - docs_scenario1 = test_mp.scenarios.set_docs( - "Scenario", "Description of test Scenario" - ) - docs_scenario2 = test_mp.scenarios.get_docs("Scenario") + def test_list_scenario(self, test_mp): + scenarios = create_testcase_scenarios(test_mp) + scenario, _ = scenarios - assert docs_scenario1 == docs_scenario2 + a = [s.id for s in scenarios] + b = [s.id for s in test_mp.scenarios.list()] + assert not (set(a) ^ set(b)) - scenario2 = test_mp.scenarios.create("Scenario2") + a = [scenario.id] + b = [s.id for s in test_mp.scenarios.list(name="Scenario")] + assert not (set(a) ^ set(b)) - assert scenario2.docs is None + def test_tabulate_scenario(self, test_mp): + scenarios = create_testcase_scenarios(test_mp) + scenario, _ = scenarios - scenario2.docs = "Description of test Scenario2" + a = df_from_list(scenarios) + b = test_mp.scenarios.tabulate() + assert_unordered_equality(a, b, check_dtype=False) - assert test_mp.scenarios.get_docs("Scenario2") == scenario2.docs + a = df_from_list([scenario]) + b = test_mp.scenarios.tabulate(name="Scenario") + assert_unordered_equality(a, b, check_dtype=False) + def test_retrieve_docs(self, test_mp): + test_mp.scenarios.create("Scenario") + docs_scenario1 = test_mp.scenarios.set_docs( + "Scenario", "Description of test Scenario" + ) + docs_scenario2 = test_mp.scenarios.get_docs("Scenario") -@all_platforms -def test_delete_docs(test_mp): - scenario = test_mp.scenarios.create("Scenario") - scenario.docs = "Description of test Scenario" - scenario.docs = None + assert docs_scenario1 == docs_scenario2 + + scenario2 = test_mp.scenarios.create("Scenario2") + + assert scenario2.docs is None + + scenario2.docs = "Description of test Scenario2" + + assert test_mp.scenarios.get_docs("Scenario2") == scenario2.docs + + def test_delete_docs(self, test_mp): + scenario = test_mp.scenarios.create("Scenario") + scenario.docs = "Description of test Scenario" + scenario.docs = None - assert scenario.docs is None + assert scenario.docs is None - scenario.docs = "Second description of test Scenario" - del scenario.docs + scenario.docs = "Second description of test Scenario" + del scenario.docs - assert scenario.docs is None + assert scenario.docs is None - scenario.docs = "Third description of test Scenario" - test_mp.scenarios.delete_docs("Scenario") + scenario.docs = "Third description of test Scenario" + test_mp.scenarios.delete_docs("Scenario") - assert scenario.docs is None + assert scenario.docs is None diff --git a/tests/core/test_unit.py b/tests/core/test_unit.py index 696ba62d..8b93868e 100644 --- a/tests/core/test_unit.py +++ b/tests/core/test_unit.py @@ -1,154 +1,139 @@ -import pytest import pandas as pd +import pytest from ixmp4 import DataPoint, Unit -from ..utils import add_regions, add_units, assert_unordered_equality, all_platforms +from ..utils import add_regions, add_units, all_platforms, assert_unordered_equality -@all_platforms -def test_delete_unit(test_mp, test_data_annual): - unit1 = test_mp.units.create("Test 1") +def create_testcase_units(test_mp): + unit = test_mp.units.create("Test") unit2 = test_mp.units.create("Test 2") - unit3 = test_mp.units.create("Test 3") - test_mp.units.create("Test 4") - - assert unit1.id != unit2.id != unit3.id - test_mp.units.delete(unit1) - test_mp.units.delete(unit2.id) - unit3.delete() - test_mp.units.delete("Test 4") - - assert test_mp.units.tabulate().empty - - add_regions(test_mp, test_data_annual["region"].unique()) - add_units(test_mp, test_data_annual["unit"].unique()) - - run = test_mp.Run("Model", "Scenario", version="new") - run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) - - with pytest.raises(Unit.DeletionPrevented): - test_mp.units.delete("EJ/yr") - - -@all_platforms -def test_retrieve_unit(test_mp): - unit1 = test_mp.units.create("Test") - unit2 = test_mp.units.get("Test") - - assert unit1.id == unit2.id - + return unit, unit2 -@all_platforms -def test_unit_unqiue(test_mp): - test_mp.units.create("Test") - with pytest.raises(Unit.NotUnique): - test_mp.units.create("Test") +# TODO: tabulate does not include docs -> should it? +def df_from_list(units): + return pd.DataFrame( + [[u.id, u.name, u.created_at, u.created_by] for u in units], + columns=["id", "name", "created_at", "created_by"], + ) @all_platforms -def test_unit_dimensionless(test_mp): - unit1 = test_mp.units.create("") - unit2 = test_mp.units.get("") +class TestCoreUnit: + def test_delete_unit(self, test_mp, test_data_annual): + unit1 = test_mp.units.create("Test 1") + unit2 = test_mp.units.create("Test 2") + unit3 = test_mp.units.create("Test 3") + test_mp.units.create("Test 4") - assert unit1.id == unit2.id + assert unit1.id != unit2.id != unit3.id + test_mp.units.delete(unit1) + test_mp.units.delete(unit2.id) + unit3.delete() + test_mp.units.delete("Test 4") + assert test_mp.units.tabulate().empty -@all_platforms -def test_unit_illegal_names(test_mp): - with pytest.raises(ValueError, match="Unit name 'dimensionless' is reserved,"): - test_mp.units.create("dimensionless") + add_regions(test_mp, test_data_annual["region"].unique()) + add_units(test_mp, test_data_annual["unit"].unique()) - with pytest.raises(ValueError, match="Using a space-only unit name is not allowed"): - test_mp.units.create(" ") + run = test_mp.Run("Model", "Scenario", version="new") + run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) + with pytest.raises(Unit.DeletionPrevented): + test_mp.units.delete("EJ/yr") -@all_platforms -def test_unit_unknown(test_mp, test_data_annual): - add_regions(test_mp, test_data_annual["region"].unique()) - add_units(test_mp, test_data_annual["unit"].unique()) + def test_retrieve_unit(self, test_mp): + unit1 = test_mp.units.create("Test") + unit2 = test_mp.units.get("Test") - test_data_annual["unit"] = "foo" + assert unit1.id == unit2.id - run = test_mp.Run("Model", "Scenario", version="new") - with pytest.raises(Unit.NotFound): - run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) + def test_unit_unqiue(self, test_mp): + test_mp.units.create("Test") + with pytest.raises(Unit.NotUnique): + test_mp.units.create("Test") -def create_testcase_units(test_mp): - unit = test_mp.units.create("Test") - unit2 = test_mp.units.create("Test 2") - return unit, unit2 + def test_unit_dimensionless(self, test_mp): + unit1 = test_mp.units.create("") + unit2 = test_mp.units.get("") + assert unit1.id == unit2.id -@all_platforms -def test_list_unit(test_mp): - units = create_testcase_units(test_mp) - unit, _ = units + def test_unit_illegal_names(self, test_mp): + with pytest.raises(ValueError, match="Unit name 'dimensionless' is reserved,"): + test_mp.units.create("dimensionless") - a = [u.id for u in units] - b = [u.id for u in test_mp.units.list()] - assert not (set(a) ^ set(b)) + with pytest.raises( + ValueError, match="Using a space-only unit name is not allowed" + ): + test_mp.units.create(" ") - a = [unit.id] - b = [u.id for u in test_mp.units.list(name="Test")] - assert not (set(a) ^ set(b)) + def test_unit_unknown(self, test_mp, test_data_annual): + add_regions(test_mp, test_data_annual["region"].unique()) + add_units(test_mp, test_data_annual["unit"].unique()) + test_data_annual["unit"] = "foo" -# TODO: tabulate does not include docs -> should it? -def df_from_list(units): - return pd.DataFrame( - [[u.id, u.name, u.created_at, u.created_by] for u in units], - columns=["id", "name", "created_at", "created_by"], - ) + run = test_mp.Run("Model", "Scenario", version="new") + with pytest.raises(Unit.NotFound): + run.iamc.add(test_data_annual, type=DataPoint.Type.ANNUAL) + def test_list_unit(self, test_mp): + units = create_testcase_units(test_mp) + unit, _ = units -@all_platforms -def test_tabulate_unit(test_mp): - units = create_testcase_units(test_mp) - unit, _ = units + a = [u.id for u in units] + b = [u.id for u in test_mp.units.list()] + assert not (set(a) ^ set(b)) - a = df_from_list(units) - b = test_mp.units.tabulate() - assert_unordered_equality(a, b, check_dtype=False) + a = [unit.id] + b = [u.id for u in test_mp.units.list(name="Test")] + assert not (set(a) ^ set(b)) - a = df_from_list([unit]) - b = test_mp.units.tabulate(name="Test") - assert_unordered_equality(a, b, check_dtype=False) + def test_tabulate_unit(self, test_mp): + units = create_testcase_units(test_mp) + unit, _ = units + a = df_from_list(units) + b = test_mp.units.tabulate() + assert_unordered_equality(a, b, check_dtype=False) -@all_platforms -def test_retrieve_docs(test_mp): - test_mp.units.create("Unit") - docs_unit1 = test_mp.units.set_docs("Unit", "Description of test Unit") - docs_unit2 = test_mp.units.get_docs("Unit") + a = df_from_list([unit]) + b = test_mp.units.tabulate(name="Test") + assert_unordered_equality(a, b, check_dtype=False) - assert docs_unit1 == docs_unit2 + def test_retrieve_docs(self, test_mp): + test_mp.units.create("Unit") + docs_unit1 = test_mp.units.set_docs("Unit", "Description of test Unit") + docs_unit2 = test_mp.units.get_docs("Unit") - unit2 = test_mp.units.create("Unit2") + assert docs_unit1 == docs_unit2 - assert unit2.docs is None + unit2 = test_mp.units.create("Unit2") - unit2.docs = "Description of test Unit2" + assert unit2.docs is None - assert test_mp.units.get_docs("Unit2") == unit2.docs + unit2.docs = "Description of test Unit2" + assert test_mp.units.get_docs("Unit2") == unit2.docs -@all_platforms -def test_delete_docs(test_mp): - unit = test_mp.units.create("Unit") - unit.docs = "Description of test Unit" - unit.docs = None + def test_delete_docs(self, test_mp): + unit = test_mp.units.create("Unit") + unit.docs = "Description of test Unit" + unit.docs = None - assert unit.docs is None + assert unit.docs is None - unit.docs = "Second description of test Unit" - del unit.docs + unit.docs = "Second description of test Unit" + del unit.docs - assert unit.docs is None + assert unit.docs is None - unit.docs = "Third description of test Unit" - test_mp.units.delete_docs("Unit") + unit.docs = "Third description of test Unit" + test_mp.units.delete_docs("Unit") - assert unit.docs is None + assert unit.docs is None diff --git a/tests/core/test_variable.py b/tests/core/test_variable.py index 6dce28fc..417638d7 100644 --- a/tests/core/test_variable.py +++ b/tests/core/test_variable.py @@ -1,42 +1,12 @@ # Variable tests are currently disabled -import pytest import pandas as pd +import pytest import ixmp4 from ixmp4 import Variable - -from ..utils import assert_unordered_equality, all_platforms - - -@all_platforms -def test_retrieve_iamc_variable(test_mp): - iamc_variable1 = test_mp.iamc.variables.create("IAMC Variable") - test_mp.regions.create("Region", "default") - test_mp.units.create("Unit") - - variable_data = pd.DataFrame( - [ - ["Region", "IAMC Variable", "Unit", 2005, 1], - ], - columns=["region", "variable", "unit", "step_year", "value"], - ) - run = test_mp.Run("Model", "Scenario", "new") - run.iamc.add(variable_data, type=ixmp4.DataPoint.Type.ANNUAL) - run.set_as_default() - - iamc_variable2 = test_mp.iamc.variables.get("IAMC Variable") - - assert iamc_variable1.id == iamc_variable2.id - - -@all_platforms -def test_iamc_variable_unqiue(test_mp): - test_mp.iamc.variables.create("IAMC Variable") - - with pytest.raises(Variable.NotUnique): - test_mp.iamc.variables.create("IAMC Variable") +from ..utils import all_platforms, assert_unordered_equality def create_testcase_iamc_variables(test_mp): @@ -60,20 +30,6 @@ def create_testcase_iamc_variables(test_mp): return iamc_variable, iamc_variable2 -@all_platforms -def test_list_iamc_variable(test_mp): - iamc_variables = create_testcase_iamc_variables(test_mp) - iamc_variable, _ = iamc_variables - - a = [v.id for v in iamc_variables] - b = [v.id for v in test_mp.iamc.variables.list()] - assert not (set(a) ^ set(b)) - - a = [iamc_variable.id] - b = [v.id for v in test_mp.iamc.variables.list(name="IAMC Variable")] - assert not (set(a) ^ set(b)) - - def df_from_list(iamc_variables): return pd.DataFrame( [[v.id, v.name, v.created_at, v.created_by] for v in iamc_variables], @@ -82,50 +38,84 @@ def df_from_list(iamc_variables): @all_platforms -def test_tabulate_iamc_variable(test_mp): - iamc_variables = create_testcase_iamc_variables(test_mp) - iamc_variable, _ = iamc_variables +class TestCoreVariable: + def test_retrieve_iamc_variable(self, test_mp): + iamc_variable1 = test_mp.iamc.variables.create("IAMC Variable") + test_mp.regions.create("Region", "default") + test_mp.units.create("Unit") + + variable_data = pd.DataFrame( + [ + ["Region", "IAMC Variable", "Unit", 2005, 1], + ], + columns=["region", "variable", "unit", "step_year", "value"], + ) + run = test_mp.Run("Model", "Scenario", "new") + run.iamc.add(variable_data, type=ixmp4.DataPoint.Type.ANNUAL) + run.set_as_default() + + iamc_variable2 = test_mp.iamc.variables.get("IAMC Variable") + + assert iamc_variable1.id == iamc_variable2.id + + def test_iamc_variable_unqiue(self, test_mp): + test_mp.iamc.variables.create("IAMC Variable") - a = df_from_list(iamc_variables) - b = test_mp.iamc.variables.tabulate() - assert_unordered_equality(a, b, check_dtype=False) + with pytest.raises(Variable.NotUnique): + test_mp.iamc.variables.create("IAMC Variable") - a = df_from_list([iamc_variable]) - b = test_mp.iamc.variables.tabulate(name="IAMC Variable") - assert_unordered_equality(a, b, check_dtype=False) + def test_list_iamc_variable(self, test_mp): + iamc_variables = create_testcase_iamc_variables(test_mp) + iamc_variable, _ = iamc_variables + a = [v.id for v in iamc_variables] + b = [v.id for v in test_mp.iamc.variables.list()] + assert not (set(a) ^ set(b)) -@all_platforms -def test_retrieve_docs(test_mp): - _, iamc_variable2 = create_testcase_iamc_variables(test_mp) - docs_iamc_variable1 = test_mp.iamc.variables.set_docs( - "IAMC Variable", "Description of test IAMC Variable" - ) - docs_iamc_variable2 = test_mp.iamc.variables.get_docs("IAMC Variable") + a = [iamc_variable.id] + b = [v.id for v in test_mp.iamc.variables.list(name="IAMC Variable")] + assert not (set(a) ^ set(b)) - assert docs_iamc_variable1 == docs_iamc_variable2 + def test_tabulate_iamc_variable(self, test_mp): + iamc_variables = create_testcase_iamc_variables(test_mp) + iamc_variable, _ = iamc_variables - assert iamc_variable2.docs is None + a = df_from_list(iamc_variables) + b = test_mp.iamc.variables.tabulate() + assert_unordered_equality(a, b, check_dtype=False) - iamc_variable2.docs = "Description of test IAMC Variable 2" + a = df_from_list([iamc_variable]) + b = test_mp.iamc.variables.tabulate(name="IAMC Variable") + assert_unordered_equality(a, b, check_dtype=False) - assert test_mp.iamc.variables.get_docs("IAMC Variable 2") == iamc_variable2.docs + def test_retrieve_docs(self, test_mp): + _, iamc_variable2 = create_testcase_iamc_variables(test_mp) + docs_iamc_variable1 = test_mp.iamc.variables.set_docs( + "IAMC Variable", "Description of test IAMC Variable" + ) + docs_iamc_variable2 = test_mp.iamc.variables.get_docs("IAMC Variable") + assert docs_iamc_variable1 == docs_iamc_variable2 -@all_platforms -def test_delete_docs(test_mp): - iamc_variable, _ = create_testcase_iamc_variables(test_mp) - iamc_variable.docs = "Description of test IAMC Variable" - iamc_variable.docs = None + assert iamc_variable2.docs is None + + iamc_variable2.docs = "Description of test IAMC Variable 2" + + assert test_mp.iamc.variables.get_docs("IAMC Variable 2") == iamc_variable2.docs + + def test_delete_docs(self, test_mp): + iamc_variable, _ = create_testcase_iamc_variables(test_mp) + iamc_variable.docs = "Description of test IAMC Variable" + iamc_variable.docs = None - assert iamc_variable.docs is None + assert iamc_variable.docs is None - iamc_variable.docs = "Second description of test IAMC Variable" - del iamc_variable.docs + iamc_variable.docs = "Second description of test IAMC Variable" + del iamc_variable.docs - assert iamc_variable.docs is None + assert iamc_variable.docs is None - iamc_variable.docs = "Third description of test IAMC Variable" - test_mp.iamc.variables.delete_docs("IAMC Variable") + iamc_variable.docs = "Third description of test IAMC Variable" + test_mp.iamc.variables.delete_docs("IAMC Variable") - assert iamc_variable.docs is None + assert iamc_variable.docs is None diff --git a/tests/data/test_docs.py b/tests/data/test_docs.py index 29e0e81f..0742b78d 100644 --- a/tests/data/test_docs.py +++ b/tests/data/test_docs.py @@ -1,221 +1,199 @@ import pytest -from ..utils import all_platforms from ixmp4.data.abstract import Docs - -@all_platforms -def test_get_and_set_modeldocs(test_mp): - model = test_mp.backend.models.create("Model") - - docs_model = test_mp.backend.models.docs.set(model.id, "Description of Model") - docs_model1 = test_mp.backend.models.docs.get(model.id) - assert docs_model == docs_model1 +from ..utils import all_platforms @all_platforms -def test_change_empty_modeldocs(test_mp): - model = test_mp.backend.models.create("Model") +class TestDataDocs: + def test_get_and_set_modeldocs(self, test_mp): + model = test_mp.backend.models.create("Model") - with pytest.raises(Docs.NotFound): - test_mp.backend.models.docs.get(model.id) + docs_model = test_mp.backend.models.docs.set(model.id, "Description of Model") + docs_model1 = test_mp.backend.models.docs.get(model.id) + assert docs_model == docs_model1 - docs_model1 = test_mp.backend.models.docs.set(model.id, "Description of test Model") + def test_change_empty_modeldocs(self, test_mp): + model = test_mp.backend.models.create("Model") - assert test_mp.backend.models.docs.get(model.id) == docs_model1 + with pytest.raises(Docs.NotFound): + test_mp.backend.models.docs.get(model.id) - docs_model2 = test_mp.backend.models.docs.set( - model.id, "Different description of test Model" - ) + docs_model1 = test_mp.backend.models.docs.set( + model.id, "Description of test Model" + ) - assert test_mp.backend.models.docs.get(model.id) == docs_model2 + assert test_mp.backend.models.docs.get(model.id) == docs_model1 + docs_model2 = test_mp.backend.models.docs.set( + model.id, "Different description of test Model" + ) -@all_platforms -def test_delete_modeldocs(test_mp): - model = test_mp.backend.models.create("Model") - docs_model = test_mp.backend.models.docs.set(model.id, "Description of test Model") + assert test_mp.backend.models.docs.get(model.id) == docs_model2 - assert test_mp.backend.models.docs.get(model.id) == docs_model + def test_delete_modeldocs(self, test_mp): + model = test_mp.backend.models.create("Model") + docs_model = test_mp.backend.models.docs.set( + model.id, "Description of test Model" + ) - test_mp.backend.models.docs.delete(model.id) + assert test_mp.backend.models.docs.get(model.id) == docs_model - with pytest.raises(Docs.NotFound): - test_mp.backend.models.docs.get(model.id) + test_mp.backend.models.docs.delete(model.id) + with pytest.raises(Docs.NotFound): + test_mp.backend.models.docs.get(model.id) -@all_platforms -def test_get_and_set_regiondocs(test_mp): - region = test_mp.backend.regions.create("Region", "Hierarchy") - docs_region = test_mp.backend.regions.docs.set( - region.id, "Description of test Region" - ) - docs_region1 = test_mp.backend.regions.docs.get(region.id) + def test_get_and_set_regiondocs(self, test_mp): + region = test_mp.backend.regions.create("Region", "Hierarchy") + docs_region = test_mp.backend.regions.docs.set( + region.id, "Description of test Region" + ) + docs_region1 = test_mp.backend.regions.docs.get(region.id) - assert docs_region == docs_region1 + assert docs_region == docs_region1 + def test_change_empty_regiondocs(self, test_mp): + region = test_mp.backend.regions.create("Region", "Hierarchy") -@all_platforms -def test_change_empty_regiondocs(test_mp): - region = test_mp.backend.regions.create("Region", "Hierarchy") + with pytest.raises(Docs.NotFound): + test_mp.backend.regions.docs.get(region.id) - with pytest.raises(Docs.NotFound): - test_mp.backend.regions.docs.get(region.id) + docs_region1 = test_mp.backend.regions.docs.set( + region.id, "Description of test region" + ) - docs_region1 = test_mp.backend.regions.docs.set( - region.id, "Description of test region" - ) + assert test_mp.backend.regions.docs.get(region.id) == docs_region1 - assert test_mp.backend.regions.docs.get(region.id) == docs_region1 + docs_region2 = test_mp.backend.regions.docs.set( + region.id, "Different description of test region" + ) - docs_region2 = test_mp.backend.regions.docs.set( - region.id, "Different description of test region" - ) + assert test_mp.backend.regions.docs.get(region.id) == docs_region2 - assert test_mp.backend.regions.docs.get(region.id) == docs_region2 + def test_delete_regiondocs(self, test_mp): + region = test_mp.backend.regions.create("Region", "Hierarchy") + docs_region = test_mp.backend.regions.docs.set( + region.id, "Description of test region" + ) + assert test_mp.backend.regions.docs.get(region.id) == docs_region -@all_platforms -def test_delete_regiondocs(test_mp): - region = test_mp.backend.regions.create("Region", "Hierarchy") - docs_region = test_mp.backend.regions.docs.set( - region.id, "Description of test region" - ) + test_mp.backend.regions.docs.delete(region.id) - assert test_mp.backend.regions.docs.get(region.id) == docs_region + with pytest.raises(Docs.NotFound): + test_mp.backend.regions.docs.get(region.id) - test_mp.backend.regions.docs.delete(region.id) + def test_get_and_set_scenariodocs(self, test_mp): + scenario = test_mp.backend.scenarios.create("Scenario") + docs_scenario = test_mp.backend.scenarios.docs.set( + scenario.id, "Description of Scenario" + ) + docs_scenario1 = test_mp.backend.scenarios.docs.get(scenario.id) + assert docs_scenario == docs_scenario1 - with pytest.raises(Docs.NotFound): - test_mp.backend.regions.docs.get(region.id) + def test_change_empty_scenariodocs(self, test_mp): + scenario = test_mp.backend.scenarios.create("Scenario") + with pytest.raises(Docs.NotFound): + test_mp.backend.scenarios.docs.get(scenario.id) -@all_platforms -def test_get_and_set_scenariodocs(test_mp): - scenario = test_mp.backend.scenarios.create("Scenario") - docs_scenario = test_mp.backend.scenarios.docs.set( - scenario.id, "Description of Scenario" - ) - docs_scenario1 = test_mp.backend.scenarios.docs.get(scenario.id) - assert docs_scenario == docs_scenario1 + docs_scenario1 = test_mp.backend.scenarios.docs.set( + scenario.id, "Description of test Scenario" + ) + assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario1 -@all_platforms -def test_change_empty_scenariodocs(test_mp): - scenario = test_mp.backend.scenarios.create("Scenario") + docs_scenario2 = test_mp.backend.scenarios.docs.set( + scenario.id, "Different description of test Scenario" + ) - with pytest.raises(Docs.NotFound): - test_mp.backend.scenarios.docs.get(scenario.id) + assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario2 - docs_scenario1 = test_mp.backend.scenarios.docs.set( - scenario.id, "Description of test Scenario" - ) + def test_delete_scenariodocs(self, test_mp): + scenario = test_mp.backend.scenarios.create("Scenario") + docs_scenario = test_mp.backend.scenarios.docs.set( + scenario.id, "Description of test Scenario" + ) - assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario1 + assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario - docs_scenario2 = test_mp.backend.scenarios.docs.set( - scenario.id, "Different description of test Scenario" - ) + test_mp.backend.scenarios.docs.delete(scenario.id) - assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario2 + with pytest.raises(Docs.NotFound): + test_mp.backend.scenarios.docs.get(scenario.id) + def test_get_and_set_unitdocs(self, test_mp): + unit = test_mp.backend.units.create("Unit") + docs_unit = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") + docs_unit1 = test_mp.backend.units.docs.get(unit.id) -@all_platforms -def test_delete_scenariodocs(test_mp): - scenario = test_mp.backend.scenarios.create("Scenario") - docs_scenario = test_mp.backend.scenarios.docs.set( - scenario.id, "Description of test Scenario" - ) + assert docs_unit == docs_unit1 - assert test_mp.backend.scenarios.docs.get(scenario.id) == docs_scenario + def test_change_empty_unitdocs(self, test_mp): + unit = test_mp.backend.units.create("Unit") - test_mp.backend.scenarios.docs.delete(scenario.id) + with pytest.raises(Docs.NotFound): + test_mp.backend.units.docs.get(unit.id) - with pytest.raises(Docs.NotFound): - test_mp.backend.scenarios.docs.get(scenario.id) + docs_unit1 = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") + assert test_mp.backend.units.docs.get(unit.id) == docs_unit1 -@all_platforms -def test_get_and_set_unitdocs(test_mp): - unit = test_mp.backend.units.create("Unit") - docs_unit = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") - docs_unit1 = test_mp.backend.units.docs.get(unit.id) + docs_unit2 = test_mp.backend.units.docs.set( + unit.id, "Different description of test Unit" + ) - assert docs_unit == docs_unit1 + assert test_mp.backend.units.docs.get(unit.id) == docs_unit2 + def test_delete_unitdocs(self, test_mp): + unit = test_mp.backend.units.create("Unit") + docs_unit = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") -@all_platforms -def test_change_empty_unitdocs(test_mp): - unit = test_mp.backend.units.create("Unit") + assert test_mp.backend.units.docs.get(unit.id) == docs_unit - with pytest.raises(Docs.NotFound): - test_mp.backend.units.docs.get(unit.id) + test_mp.backend.units.docs.delete(unit.id) - docs_unit1 = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") + with pytest.raises(Docs.NotFound): + test_mp.backend.units.docs.get(unit.id) - assert test_mp.backend.units.docs.get(unit.id) == docs_unit1 + def test_get_and_set_variabledocs(self, test_mp): + variable = test_mp.backend.iamc.variables.create("Variable") + docs_variable = test_mp.backend.iamc.variables.docs.set( + variable.id, "Description of test Variable" + ) + docs_variables1 = test_mp.backend.iamc.variables.docs.get(variable.id) - docs_unit2 = test_mp.backend.units.docs.set( - unit.id, "Different description of test Unit" - ) + assert docs_variable == docs_variables1 - assert test_mp.backend.units.docs.get(unit.id) == docs_unit2 + def test_change_empty_variabledocs(self, test_mp): + variable = test_mp.backend.iamc.variables.create("Variable") + with pytest.raises(Docs.NotFound): + test_mp.backend.iamc.variables.docs.get(variable.id) -@all_platforms -def test_delete_unitdocs(test_mp): - unit = test_mp.backend.units.create("Unit") - docs_unit = test_mp.backend.units.docs.set(unit.id, "Description of test Unit") + docs_variable1 = test_mp.backend.iamc.variables.docs.set( + variable.id, "Description of test Variable" + ) - assert test_mp.backend.units.docs.get(unit.id) == docs_unit + assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable1 - test_mp.backend.units.docs.delete(unit.id) + docs_variable2 = test_mp.backend.iamc.variables.docs.set( + variable.id, "Different description of test Variable" + ) - with pytest.raises(Docs.NotFound): - test_mp.backend.units.docs.get(unit.id) + assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable2 + def test_delete_variabledocs(self, test_mp): + variable = test_mp.backend.iamc.variables.create("Variable") + docs_variable = test_mp.backend.iamc.variables.docs.set( + variable.id, "Description of test Variable" + ) -@all_platforms -def test_get_and_set_variabledocs(test_mp): - variable = test_mp.backend.iamc.variables.create("Variable") - docs_variable = test_mp.backend.iamc.variables.docs.set( - variable.id, "Description of test Variable" - ) - docs_variables1 = test_mp.backend.iamc.variables.docs.get(variable.id) - - assert docs_variable == docs_variables1 - - -@all_platforms -def test_change_empty_variabledocs(test_mp): - variable = test_mp.backend.iamc.variables.create("Variable") - - with pytest.raises(Docs.NotFound): - test_mp.backend.iamc.variables.docs.get(variable.id) - - docs_variable1 = test_mp.backend.iamc.variables.docs.set( - variable.id, "Description of test Variable" - ) - - assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable1 - - docs_variable2 = test_mp.backend.iamc.variables.docs.set( - variable.id, "Different description of test Variable" - ) - - assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable2 - - -@all_platforms -def test_delete_variabledocs(test_mp): - variable = test_mp.backend.iamc.variables.create("Variable") - docs_variable = test_mp.backend.iamc.variables.docs.set( - variable.id, "Description of test Variable" - ) - - assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable + assert test_mp.backend.iamc.variables.docs.get(variable.id) == docs_variable - test_mp.backend.iamc.variables.docs.delete(variable.id) + test_mp.backend.iamc.variables.docs.delete(variable.id) - with pytest.raises(Docs.NotFound): - test_mp.backend.iamc.variables.docs.get(variable.id) + with pytest.raises(Docs.NotFound): + test_mp.backend.iamc.variables.docs.get(variable.id) diff --git a/tests/data/test_iamc_datapoint.py b/tests/data/test_iamc_datapoint.py index 38c9134d..489d8569 100644 --- a/tests/data/test_iamc_datapoint.py +++ b/tests/data/test_iamc_datapoint.py @@ -2,6 +2,8 @@ import pandas as pd from ..utils import add_regions, add_units, all_platforms, assert_unordered_equality +from ixmp4.core.exceptions import BadFilterArguments + @all_platforms @pytest.mark.parametrize( @@ -56,3 +58,21 @@ def test_filtering(test_mp, filter, exp_filter): if exp_filter is not None: exp = exp[getattr(exp[exp_filter[0]], exp_filter[1])(exp_filter[2])] assert_unordered_equality(obs, exp, check_like=True) + + +@all_platforms +@pytest.mark.parametrize( + "filter", + [ + {"unit": "test"}, + {"dne": {"dne": "test"}}, + {"region": {"dne": "test"}}, + {"region": {"name__in": False}}, + {"run": {"default_only": "test"}}, + ], +) +def test_invalid_filters(test_mp, filter): + with pytest.raises(BadFilterArguments): + test_mp.backend.iamc.datapoints.tabulate(**filter) + with pytest.raises(BadFilterArguments): + test_mp.backend.iamc.datapoints.list(**filter) diff --git a/tests/data/test_iamc_variable.py b/tests/data/test_iamc_variable.py index 33788c9a..fc990258 100644 --- a/tests/data/test_iamc_variable.py +++ b/tests/data/test_iamc_variable.py @@ -1,61 +1,57 @@ import pytest + from ixmp4 import Variable from ..utils import all_platforms, create_filter_test_data @all_platforms -def test_create_iamc_variable(test_mp): - variable = test_mp.backend.iamc.variables.create("Variable") - assert variable.name == "Variable" - assert variable.created_at is not None - assert variable.created_by == "@unknown" - - -@all_platforms -def test_iamc_variable_unique(test_mp): - test_mp.backend.iamc.variables.create("Variable") - - with pytest.raises(Variable.NotUnique): - test_mp.iamc.variables.create("Variable") - - -@all_platforms -def test_iamc_variable_not_found(test_mp): - with pytest.raises(Variable.NotFound): - test_mp.iamc.variables.get("Variable") - - -@all_platforms -def test_filter_iamc_variable(test_mp): - run1, run2 = create_filter_test_data(test_mp) - res = test_mp.backend.iamc.variables.tabulate(unit={"name": "Unit 1"}) - assert sorted(res["name"].tolist()) == ["Variable 1", "Variable 2"] - - run2.set_as_default() - res = test_mp.backend.iamc.variables.tabulate( - unit={"name": "Unit 3"}, region={"name": "Region 3"} - ) - assert sorted(res["name"].tolist()) == ["Variable 1"] - - run1.set_as_default() - res = test_mp.backend.iamc.variables.tabulate( - unit={"name": "Unit 3"}, - region={"name__in": ["Region 4", "Region 5"]}, - run={"model": {"name": "Model 1"}, "default_only": True}, - ) - assert res["name"].tolist() == [] - - res = test_mp.backend.iamc.variables.tabulate( - unit={"name": "Unit 3"}, - region={"name__in": ["Region 4", "Region 5"]}, - run={"default_only": False}, - ) - assert sorted(res["name"].tolist()) == ["Variable 2"] - - res = test_mp.backend.iamc.variables.tabulate() - - assert sorted(res["name"].tolist()) == [ - "Variable 1", - "Variable 2", - ] +class TestDataIamcVariable: + def test_create_iamc_variable(self, test_mp): + variable = test_mp.backend.iamc.variables.create("Variable") + assert variable.name == "Variable" + assert variable.created_at is not None + assert variable.created_by == "@unknown" + + def test_iamc_variable_unique(self, test_mp): + test_mp.backend.iamc.variables.create("Variable") + + with pytest.raises(Variable.NotUnique): + test_mp.iamc.variables.create("Variable") + + def test_iamc_variable_not_found(self, test_mp): + with pytest.raises(Variable.NotFound): + test_mp.iamc.variables.get("Variable") + + def test_filter_iamc_variable(self, test_mp): + run1, run2 = create_filter_test_data(test_mp) + res = test_mp.backend.iamc.variables.tabulate(unit={"name": "Unit 1"}) + assert sorted(res["name"].tolist()) == ["Variable 1", "Variable 2"] + + run2.set_as_default() + res = test_mp.backend.iamc.variables.tabulate( + unit={"name": "Unit 3"}, region={"name": "Region 3"} + ) + assert sorted(res["name"].tolist()) == ["Variable 1"] + + run1.set_as_default() + res = test_mp.backend.iamc.variables.tabulate( + unit={"name": "Unit 3"}, + region={"name__in": ["Region 4", "Region 5"]}, + run={"model": {"name": "Model 1"}, "default_only": True}, + ) + assert res["name"].tolist() == [] + + res = test_mp.backend.iamc.variables.tabulate( + unit={"name": "Unit 3"}, + region={"name__in": ["Region 4", "Region 5"]}, + run={"default_only": False}, + ) + assert sorted(res["name"].tolist()) == ["Variable 2"] + + res = test_mp.backend.iamc.variables.tabulate() + + assert sorted(res["name"].tolist()) == [ + "Variable 1", + "Variable 2", + ] diff --git a/tests/data/test_meta.py b/tests/data/test_meta.py index 4e3c6ff7..bac00c03 100644 --- a/tests/data/test_meta.py +++ b/tests/data/test_meta.py @@ -1,10 +1,10 @@ -import pytest import pandas as pd +import pytest -from ixmp4.data.abstract.meta import RunMetaEntry from ixmp4.core.exceptions import SchemaError +from ixmp4.data.abstract.meta import RunMetaEntry -from ..utils import assert_unordered_equality, all_platforms +from ..utils import all_platforms, assert_unordered_equality TEST_ENTRIES = [ ("Boolean", True, RunMetaEntry.Type.BOOL), @@ -20,157 +20,146 @@ @all_platforms -def test_create_get_entry(test_mp): - run = test_mp.Run("Model", "Scenario", "new") +class TestDataMeta: + def test_create_get_entry(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + + for key, value, type in TEST_ENTRIES: + entry = test_mp.backend.meta.create(run.id, key, value) + assert entry.key == key + assert entry.value == value + assert entry.type == type + + for key, value, type in TEST_ENTRIES: + entry = test_mp.backend.meta.get(run.id, key) + assert entry.key == key + assert entry.value == value + assert entry.type == type + + def test_entry_unique(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + test_mp.backend.meta.create(run.id, "Key", "Value") - for key, value, type in TEST_ENTRIES: - entry = test_mp.backend.meta.create(run.id, key, value) - assert entry.key == key - assert entry.value == value - assert entry.type == type + with pytest.raises(RunMetaEntry.NotUnique): + test_mp.backend.meta.create(run.id, "Key", "Value") - for key, value, type in TEST_ENTRIES: - entry = test_mp.backend.meta.get(run.id, key) - assert entry.key == key - assert entry.value == value - assert entry.type == type + with pytest.raises(RunMetaEntry.NotUnique): + test_mp.backend.meta.create(run.id, "Key", 1) + def test_entry_not_found(self, test_mp): + with pytest.raises(RunMetaEntry.NotFound): + test_mp.backend.meta.get(-1, "Key") -@all_platforms -def test_entry_unique(test_mp): - run = test_mp.Run("Model", "Scenario", "new") - test_mp.backend.meta.create(run.id, "Key", "Value") + run = test_mp.Run("Model", "Scenario", "new") - with pytest.raises(RunMetaEntry.NotUnique): - test_mp.backend.meta.create(run.id, "Key", "Value") + with pytest.raises(RunMetaEntry.NotFound): + test_mp.backend.meta.get(run.id, "Key") - with pytest.raises(RunMetaEntry.NotUnique): - test_mp.backend.meta.create(run.id, "Key", 1) + def test_delete_entry(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") + entry = test_mp.backend.meta.create(run.id, "Key", "Value") + test_mp.backend.meta.delete(entry.id) + with pytest.raises(RunMetaEntry.NotFound): + test_mp.backend.meta.get(run.id, "Key") -@all_platforms -def test_entry_not_found(test_mp): - with pytest.raises(RunMetaEntry.NotFound): - test_mp.backend.meta.get(-1, "Key") + def test_list_entry(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") - run = test_mp.Run("Model", "Scenario", "new") + for key, value, _ in TEST_ENTRIES: + entry = test_mp.backend.meta.create(run.id, key, value) - with pytest.raises(RunMetaEntry.NotFound): - test_mp.backend.meta.get(run.id, "Key") + entries = test_mp.backend.regions.list() + for (key, value, type), entry in zip(TEST_ENTRIES, entries): + assert entry.key == key + assert entry.value == value + assert entry.type == type -@all_platforms -def test_delete_entry(test_mp): - run = test_mp.Run("Model", "Scenario", "new") - entry = test_mp.backend.meta.create(run.id, "Key", "Value") - test_mp.backend.meta.delete(entry.id) + def test_tabulate_entry(self, test_mp): + run = test_mp.Run("Model", "Scenario", "new") - with pytest.raises(RunMetaEntry.NotFound): - test_mp.backend.meta.get(run.id, "Key") + for key, value, _ in TEST_ENTRIES: + test_mp.backend.meta.create(run.id, key, value) + true_entries = TEST_ENTRIES_DF.copy() + true_entries["run__id"] = run.id -@all_platforms -def test_list_entry(test_mp): - run = test_mp.Run("Model", "Scenario", "new") + entries = test_mp.backend.meta.tabulate() + assert_unordered_equality(entries, true_entries) - for key, value, _ in TEST_ENTRIES: - entry = test_mp.backend.meta.create(run.id, key, value) + def test_entry_bulk_operations(self, test_mp): + run = test_mp.Run("Model", "Scenario", version="new") + entries = TEST_ENTRIES_DF.copy() + entries["run__id"] = run.id - entries = test_mp.backend.regions.list() + # == Full Addition == + test_mp.backend.meta.bulk_upsert(entries.drop(columns=["id", "type"])) + ret = test_mp.backend.meta.tabulate() + assert_unordered_equality(entries, ret) - for (key, value, type), entry in zip(TEST_ENTRIES, entries): - assert entry.key == key - assert entry.value == value - assert entry.type == type + # == Partial Removal == + # Remove half the data + remove_data = entries.head(len(entries) // 2).drop( + columns=["value", "id", "type"] + ) + remaining_data = entries.tail(len(entries) // 2).reset_index(drop=True) + test_mp.backend.meta.bulk_delete(remove_data) + ret = test_mp.backend.meta.tabulate() + assert_unordered_equality(remaining_data, ret) -@all_platforms -def test_tabulate_entry(test_mp): - run = test_mp.Run("Model", "Scenario", "new") + # == Partial Update / Partial Addition == + entries["value"] = -9.9 + entries["id"] = [5, 6, 3, 4] - for key, value, _ in TEST_ENTRIES: - test_mp.backend.meta.create(run.id, key, value) + updated_entries = pd.DataFrame( + [ + [5, "Boolean", -9.9, RunMetaEntry.Type.FLOAT], + [6, "Float", -9.9, RunMetaEntry.Type.FLOAT], + [3, "Integer", -9.9, RunMetaEntry.Type.FLOAT], + [4, "String", -9.9, RunMetaEntry.Type.FLOAT], + ], + columns=["id", "key", "value", "type"], + ) + updated_entries["run__id"] = run.id + updated_entries["value"] = updated_entries["value"].astype("object") # type: ignore - true_entries = TEST_ENTRIES_DF.copy() - true_entries["run__id"] = run.id + test_mp.backend.meta.bulk_upsert(updated_entries.drop(columns=["id", "type"])) + ret = test_mp.backend.meta.tabulate() - entries = test_mp.backend.meta.tabulate() - assert_unordered_equality(entries, true_entries) + assert_unordered_equality(updated_entries, ret, check_like=True) + # == Full Removal == + remove_data = entries.drop(columns=["value", "id", "type"]) + test_mp.backend.meta.bulk_delete(remove_data) -@all_platforms -def test_entry_bulk_operations(test_mp): - run = test_mp.Run("Model", "Scenario", version="new") - entries = TEST_ENTRIES_DF.copy() - entries["run__id"] = run.id - - # == Full Addition == - test_mp.backend.meta.bulk_upsert(entries.drop(columns=["id", "type"])) - ret = test_mp.backend.meta.tabulate() - assert_unordered_equality(entries, ret) - - # == Partial Removal == - # Remove half the data - remove_data = entries.head(len(entries) // 2).drop(columns=["value", "id", "type"]) - remaining_data = entries.tail(len(entries) // 2).reset_index(drop=True) - test_mp.backend.meta.bulk_delete(remove_data) - - ret = test_mp.backend.meta.tabulate() - assert_unordered_equality(remaining_data, ret) - - # == Partial Update / Partial Addition == - entries["value"] = -9.9 - entries["id"] = [5, 6, 3, 4] - - updated_entries = pd.DataFrame( - [ - [5, "Boolean", -9.9, RunMetaEntry.Type.FLOAT], - [6, "Float", -9.9, RunMetaEntry.Type.FLOAT], - [3, "Integer", -9.9, RunMetaEntry.Type.FLOAT], - [4, "String", -9.9, RunMetaEntry.Type.FLOAT], - ], - columns=["id", "key", "value", "type"], - ) - updated_entries["run__id"] = run.id - updated_entries["value"] = updated_entries["value"].astype("object") # type: ignore - - test_mp.backend.meta.bulk_upsert(updated_entries.drop(columns=["id", "type"])) - ret = test_mp.backend.meta.tabulate() - - assert_unordered_equality(updated_entries, ret, check_like=True) - - # == Full Removal == - remove_data = entries.drop(columns=["value", "id", "type"]) - test_mp.backend.meta.bulk_delete(remove_data) - - ret = test_mp.backend.meta.tabulate() - assert ret.empty + ret = test_mp.backend.meta.tabulate() + assert ret.empty + def test_meta_bulk_exceptions(self, test_mp): + entries = pd.DataFrame( + [ + ["Boolean", -9.9], + ["Float", -9.9], + ["Integer", -9.9], + ["String", -9.9], + ], + columns=["key", "value"], + ) + run = test_mp.Run("Model", "Scenario", version="new") + entries["run__id"] = run.id -@all_platforms -def test_meta_bulk_exceptions(test_mp): - entries = pd.DataFrame( - [ - ["Boolean", -9.9], - ["Float", -9.9], - ["Integer", -9.9], - ["String", -9.9], - ], - columns=["key", "value"], - ) - run = test_mp.Run("Model", "Scenario", version="new") - entries["run__id"] = run.id - - duplicated_entries = pd.concat([entries] * 2, ignore_index=True) - - with pytest.raises(RunMetaEntry.NotUnique): - test_mp.backend.meta.bulk_upsert(duplicated_entries) - - entries["foo"] = "bar" - - with pytest.raises(SchemaError): - test_mp.backend.meta.bulk_upsert(entries) - - entries = entries.drop(columns=["value"]) - with pytest.raises(SchemaError): - test_mp.backend.meta.bulk_delete(entries) + duplicated_entries = pd.concat([entries] * 2, ignore_index=True) + + with pytest.raises(RunMetaEntry.NotUnique): + test_mp.backend.meta.bulk_upsert(duplicated_entries) + + entries["foo"] = "bar" + + with pytest.raises(SchemaError): + test_mp.backend.meta.bulk_upsert(entries) + + entries = entries.drop(columns=["value"]) + with pytest.raises(SchemaError): + test_mp.backend.meta.bulk_delete(entries) diff --git a/tests/data/test_model.py b/tests/data/test_model.py index 669ddde0..5adcc8ca 100644 --- a/tests/data/test_model.py +++ b/tests/data/test_model.py @@ -3,103 +3,92 @@ from ixmp4 import Model -from ..utils import assert_unordered_equality, all_platforms, create_filter_test_data +from ..utils import all_platforms, assert_unordered_equality, create_filter_test_data @all_platforms -def test_create_model(test_mp): - model = test_mp.backend.models.create("Model") - assert model.name == "Model" - assert model.created_at is not None - assert model.created_by == "@unknown" - - -@all_platforms -def test_model_unique(test_mp): - test_mp.backend.models.create("Model") - - with pytest.raises(Model.NotUnique): - test_mp.models.create("Model") - - -@all_platforms -def test_get_model(test_mp): - model1 = test_mp.backend.models.create("Model") - model2 = test_mp.backend.models.get("Model") - assert model1 == model2 - - -@all_platforms -def test_model_not_found(test_mp): - with pytest.raises(Model.NotFound): - test_mp.models.get("Model") - - -@all_platforms -def test_list_model(test_mp): - test_mp.Run("Model 1", "Scenario", version="new") - test_mp.Run("Model 2", "Scenario", version="new") - - models = sorted(test_mp.backend.models.list(), key=lambda x: x.id) - assert models[0].id == 1 - assert models[0].name == "Model 1" - assert models[1].id == 2 - assert models[1].name == "Model 2" - - -@all_platforms -def test_tabulate_model(test_mp): - test_mp.Run("Model 1", "Scenario", version="new") - test_mp.Run("Model 2", "Scenario", version="new") - - true_models = pd.DataFrame( - [ - [1, "Model 1"], - [2, "Model 2"], - ], - columns=["id", "name"], - ) - - models = test_mp.backend.models.tabulate() - assert_unordered_equality( - models.drop(columns=["created_at", "created_by"]), true_models - ) - - -@all_platforms -def test_filter_model(test_mp): - run1, _ = create_filter_test_data(test_mp) - - res = test_mp.backend.models.tabulate( - iamc={ - "region": {"name": "Region 1"}, - "run": {"default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Model 1"] - - res = test_mp.backend.models.tabulate( - iamc={ - "region": {"name": "Region 3"}, - "run": {"default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Model 1", "Model 2"] - - run1.set_as_default() - res = test_mp.backend.models.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "unit": {"name__in": ["Unit 3", "Unit 4"]}, - "run": {"default_only": True}, - } - ) - assert res["name"].tolist() == ["Model 2"] - - res = test_mp.backend.models.tabulate( - iamc={ - "run": {"default_only": False, "scenario": {"name": "Scenario 2"}}, - } - ) - - assert sorted(res["name"].tolist()) == ["Model 2"] +class TestDataModel: + def test_create_model(self, test_mp): + model = test_mp.backend.models.create("Model") + assert model.name == "Model" + assert model.created_at is not None + assert model.created_by == "@unknown" + + def test_model_unique(self, test_mp): + test_mp.backend.models.create("Model") + + with pytest.raises(Model.NotUnique): + test_mp.models.create("Model") + + def test_get_model(self, test_mp): + model1 = test_mp.backend.models.create("Model") + model2 = test_mp.backend.models.get("Model") + assert model1 == model2 + + def test_model_not_found(self, test_mp): + with pytest.raises(Model.NotFound): + test_mp.models.get("Model") + + def test_list_model(self, test_mp): + test_mp.Run("Model 1", "Scenario", version="new") + test_mp.Run("Model 2", "Scenario", version="new") + + models = sorted(test_mp.backend.models.list(), key=lambda x: x.id) + assert models[0].id == 1 + assert models[0].name == "Model 1" + assert models[1].id == 2 + assert models[1].name == "Model 2" + + def test_tabulate_model(self, test_mp): + test_mp.Run("Model 1", "Scenario", version="new") + test_mp.Run("Model 2", "Scenario", version="new") + + true_models = pd.DataFrame( + [ + [1, "Model 1"], + [2, "Model 2"], + ], + columns=["id", "name"], + ) + + models = test_mp.backend.models.tabulate() + assert_unordered_equality( + models.drop(columns=["created_at", "created_by"]), true_models + ) + + def test_filter_model(self, test_mp): + run1, _ = create_filter_test_data(test_mp) + + res = test_mp.backend.models.tabulate( + iamc={ + "region": {"name": "Region 1"}, + "run": {"default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Model 1"] + + res = test_mp.backend.models.tabulate( + iamc={ + "region": {"name": "Region 3"}, + "run": {"default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Model 1", "Model 2"] + + run1.set_as_default() + res = test_mp.backend.models.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "unit": {"name__in": ["Unit 3", "Unit 4"]}, + "run": {"default_only": True}, + } + ) + assert res["name"].tolist() == ["Model 2"] + + res = test_mp.backend.models.tabulate( + iamc={ + "run": {"default_only": False, "scenario": {"name": "Scenario 2"}}, + } + ) + + assert sorted(res["name"].tolist()) == ["Model 2"] diff --git a/tests/data/test_region.py b/tests/data/test_region.py index 3b74681b..59b74d77 100644 --- a/tests/data/test_region.py +++ b/tests/data/test_region.py @@ -1,148 +1,133 @@ -import pytest import pandas as pd +import pytest from ixmp4 import Region -from ..utils import assert_unordered_equality, all_platforms, create_filter_test_data - - -@all_platforms -def test_create_region(test_mp): - region1 = test_mp.backend.regions.create("Region", "Hierarchy") - assert region1.name == "Region" - assert region1.hierarchy == "Hierarchy" - assert region1.created_at is not None - assert region1.created_by == "@unknown" - - -@all_platforms -def test_delete_region(test_mp): - region1 = test_mp.backend.regions.create("Region", "Hierarchy") - test_mp.backend.regions.delete(region1.id) - assert test_mp.backend.regions.tabulate().empty - - -@all_platforms -def test_region_unique(test_mp): - test_mp.backend.regions.create("Region", "Hierarchy") - - with pytest.raises(Region.NotUnique): - test_mp.regions.create("Region", "Hierarchy") - - with pytest.raises(Region.NotUnique): - test_mp.regions.create("Region", "Another Hierarchy") - - -@all_platforms -def test_get_region(test_mp): - region1 = test_mp.backend.regions.create("Region", "Hierarchy") - region2 = test_mp.backend.regions.get("Region") - assert region1 == region2 - - -@all_platforms -def test_region_not_found(test_mp): - with pytest.raises(Region.NotFound): - test_mp.regions.get("Region") - - -@all_platforms -def test_get_or_create_region(test_mp): - region1 = test_mp.backend.regions.create("Region", "Hierarchy") - region2 = test_mp.backend.regions.get_or_create("Region") - assert region1.id == region2.id - - test_mp.backend.regions.get_or_create("Other", hierarchy="Hierarchy") - - with pytest.raises(Region.NotUnique): - test_mp.backend.regions.get_or_create("Other", hierarchy="Other Hierarchy") - - -@all_platforms -def test_list_region(test_mp): - region1 = test_mp.backend.regions.create("Region 1", "Hierarchy") - test_mp.backend.regions.create("Region 2", "Hierarchy") - - regions = test_mp.backend.regions.list() - regions = sorted(regions, key=lambda x: x.id) - assert regions[0].id == 1 - assert regions[0].name == "Region 1" - assert regions[0].hierarchy == "Hierarchy" - assert regions[1].id == 2 - assert regions[1].name == "Region 2" - - -@all_platforms -def test_tabulate_region(test_mp): - region1 = test_mp.backend.regions.create("Region 1", "Hierarchy") - test_mp.backend.regions.create("Region 2", "Hierarchy") - - true_regions = pd.DataFrame( - [ - [1, "Region 1", "Hierarchy"], - [2, "Region 2", "Hierarchy"], - ], - columns=["id", "name", "hierarchy"], - ) - - regions = test_mp.backend.regions.tabulate() - assert_unordered_equality( - regions.drop(columns=["created_at", "created_by"]), true_regions - ) +from ..utils import all_platforms, assert_unordered_equality, create_filter_test_data @all_platforms -def test_filter_region(test_mp): - run1, run2 = create_filter_test_data(test_mp) - - res = test_mp.backend.regions.tabulate( - iamc={ - "run": {"model": {"name": "Model 1"}}, - "variable": {"name": "Variable 1"}, - } - ) - assert sorted(res["name"].tolist()) == ["Region 1", "Region 3"] - - run2.set_as_default() - res = test_mp.backend.regions.tabulate( - iamc={ - "run": {"model": {"name": "Model 1"}}, - "variable": {"name": "Variable 1"}, - } - ) - assert sorted(res["name"].tolist()) == ["Region 3", "Region 5"] - - run1.set_as_default() - res = test_mp.backend.regions.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "unit": {"name__in": ["Unit 3", "Unit 4"]}, - "run": {"model": {"name": "Model 1"}, "default_only": True}, - } - ) - assert res["name"].tolist() == [] - - res = test_mp.backend.regions.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "unit": {"name__in": ["Unit 3", "Unit 4"]}, - "run": {"model": {"name": "Model 1"}, "default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Region 3", "Region 5"] - - res = test_mp.backend.regions.tabulate(iamc=False) - - assert res["name"].tolist() == ["Region 7"] - - res = test_mp.backend.regions.tabulate() - - assert sorted(res["name"].tolist()) == [ - "Region 1", - "Region 2", - "Region 3", - "Region 4", - "Region 5", - "Region 6", - "Region 7", - ] +class TestDataRegion: + def test_create_region(self, test_mp): + region1 = test_mp.backend.regions.create("Region", "Hierarchy") + assert region1.name == "Region" + assert region1.hierarchy == "Hierarchy" + assert region1.created_at is not None + assert region1.created_by == "@unknown" + + def test_delete_region(self, test_mp): + region1 = test_mp.backend.regions.create("Region", "Hierarchy") + test_mp.backend.regions.delete(region1.id) + assert test_mp.backend.regions.tabulate().empty + + def test_region_unique(self, test_mp): + test_mp.backend.regions.create("Region", "Hierarchy") + + with pytest.raises(Region.NotUnique): + test_mp.regions.create("Region", "Hierarchy") + + with pytest.raises(Region.NotUnique): + test_mp.regions.create("Region", "Another Hierarchy") + + def test_get_region(self, test_mp): + region1 = test_mp.backend.regions.create("Region", "Hierarchy") + region2 = test_mp.backend.regions.get("Region") + assert region1 == region2 + + def test_region_not_found(self, test_mp): + with pytest.raises(Region.NotFound): + test_mp.regions.get("Region") + + def test_get_or_create_region(self, test_mp): + region1 = test_mp.backend.regions.create("Region", "Hierarchy") + region2 = test_mp.backend.regions.get_or_create("Region") + assert region1.id == region2.id + + test_mp.backend.regions.get_or_create("Other", hierarchy="Hierarchy") + + with pytest.raises(Region.NotUnique): + test_mp.backend.regions.get_or_create("Other", hierarchy="Other Hierarchy") + + def test_list_region(self, test_mp): + test_mp.backend.regions.create("Region 1", "Hierarchy") + test_mp.backend.regions.create("Region 2", "Hierarchy") + + regions = test_mp.backend.regions.list() + regions = sorted(regions, key=lambda x: x.id) + assert regions[0].id == 1 + assert regions[0].name == "Region 1" + assert regions[0].hierarchy == "Hierarchy" + assert regions[1].id == 2 + assert regions[1].name == "Region 2" + + def test_tabulate_region(self, test_mp): + test_mp.backend.regions.create("Region 1", "Hierarchy") + test_mp.backend.regions.create("Region 2", "Hierarchy") + + true_regions = pd.DataFrame( + [ + [1, "Region 1", "Hierarchy"], + [2, "Region 2", "Hierarchy"], + ], + columns=["id", "name", "hierarchy"], + ) + + regions = test_mp.backend.regions.tabulate() + assert_unordered_equality( + regions.drop(columns=["created_at", "created_by"]), true_regions + ) + + def test_filter_region(self, test_mp): + run1, run2 = create_filter_test_data(test_mp) + + res = test_mp.backend.regions.tabulate( + iamc={ + "run": {"model": {"name": "Model 1"}}, + "variable": {"name": "Variable 1"}, + } + ) + assert sorted(res["name"].tolist()) == ["Region 1", "Region 3"] + + run2.set_as_default() + res = test_mp.backend.regions.tabulate( + iamc={ + "run": {"model": {"name": "Model 1"}}, + "variable": {"name": "Variable 1"}, + } + ) + assert sorted(res["name"].tolist()) == ["Region 3", "Region 5"] + + run1.set_as_default() + res = test_mp.backend.regions.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "unit": {"name__in": ["Unit 3", "Unit 4"]}, + "run": {"model": {"name": "Model 1"}, "default_only": True}, + } + ) + assert res["name"].tolist() == [] + + res = test_mp.backend.regions.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "unit": {"name__in": ["Unit 3", "Unit 4"]}, + "run": {"model": {"name": "Model 1"}, "default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Region 3", "Region 5"] + + res = test_mp.backend.regions.tabulate(iamc=False) + + assert res["name"].tolist() == ["Region 7"] + + res = test_mp.backend.regions.tabulate() + + assert sorted(res["name"].tolist()) == [ + "Region 1", + "Region 2", + "Region 3", + "Region 4", + "Region 5", + "Region 6", + "Region 7", + ] diff --git a/tests/data/test_run.py b/tests/data/test_run.py index e24f7ac6..f7437fb2 100644 --- a/tests/data/test_run.py +++ b/tests/data/test_run.py @@ -1,100 +1,95 @@ -import pytest import pandas as pd +import pytest from ixmp4.core.exceptions import NoDefaultRunVersion -from ..utils import assert_unordered_equality, all_platforms - - -@all_platforms -def test_create_run(test_mp): - run1 = test_mp.backend.runs.create("Model", "Scenario") - assert run1.model.name == "Model" - assert run1.scenario.name == "Scenario" - assert run1.version == 1 - assert not run1.is_default - - -@all_platforms -def test_create_run_increment_version(test_mp): - test_mp.backend.runs.create("Model", "Scenario") - run2 = test_mp.backend.runs.create("Model", "Scenario") - assert run2.model.name == "Model" - assert run2.scenario.name == "Scenario" - assert run2.version == 2 - assert not run2.is_default - - -@all_platforms -def test_get_run_versions(test_mp): - run1a = test_mp.backend.runs.create("Model", "Scenario") - run2a = test_mp.backend.runs.create("Model", "Scenario") - test_mp.backend.runs.set_as_default_version(run2a.id) - run3a = test_mp.backend.runs.create("Model", "Scenario") - - run1b = test_mp.backend.runs.get("Model", "Scenario", 1) - assert run1a.id == run1b.id - - run2b = test_mp.backend.runs.get("Model", "Scenario", 2) - assert run2a.id == run2b.id - run2c = test_mp.backend.runs.get_default_version("Model", "Scenario") - assert run2a.id == run2c.id - - run3b = test_mp.backend.runs.get("Model", "Scenario", 3) - assert run3a.id == run3b.id - - -@all_platforms -def test_get_run_no_default_version(test_mp): - with pytest.raises(NoDefaultRunVersion): - test_mp.backend.runs.get_default_version("Model", "Scenario") - - -@all_platforms -def test_get_or_create_run(test_mp): - run1 = test_mp.backend.runs.create("Model", "Scenario") - run2 = test_mp.backend.runs.get_or_create("Model", "Scenario") - assert run1.id != run2.id - assert run2.version == 2 - - test_mp.backend.runs.set_as_default_version(run1.id) - - run3 = test_mp.backend.runs.get_or_create("Model", "Scenario") - assert run1.id == run3.id - - -@all_platforms -def test_list_run(test_mp): - run1 = test_mp.backend.runs.create("Model", "Scenario") - test_mp.backend.runs.create("Model", "Scenario") - - runs = test_mp.backend.runs.list(default_only=False) - assert runs[0].id == 1 - assert runs[0].version == 1 - assert runs[0].model.name == "Model" - assert runs[0].scenario.name == "Scenario" - assert runs[1].id == 2 - assert runs[1].version == 2 - - test_mp.backend.runs.set_as_default_version(run1.id) - [run] = test_mp.backend.runs.list(default_only=True) - - assert run1.id == run.id +from ..utils import all_platforms, assert_unordered_equality @all_platforms -def test_tabulate_run(test_mp): - run = test_mp.backend.runs.create("Model", "Scenario") - test_mp.backend.runs.set_as_default_version(run.id) - test_mp.backend.runs.create("Model", "Scenario") - - true_runs = pd.DataFrame( - [ - [1, True, 1, 1, 1], - [2, False, 1, 1, 2], - ], - columns=["id", "is_default", "model__id", "scenario__id", "version"], - ) - - runs = test_mp.backend.runs.tabulate(default_only=False) - assert_unordered_equality(runs, true_runs) +class TestDataRun: + def test_create_run(self, test_mp): + run1 = test_mp.backend.runs.create("Model", "Scenario") + assert run1.model.name == "Model" + assert run1.scenario.name == "Scenario" + assert run1.version == 1 + assert not run1.is_default + + def test_create_run_increment_version(self, test_mp): + test_mp.backend.runs.create("Model", "Scenario") + run2 = test_mp.backend.runs.create("Model", "Scenario") + assert run2.model.name == "Model" + assert run2.scenario.name == "Scenario" + assert run2.version == 2 + assert not run2.is_default + + def test_get_run_versions(self, test_mp): + run1a = test_mp.backend.runs.create("Model", "Scenario") + run2a = test_mp.backend.runs.create("Model", "Scenario") + test_mp.backend.runs.set_as_default_version(run2a.id) + run3a = test_mp.backend.runs.create("Model", "Scenario") + + run1b = test_mp.backend.runs.get("Model", "Scenario", 1) + assert run1a.id == run1b.id + + run2b = test_mp.backend.runs.get("Model", "Scenario", 2) + assert run2a.id == run2b.id + run2c = test_mp.backend.runs.get_default_version("Model", "Scenario") + assert run2a.id == run2c.id + + run3b = test_mp.backend.runs.get("Model", "Scenario", 3) + assert run3a.id == run3b.id + + def test_get_run_no_default_version(self, test_mp): + with pytest.raises(NoDefaultRunVersion): + test_mp.backend.runs.get_default_version("Model", "Scenario") + + def test_get_or_create_run(self, test_mp): + run1 = test_mp.backend.runs.create("Model", "Scenario") + run2 = test_mp.backend.runs.get_or_create("Model", "Scenario") + assert run1.id != run2.id + assert run2.version == 2 + + test_mp.backend.runs.set_as_default_version(run1.id) + + run3 = test_mp.backend.runs.get_or_create("Model", "Scenario") + assert run1.id == run3.id + + def test_list_run(self, test_mp): + run1 = test_mp.backend.runs.create("Model", "Scenario") + test_mp.backend.runs.create("Model", "Scenario") + + runs = test_mp.backend.runs.list(default_only=False) + assert runs[0].id == 1 + assert runs[0].version == 1 + assert runs[0].model.name == "Model" + assert runs[0].scenario.name == "Scenario" + assert runs[1].id == 2 + assert runs[1].version == 2 + + test_mp.backend.runs.set_as_default_version(run1.id) + [run] = test_mp.backend.runs.list(default_only=True) + + assert run1.id == run.id + + def test_tabulate_run(self, test_mp): + run = test_mp.backend.runs.create("Model", "Scenario") + test_mp.backend.runs.set_as_default_version(run.id) + test_mp.backend.runs.create("Model", "Scenario") + + true_runs = pd.DataFrame( + [ + [1, True, 1, 1, 1], + [2, False, 1, 1, 2], + ], + columns=[ + "id", + "is_default", + "model__id", + "scenario__id", + "version", + ], + ) + + runs = test_mp.backend.runs.tabulate(default_only=False) + assert_unordered_equality(runs, true_runs) diff --git a/tests/data/test_scenario.py b/tests/data/test_scenario.py index bc2b1f0e..d6359d33 100644 --- a/tests/data/test_scenario.py +++ b/tests/data/test_scenario.py @@ -3,104 +3,93 @@ from ixmp4 import Scenario -from ..utils import assert_unordered_equality, all_platforms, create_filter_test_data +from ..utils import all_platforms, assert_unordered_equality, create_filter_test_data @all_platforms -def test_create_scenario(test_mp): - scenario = test_mp.backend.scenarios.create("Scenario") - assert scenario.name == "Scenario" - assert scenario.created_at is not None - assert scenario.created_by == "@unknown" - - -@all_platforms -def test_scenario_unique(test_mp): - test_mp.backend.scenarios.create("Scenario") - - with pytest.raises(Scenario.NotUnique): - test_mp.scenarios.create("Scenario") - - -@all_platforms -def test_get_scenario(test_mp): - scenario1 = test_mp.backend.scenarios.create("Scenario") - scenario2 = test_mp.backend.scenarios.get("Scenario") - assert scenario1 == scenario2 - - -@all_platforms -def test_scenario_not_found(test_mp): - with pytest.raises(Scenario.NotFound): - test_mp.scenarios.get("Scenario") - - -@all_platforms -def test_list_scenario(test_mp): - test_mp.Run("Model", "Scenario 1", version="new") - test_mp.Run("Model", "Scenario 2", version="new") - - scenarios = sorted(test_mp.backend.scenarios.list(), key=lambda x: x.id) - - assert scenarios[0].id == 1 - assert scenarios[0].name == "Scenario 1" - assert scenarios[1].id == 2 - assert scenarios[1].name == "Scenario 2" - - -@all_platforms -def test_tabulate_scenario(test_mp): - test_mp.Run("Model", "Scenario 1", version="new") - test_mp.Run("Model", "Scenario 2", version="new") - - true_scenarios = pd.DataFrame( - [ - [1, "Scenario 1"], - [2, "Scenario 2"], - ], - columns=["id", "name"], - ) - - scenarios = test_mp.backend.scenarios.tabulate() - assert_unordered_equality( - scenarios.drop(columns=["created_at", "created_by"]), true_scenarios - ) - - -@all_platforms -def test_filter_scenario(test_mp): - run1, _ = create_filter_test_data(test_mp) - - res = test_mp.backend.scenarios.tabulate( - iamc={ - "region": {"name": "Region 1"}, - "run": {"default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Scenario 1"] - - res = test_mp.backend.scenarios.tabulate( - iamc={ - "region": {"name": "Region 3"}, - "run": {"default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Scenario 1", "Scenario 2"] - - run1.set_as_default() - res = test_mp.backend.scenarios.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "unit": {"name__in": ["Unit 3", "Unit 4"]}, - "run": {"default_only": True}, - } - ) - assert res["name"].tolist() == ["Scenario 2"] - - res = test_mp.backend.scenarios.tabulate( - iamc={ - "run": {"default_only": False, "model": {"name": "Model 2"}}, - } - ) - - assert sorted(res["name"].tolist()) == ["Scenario 2"] +class TestDataScenario: + def test_create_scenario(self, test_mp): + scenario = test_mp.backend.scenarios.create("Scenario") + assert scenario.name == "Scenario" + assert scenario.created_at is not None + assert scenario.created_by == "@unknown" + + def test_scenario_unique(self, test_mp): + test_mp.backend.scenarios.create("Scenario") + + with pytest.raises(Scenario.NotUnique): + test_mp.scenarios.create("Scenario") + + def test_get_scenario(self, test_mp): + scenario1 = test_mp.backend.scenarios.create("Scenario") + scenario2 = test_mp.backend.scenarios.get("Scenario") + assert scenario1 == scenario2 + + def test_scenario_not_found(self, test_mp): + with pytest.raises(Scenario.NotFound): + test_mp.scenarios.get("Scenario") + + def test_list_scenario(self, test_mp): + test_mp.Run("Model", "Scenario 1", version="new") + test_mp.Run("Model", "Scenario 2", version="new") + + scenarios = sorted(test_mp.backend.scenarios.list(), key=lambda x: x.id) + + assert scenarios[0].id == 1 + assert scenarios[0].name == "Scenario 1" + assert scenarios[1].id == 2 + assert scenarios[1].name == "Scenario 2" + + def test_tabulate_scenario(self, test_mp): + test_mp.Run("Model", "Scenario 1", version="new") + test_mp.Run("Model", "Scenario 2", version="new") + + true_scenarios = pd.DataFrame( + [ + [1, "Scenario 1"], + [2, "Scenario 2"], + ], + columns=["id", "name"], + ) + + scenarios = test_mp.backend.scenarios.tabulate() + assert_unordered_equality( + scenarios.drop(columns=["created_at", "created_by"]), true_scenarios + ) + + def test_filter_scenario(self, test_mp): + run1, _ = create_filter_test_data(test_mp) + + res = test_mp.backend.scenarios.tabulate( + iamc={ + "region": {"name": "Region 1"}, + "run": {"default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Scenario 1"] + + res = test_mp.backend.scenarios.tabulate( + iamc={ + "region": {"name": "Region 3"}, + "run": {"default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Scenario 1", "Scenario 2"] + + run1.set_as_default() + res = test_mp.backend.scenarios.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "unit": {"name__in": ["Unit 3", "Unit 4"]}, + "run": {"default_only": True}, + } + ) + assert res["name"].tolist() == ["Scenario 2"] + + res = test_mp.backend.scenarios.tabulate( + iamc={ + "run": {"default_only": False, "model": {"name": "Model 2"}}, + } + ) + + assert sorted(res["name"].tolist()) == ["Scenario 2"] diff --git a/tests/data/test_unit.py b/tests/data/test_unit.py index 5e93ed53..1c148322 100644 --- a/tests/data/test_unit.py +++ b/tests/data/test_unit.py @@ -1,134 +1,121 @@ -import pytest import pandas as pd +import pytest from ixmp4 import Unit -from ..utils import assert_unordered_equality, all_platforms, create_filter_test_data - - -@all_platforms -def test_create_get_unit(test_mp): - unit1 = test_mp.backend.units.create("Unit") - assert unit1.name == "Unit" - - unit2 = test_mp.backend.units.get("Unit") - assert unit1.id == unit2.id +from ..utils import all_platforms, assert_unordered_equality, create_filter_test_data @all_platforms -def test_delete_unit(test_mp): - unit1 = test_mp.backend.units.create("Unit") - test_mp.backend.units.delete(unit1.id) - assert test_mp.backend.units.tabulate().empty +class TestDataUnit: + def test_create_get_unit(self, test_mp): + unit1 = test_mp.backend.units.create("Unit") + assert unit1.name == "Unit" + unit2 = test_mp.backend.units.get("Unit") + assert unit1.id == unit2.id -@all_platforms -def test_get_or_create_unit(test_mp): - unit1 = test_mp.backend.units.create("Unit") - unit2 = test_mp.backend.units.get_or_create("Unit") - assert unit1.id == unit2.id - - unit3 = test_mp.backend.units.get_or_create("Another Unit") - assert unit3.name == "Another Unit" - assert unit1.id != unit3.id + def test_delete_unit(self, test_mp): + unit1 = test_mp.backend.units.create("Unit") + test_mp.backend.units.delete(unit1.id) + assert test_mp.backend.units.tabulate().empty + def test_get_or_create_unit(self, test_mp): + unit1 = test_mp.backend.units.create("Unit") + unit2 = test_mp.backend.units.get_or_create("Unit") + assert unit1.id == unit2.id -@all_platforms -def test_unit_unique(test_mp): - test_mp.backend.units.create("Unit") + unit3 = test_mp.backend.units.get_or_create("Another Unit") + assert unit3.name == "Another Unit" + assert unit1.id != unit3.id - with pytest.raises(Unit.NotUnique): + def test_unit_unique(self, test_mp): test_mp.backend.units.create("Unit") - -@all_platforms -def test_unit_not_found(test_mp): - with pytest.raises(Unit.NotFound): - test_mp.backend.units.get("Unit") - - -@all_platforms -def test_list_unit(test_mp): - test_mp.backend.units.create("Unit 1") - test_mp.backend.units.create("Unit 2") - - units = test_mp.backend.units.list() - units = sorted(units, key=lambda x: x.id) - - assert units[0].id == 1 - assert units[0].name == "Unit 1" - assert units[1].id == 2 - assert units[1].name == "Unit 2" - - -@all_platforms -def test_tabulate_unit(test_mp): - test_mp.backend.units.create("Unit 1") - test_mp.backend.units.create("Unit 2") - - true_units = pd.DataFrame( - [ - [1, "Unit 1"], - [2, "Unit 2"], - ], - columns=["id", "name"], - ) - - units = test_mp.backend.units.tabulate() - assert_unordered_equality( - units.drop(columns=["created_at", "created_by"]), true_units - ) - - -@all_platforms -def test_filter_unit(test_mp): - run1, run2 = create_filter_test_data(test_mp) - res = test_mp.backend.units.tabulate( - iamc={ - "run": {"model": {"name": "Model 1"}}, - "variable": {"name": "Variable 1"}, - } - ) - assert sorted(res["name"].tolist()) == ["Unit 1", "Unit 2"] - - run2.set_as_default() - res = test_mp.backend.units.tabulate( - iamc={ - "run": {"model": {"name": "Model 1"}}, - "variable": {"name": "Variable 1"}, - } - ) - assert sorted(res["name"].tolist()) == ["Unit 3", "Unit 4"] - - run1.set_as_default() - res = test_mp.backend.units.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "region": {"name__in": ["Region 5", "Region 6"]}, - "run": {"model": {"name": "Model 1"}, "default_only": True}, - } - ) - assert res["name"].tolist() == [] - - res = test_mp.backend.units.tabulate( - iamc={ - "variable": {"name": "Variable 1"}, - "region": {"name__in": ["Region 5", "Region 6"]}, - "run": {"model": {"name": "Model 1"}, "default_only": False}, - } - ) - assert sorted(res["name"].tolist()) == ["Unit 4"] - - res = test_mp.backend.units.tabulate(iamc=False) - - assert res["name"].tolist() == ["Unit 5"] - - res = test_mp.backend.units.tabulate() - - assert sorted(res["name"].tolist()) == [ - "Unit 1", - "Unit 2", - "Unit 3", - "Unit 4", - "Unit 5", - ] + with pytest.raises(Unit.NotUnique): + test_mp.backend.units.create("Unit") + + def test_unit_not_found(self, test_mp): + with pytest.raises(Unit.NotFound): + test_mp.backend.units.get("Unit") + + def test_list_unit(self, test_mp): + test_mp.backend.units.create("Unit 1") + test_mp.backend.units.create("Unit 2") + + units = test_mp.backend.units.list() + units = sorted(units, key=lambda x: x.id) + + assert units[0].id == 1 + assert units[0].name == "Unit 1" + assert units[1].id == 2 + assert units[1].name == "Unit 2" + + def test_tabulate_unit(self, test_mp): + test_mp.backend.units.create("Unit 1") + test_mp.backend.units.create("Unit 2") + + true_units = pd.DataFrame( + [ + [1, "Unit 1"], + [2, "Unit 2"], + ], + columns=["id", "name"], + ) + + units = test_mp.backend.units.tabulate() + assert_unordered_equality( + units.drop(columns=["created_at", "created_by"]), true_units + ) + + def test_filter_unit(self, test_mp): + run1, run2 = create_filter_test_data(test_mp) + res = test_mp.backend.units.tabulate( + iamc={ + "run": {"model": {"name": "Model 1"}}, + "variable": {"name": "Variable 1"}, + } + ) + assert sorted(res["name"].tolist()) == ["Unit 1", "Unit 2"] + + run2.set_as_default() + res = test_mp.backend.units.tabulate( + iamc={ + "run": {"model": {"name": "Model 1"}}, + "variable": {"name": "Variable 1"}, + } + ) + assert sorted(res["name"].tolist()) == ["Unit 3", "Unit 4"] + + run1.set_as_default() + res = test_mp.backend.units.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "region": {"name__in": ["Region 5", "Region 6"]}, + "run": {"model": {"name": "Model 1"}, "default_only": True}, + } + ) + assert res["name"].tolist() == [] + + res = test_mp.backend.units.tabulate( + iamc={ + "variable": {"name": "Variable 1"}, + "region": {"name__in": ["Region 5", "Region 6"]}, + "run": {"model": {"name": "Model 1"}, "default_only": False}, + } + ) + assert sorted(res["name"].tolist()) == ["Unit 4"] + + res = test_mp.backend.units.tabulate(iamc=False) + + assert res["name"].tolist() == ["Unit 5"] + + res = test_mp.backend.units.tabulate() + + assert sorted(res["name"].tolist()) == [ + "Unit 1", + "Unit 2", + "Unit 3", + "Unit 4", + "Unit 5", + ] diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index e62153ba..9d89b1f2 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,15 +1,6 @@ version: '3.1' services: - oracle: - image: gvenzl/oracle-xe:latest - environment: - ORACLE_RANDOM_PASSWORD: 'true' - APP_USER: ixmp4_test - APP_USER_PASSWORD: ixmp4_test - ports: - - 1521:1521 - postgres: image: postgres environment: diff --git a/tests/test_benchmarks.py b/tests/test_benchmarks.py index a3ff0c23..d918d8cf 100644 --- a/tests/test_benchmarks.py +++ b/tests/test_benchmarks.py @@ -1,13 +1,11 @@ """This module only contains benchmarks, no assertions are made to validate the results.""" -import pytest import pandas as pd +import pytest from ixmp4 import NotFound - -from .utils import add_regions, add_units, all_platforms from .conftest import TEST_DATA_BIG - +from .utils import add_regions, add_units, all_platforms # skip tests if performance test file not found if TEST_DATA_BIG is None: @@ -55,95 +53,94 @@ def tabulate_datapoints(test_mp, **kwargs): @all_platforms -def test_add_datapoints_full_benchmark(test_mp, profiled, benchmark, test_data_big): - """Benchmarks a full insert of `test_data_big`.""" - - def setup(): - add_regions(test_mp, test_data_big["region"].unique()) - add_units(test_mp, test_data_big["unit"].unique()) - return (test_mp,), {} - - def run(mp): - with profiled(): - add_datapoints(mp, test_data_big) - - benchmark.pedantic(run, setup=setup) - - -@all_platforms -def test_add_datapoints_half_unchanged_benchmark( - test_mp, profiled, benchmark, test_data_big -): - """Benchmarks a full insert of `test_data_big` on a half-filled database.""" - - def setup(): - add_regions(test_mp, test_data_big["region"].unique()) - add_units(test_mp, test_data_big["unit"].unique()) - add_datapoints(test_mp, test_data_big.head(len(test_data_big) // 2)) - - return (test_mp,), {} - - def run(mp): - with profiled(): - add_datapoints(mp, test_data_big) - - benchmark.pedantic(run, setup=setup) - - -@all_platforms -def test_add_datapoints_half_insert_half_update_benchmark( - test_mp, profiled, benchmark, test_data_big -): - """Benchmarks a full insert of `test_data_big` with changed values on a half-filled database.""" - - def setup(): - add_regions(test_mp, test_data_big["region"].unique()) - add_units(test_mp, test_data_big["unit"].unique()) - add_datapoints(test_mp, test_data_big.head(len(test_data_big) // 2)) - data = test_data_big.copy() - data["value"] = -9999 - return (test_mp, data), {} - - def run(mp, data): - with profiled(): - add_datapoints(mp, data) - - ret = tabulate_datapoints(mp).drop(columns=["id"]) - assert ret["value"].unique() == [-9999] - - benchmark.pedantic(run, setup=setup) - - -@all_platforms -def test_remove_datapoints_benchmark(test_mp, profiled, benchmark, test_data_big): - """Benchmarks a full removal of `test_data_big` from a filled database.""" - - def setup(): - add_regions(test_mp, test_data_big["region"].unique()) - add_units(test_mp, test_data_big["unit"].unique()) - add_datapoints(test_mp, test_data_big) - data = test_data_big.drop(columns=["value"]) - return (test_mp, data), {} - - def run(mp, data): - with profiled(): - remove_datapoints(mp, data) - - benchmark.pedantic(run, setup=setup) - - -@all_platforms -def test_tabulate_datapoints_benchmark(test_mp, profiled, benchmark, test_data_big): - """Benchmarks a full retrieval of `test_data_big` from a filled database.""" - - def setup(): - add_regions(test_mp, test_data_big["region"].unique()) - add_units(test_mp, test_data_big["unit"].unique()) - add_datapoints(test_mp, test_data_big) - return (test_mp,), {} - - def run(mp): - with profiled(): - tabulate_datapoints(mp) - - benchmark.pedantic(run, setup=setup) +class TestBenchmarks: + def test_add_datapoints_full_benchmark( + self, test_mp, profiled, benchmark, test_data_big + ): + """Benchmarks a full insert of `test_data_big`.""" + + def setup(): + add_regions(test_mp, test_data_big["region"].unique()) + add_units(test_mp, test_data_big["unit"].unique()) + return (test_mp,), {} + + def run(mp): + with profiled(): + add_datapoints(mp, test_data_big) + + benchmark.pedantic(run, setup=setup) + + def test_add_datapoints_half_unchanged_benchmark( + self, test_mp, profiled, benchmark, test_data_big + ): + """Benchmarks a full insert of `test_data_big` on a half-filled database.""" + + def setup(): + add_regions(test_mp, test_data_big["region"].unique()) + add_units(test_mp, test_data_big["unit"].unique()) + add_datapoints(test_mp, test_data_big.head(len(test_data_big) // 2)) + + return (test_mp,), {} + + def run(mp): + with profiled(): + add_datapoints(mp, test_data_big) + + benchmark.pedantic(run, setup=setup) + + def test_add_datapoints_half_insert_half_update_benchmark( + self, test_mp, profiled, benchmark, test_data_big + ): + """Benchmarks a full insert of `test_data_big` with changed values on a half-filled database.""" + + def setup(): + add_regions(test_mp, test_data_big["region"].unique()) + add_units(test_mp, test_data_big["unit"].unique()) + add_datapoints(test_mp, test_data_big.head(len(test_data_big) // 2)) + data = test_data_big.copy() + data["value"] = -9999 + return (test_mp, data), {} + + def run(mp, data): + with profiled(): + add_datapoints(mp, data) + + ret = tabulate_datapoints(mp).drop(columns=["id"]) + assert ret["value"].unique() == [-9999] + + benchmark.pedantic(run, setup=setup) + + def test_remove_datapoints_benchmark( + self, test_mp, profiled, benchmark, test_data_big + ): + """Benchmarks a full removal of `test_data_big` from a filled database.""" + + def setup(): + add_regions(test_mp, test_data_big["region"].unique()) + add_units(test_mp, test_data_big["unit"].unique()) + add_datapoints(test_mp, test_data_big) + data = test_data_big.drop(columns=["value"]) + return (test_mp, data), {} + + def run(mp, data): + with profiled(): + remove_datapoints(mp, data) + + benchmark.pedantic(run, setup=setup) + + def test_tabulate_datapoints_benchmark( + self, test_mp, profiled, benchmark, test_data_big + ): + """Benchmarks a full retrieval of `test_data_big` from a filled database.""" + + def setup(): + add_regions(test_mp, test_data_big["region"].unique()) + add_units(test_mp, test_data_big["unit"].unique()) + add_datapoints(test_mp, test_data_big) + return (test_mp,), {} + + def run(mp): + with profiled(): + tabulate_datapoints(mp) + + benchmark.pedantic(run, setup=setup) diff --git a/tests/utils.py b/tests/utils.py index 175f30e7..e3b11776 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,6 @@ -import pytest - import pandas as pd import pandas.testing as pdt +import pytest from ixmp4 import DataPoint @@ -29,7 +28,6 @@ def assert_unordered_equality(df1, df2, **kwargs): [ pytest.lazy_fixture("test_sqlite_mp"), pytest.lazy_fixture("test_pgsql_mp"), - pytest.lazy_fixture("test_oracle_mp"), pytest.lazy_fixture("test_api_sqlite_mp"), pytest.lazy_fixture("test_api_pgsql_mp"), ], @@ -48,7 +46,6 @@ def assert_unordered_equality(df1, df2, **kwargs): [ pytest.lazy_fixture("test_sqlite_mp"), pytest.lazy_fixture("test_pgsql_mp"), - pytest.lazy_fixture("test_oracle_mp"), ], ) diff --git a/tutorial/transport/_static/python.png b/tutorial/transport/_static/python.png new file mode 100644 index 00000000..738f6ed4 Binary files /dev/null and b/tutorial/transport/_static/python.png differ diff --git a/tutorial/transport/py_transport.ipynb b/tutorial/transport/py_transport.ipynb new file mode 100644 index 00000000..d96ad864 --- /dev/null +++ b/tutorial/transport/py_transport.ipynb @@ -0,0 +1,469 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial 1

Solve Dantzig's Transport Problem using the *ix modeling platform* (ixmp4)\n", + "\n", + "\n", + "\n", + "## Aim and scope of the tutorial\n", + "\n", + "This tutorial takes you through the steps to import the data for a very simple optimization model\n", + "and solve it using the **ixmp4**-GAMS interface.\n", + "\n", + "We use Dantzig's transport problem, which is also used as the standard GAMS tutorial.\n", + "This problem finds a least cost shipping schedule that meets requirements at markets and supplies at factories.\n", + "\n", + "If you are not familiar with GAMS, please take a minute to look at the [transport.gms](transport.gms) code.\n", + "\n", + "For reference of the transport problem, see:\n", + "> Dantzig, G B, Chapter 3.3. In Linear Programming and Extensions. \n", + "> Princeton University Press, Princeton, New Jersey, 1963.\n", + "\n", + "> This formulation is described in detail in: \n", + "> Rosenthal, R E, Chapter 2: A GAMS Tutorial. \n", + "> In GAMS: A User's Guide. The Scientific Press, Redwood City, California, 1988.\n", + "\n", + "> see http://www.gams.com/mccarl/trnsport.gms\n", + "\n", + "## Tutorial outline\n", + "\n", + "The steps in the tutorial are the following:\n", + "\n", + "0. Launch an **ixmp4.Platform** instance and initialize a new **ixmp4.Run**\n", + "0. Define the **sets and parameters** in the scenario and save the data to the platform\n", + "0. Initialize **variables and equations** to import the solution from GAMS\n", + "0. Call GAMS to **solve the scenario** (export to GAMS input gdx, execute, read solution from output gdx)\n", + "0. Display the **solution** (variables and equation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Launching the *Platform* and initializing a new *Run*\n", + "\n", + "A **Platform** is the connection to the database that holds all data and relevant additional information.\n", + "\n", + "A **Run** is an object that holds all relevant information for one quantification of a scenario. \n", + "A run is identified by a model name, a scenario name and a version number (assigned automatically)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import ixmp4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have to *register a new local database* before you can run the tutorial. \n", + "\n", + "Run the following in the command-line:\n", + "```\n", + "ixmp4 platforms add sqlite-test\n", + "```\n", + "\n", + "You can then check if the database was successfully created by running\n", + "```\n", + "ixmp4 platforms list\n", + "```\n", + "\n", + "After creating the database, you can connect to it via an **ixmp4.Platform** instance." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "mp = ixmp4.Platform(\"sqlite-test\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we initialize a new **ixmp4.Run** in the database. This is done by using the argument *version=\"new\"*." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "run = mp.Run(model=\"transport problem\", scenario=\"standard\", version=\"new\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Defining the *IndexSets*\n", + "\n", + "An **IndexSet** defines a named list of elements. These IndexSets can be used for \"indexed assignment\" of parameters, variables and equations. \n", + "In database-lingo, a column of a parameter can be \"foreign-keyed\" onto an IndexSet.\n", + "\n", + "Below, we first show the data as they would be written in the GAMS tutorial ([transport.gms](transport.gms) in this folder). " + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "Sets\n", + " i canning plants / seattle, san-diego /\n", + " j markets / new-york, chicago, topeka / ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now initialize these sets and assign the elements." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "i = run.optimization.IndexSet(\"i\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "i.add([\"seattle\", \"san-diego\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can display the elements of **IndexSet i** as a Python list." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['seattle', 'san-diego']" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "i.elements" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For simplicity, the steps of creating an **IndexSet** and assigning elements can be done in one line." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "run.optimization.IndexSet(\"j\").add([\"new-york\", \"chicago\", \"topeka\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assigning the *Parameters*\n", + "\n", + "Next, we define the parameters *capacity* and *demand*. The parameters are assigned on the IndexSets *i* and *j*, respectively." + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "Parameters\n", + " a(i) capacity of plant i in cases\n", + " / seattle 350\n", + " san-diego 600 /\n", + " b(j) demand at market j in cases\n", + " / new-york 325\n", + " chicago 300\n", + " topeka 275 / ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# capacity of plant i in cases \n", + "# add parameter elements one-by-one (string and value) \n", + "scen.init_par(\"a\", idx_sets=\"i\")\n", + "scen.add_par(\"a\", \"seattle\", 350, \"cases\")\n", + "scen.add_par(\"a\", \"san-diego\", 600, \"cases\")\n", + "\n", + "# demand at market j in cases \n", + "# add parameter elements as dataframe (with index names) \n", + "scen.init_par(\"b\", idx_sets=\"j\")\n", + "b_data = [\n", + " {'j': \"new-york\", 'value': 325, 'unit': \"cases\"},\n", + " {'j': \"chicago\", 'value': 300, 'unit': \"cases\"},\n", + " {'j': \"topeka\", 'value': 275, 'unit': \"cases\"}\n", + "]\n", + "b = pd.DataFrame(b_data)\n", + "scen.add_par(\"b\", b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scen.par('b')" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "Table d(i,j) distance in thousands of miles\n", + " new-york chicago topeka\n", + " seattle 2.5 1.7 1.8\n", + " san-diego 2.5 1.8 1.4 ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# distance in thousands of miles \n", + "scen.init_par(\"d\", idx_sets=[\"i\", \"j\"])\n", + "# add more parameter elements as dataframe by index names \n", + "d_data = [\n", + " {'i': \"seattle\", 'j': \"new-york\", 'value': 2.5, 'unit': \"km\"},\n", + " {'i': \"seattle\", 'j': \"chicago\", 'value': 1.7, 'unit': \"km\"},\n", + " {'i': \"seattle\", 'j': \"topeka\", 'value': 1.8, 'unit': \"km\"},\n", + " {'i': \"san-diego\", 'j': \"new-york\", 'value': 2.5, 'unit': \"km\"},\n", + "]\n", + "d = pd.DataFrame(d_data)\n", + "scen.add_par(\"d\", d)\n", + "\n", + "# add other parameter elements as key list, value, unit\n", + "scen.add_par(\"d\", [\"san-diego\", \"chicago\"], 1.8, \"km\")\n", + "scen.add_par(\"d\", [\"san-diego\", \"topeka\"], 1.4, \"km\")" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "Scalar f freight in dollars per case per thousand miles /90/ ; " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# cost per case per 1000 miles \n", + "# initialize scalar with a value and a unit (and optionally a comment) \n", + "scen.init_scalar(\"f\", 90.0, \"USD/km\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Committing the scenario to the ixmp database instance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# commit new scenario to the database\n", + "# no changes can then be made to the scenario data until a check-out is performed\n", + "comment = \"importing Dantzig's transport problem for illustration\"\n", + "comment += \" and testing of the Python interface using a generic datastructure\" \n", + "scen.commit(comment) \n", + "\n", + "# set this new scenario as the default version for the model/scenario name\n", + "scen.set_as_default()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Defining variables and equations in the scenario\n", + "\n", + "The levels and marginals of these variables and equations will be imported to the scenario when reading the gdx solution file." + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "Variables\n", + " x(i,j) shipment quantities in cases\n", + " z total transportation costs in thousands of dollars ;\n", + " \n", + "Equations\n", + " cost define objective function\n", + " supply(i) observe supply limit at plant i\n", + " demand(j) satisfy demand at market j ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# perform a check_out to make further changes\n", + "scen.check_out()\n", + "\n", + "# initialize the decision variables and equations\n", + "scen.init_var(\"z\", None, None)\n", + "scen.init_var(\"x\", idx_sets=[\"i\", \"j\"])\n", + "scen.init_equ(\"demand\", idx_sets=[\"j\"])\n", + "\n", + "# commit changes to the scenario (save changes in ixmp database instance)\n", + "change_comment = \"initialize the model variables and equations\"\n", + "scen.commit(change_comment)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solve the scenario\n", + "\n", + "The ``solve()`` function exports the scenario to a GAMS gdx file, executes GAMS, and then imports the solution from an output GAMS gdx file to the database.\n", + "\n", + "For the model equations and the GAMS workflow (reading the data from gdx, solving the model, writing the results to gdx), see ``transport_ixmp.gms``." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scen.solve(model='dantzig')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Display and analyze the results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# display the objective value of the solution\n", + "scen.var(\"z\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# display the quantities transported from canning plants to demand locations\n", + "scen.var(\"x\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# display the quantities and marginals (=shadow prices) of the demand balance constraints\n", + "scen.equ(\"demand\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Close the database connection of the ix modeling platform\n", + "\n", + "Closing the database connection is recommended when working with the local file-based database, i.e., ``dbtype='HSQLDB'``.\n", + "This command closes the database files and removes temporary data. This is necessary so that other notebooks or ``ixmp`` instances can access the database file, or so that the database files can be copied to a different folder or drive." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# close the connection of the platform instance to the local ixmp database files\n", + "mp.close_db()" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/tutorial/transport/transport.gms b/tutorial/transport/transport.gms new file mode 100644 index 00000000..350039b1 --- /dev/null +++ b/tutorial/transport/transport.gms @@ -0,0 +1,62 @@ +*Basic example of transport model from GAMS model library + +$Title A Transportation Problem (TRNSPORT,SEQ=1) +$Ontext + +This problem finds a least cost shipping schedule that meets +requirements at markets and supplies at factories. + +Dantzig, G B, Chapter 3.3. In Linear Programming and Extensions. +Princeton University Press, Princeton, New Jersey, 1963. + +This formulation is described in detail in: +Rosenthal, R E, Chapter 2: A GAMS Tutorial. In GAMS: A User's Guide. +The Scientific Press, Redwood City, California, 1988. + +The line numbers will not match those in the book because of these +comments. + +$Offtext + +Sets + i canning plants / seattle, san-diego / + j markets / new-york, chicago, topeka / ; +Parameters + a(i) capacity of plant i in cases + / seattle 350 + san-diego 600 / + b(j) demand at market j in cases + / new-york 325 + chicago 300 + topeka 275 / ; +Table d(i,j) distance in thousands of miles + new-york chicago topeka + seattle 2.5 1.7 1.8 + san-diego 2.5 1.8 1.4 ; +Scalar f freight in dollars per case per thousand miles /90/ ; +Parameter c(i,j) transport cost in thousands of dollars per case ; + c(i,j) = f * d(i,j) / 1000 ; +Variables + x(i,j) shipment quantities in cases + z total transportation costs in thousands of dollars ; + +Positive Variable x ; + +Equations + cost define objective function + supply(i) observe supply limit at plant i + demand(j) satisfy demand at market j ; + +cost .. z =e= sum((i,j), c(i,j)*x(i,j)) ; + +supply(i) .. sum(j, x(i,j)) =l= a(i) ; + +demand(j) .. sum(i, x(i,j)) =g= b(j) ; + +Model transport /all/ ; + +Solve transport using lp minimizing z ; + +Display x.l, x.m ; + +Execute_unload 'transport_results.gdx';