From 3157d28474b4b137ab61e546e6a28b4d729bf08f Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Mon, 4 Dec 2023 15:45:33 +0200 Subject: [PATCH 01/22] added support for uints --- deker/ABC/base_adapters.py | 2 +- deker/ABC/base_schemas.py | 10 +++- deker/tools/array.py | 2 +- deker/tools/schema.py | 2 +- deker/types/private/enums.py | 11 ++++ deker/types/private/typings.py | 58 +++++++++++++------ deker/uri.py | 53 +++++++++++------ .../test_collection_methods.py | 8 ++- tests/test_cases/test_locking/mpt.py | 1 - .../test_cases/test_managers/test_managers.py | 2 +- tests/test_cases/test_tools/test_tools.py | 2 +- 11 files changed, 104 insertions(+), 47 deletions(-) diff --git a/deker/ABC/base_adapters.py b/deker/ABC/base_adapters.py index 96a814b..c6146db 100644 --- a/deker/ABC/base_adapters.py +++ b/deker/ABC/base_adapters.py @@ -230,7 +230,7 @@ def create_collection_from_meta( schema_class = SchemaTypeEnum[collection_data.get("type")].value try: - dtype = DTypeEnum[data["dtype"].lstrip("numpy.")].value + dtype = DTypeEnum[data["dtype"].split("numpy.")[-1]].value fill_value = ( dtype(data["fill_value"]) if data["fill_value"] is not None else data["fill_value"] ) diff --git a/deker/ABC/base_schemas.py b/deker/ABC/base_schemas.py index b181f70..9f04704 100644 --- a/deker/ABC/base_schemas.py +++ b/deker/ABC/base_schemas.py @@ -90,7 +90,7 @@ class BaseArraysSchema: dtype: Type[Numeric] fill_value: Union[Numeric, type(np.nan), None] # type: ignore[valid-type] dimensions: Union[List[BaseDimensionSchema], Tuple[BaseDimensionSchema, ...]] - attributes: Union[List[BaseAttributeSchema], Tuple[BaseAttributeSchema, ...]] + attributes: Union[List[BaseAttributeSchema], Tuple[BaseAttributeSchema, ...], None] @property def primary_attributes(self) -> Optional[Tuple[BaseAttributeSchema, ...]]: @@ -163,6 +163,10 @@ def named_shape(self) -> Tuple[Tuple[str, int], ...]: @property def as_dict(self) -> dict: """Serialize as dict.""" + if not issubclass(self.dtype, Numeric): # type: ignore[arg-type] + raise DekerInvalidSchemaError( + f'Schema "{self.__class__.__name__}" is invalid/corrupted: wrong dtype {self.dtype}' + ) try: dtype = DTypeEnum.get_name(DTypeEnum(self.dtype)) fill_value = None if np.isnan(self.fill_value) else str(self.fill_value) # type: ignore[arg-type] @@ -170,7 +174,9 @@ def as_dict(self) -> dict: return { "dimensions": tuple(dim.as_dict for dim in self.dimensions), "dtype": dtype, - "attributes": tuple(attr.as_dict for attr in self.attributes), + "attributes": tuple(attr.as_dict for attr in self.attributes) + if self.attributes is not None + else tuple(), "fill_value": fill_value, } except (KeyError, ValueError) as e: diff --git a/deker/tools/array.py b/deker/tools/array.py index 5f1f66d..d122a43 100644 --- a/deker/tools/array.py +++ b/deker/tools/array.py @@ -88,7 +88,7 @@ def check_memory(shape: tuple, dtype: type, mem_limit_from_settings: int) -> Non if array_size_bytes > limit: raise DekerMemoryError( f"Can not allocate {array_size_human} for array/subset with shape {shape} and dtype {dtype}. " - f"Current Deker limit per array/subset is {limit_human}. Value in config: {mem_limit_from_settings}" + f"Current Deker limit per array/subset is {limit_human}. Value in config: {mem_limit_from_settings} bytes. " f"Reduce shape or dtype of your array/subset or increase Deker RAM limit." ) diff --git a/deker/tools/schema.py b/deker/tools/schema.py index be9ed9c..358dbcc 100644 --- a/deker/tools/schema.py +++ b/deker/tools/schema.py @@ -93,7 +93,7 @@ def create_attributes_schema(attributes_schemas: List[dict]) -> Tuple["Attribute attributes = [] try: for params in attributes_schemas: - dtype = DTypeEnum[params["dtype"].lstrip("numpy.")].value + dtype = DTypeEnum[params["dtype"].split("numpy.")[-1]].value attr_schema = AttributeSchema(**{**params, "dtype": dtype}) attributes.append(attr_schema) return tuple(attributes) diff --git a/deker/types/private/enums.py b/deker/types/private/enums.py index ed5eb4c..54b1857 100644 --- a/deker/types/private/enums.py +++ b/deker/types/private/enums.py @@ -33,7 +33,18 @@ class DTypeEnum(Enum): int16 = np.int16 int32 = np.int32 int64 = np.int64 + int_ = np.int64 longlong = np.longlong + uint = np.uint + uint8 = np.uint8 + ubyte = np.ubyte + uint16 = np.uint16 + uint32 = np.uint32 + uintc = np.uintc + uint64 = np.uint64 + uintp = np.uintp + ushort = np.ushort + ulonglong = np.ulonglong float16 = np.float16 float32 = np.float32 float64 = np.float64 diff --git a/deker/types/private/typings.py b/deker/types/private/typings.py index 4bddbce..e14f5b9 100644 --- a/deker/types/private/typings.py +++ b/deker/types/private/typings.py @@ -46,25 +46,35 @@ EllipsisType = Type[Ellipsis] NumericDtypes = [ - int, - float, - complex, - np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 - np.int8, - np.int16, - np.int32, - np.int64, - np.float16, - np.float64, - np.float128, - np.longfloat, - np.double, - np.longdouble, - np.complex64, - np.complex128, - np.complex256, - np.longcomplex, - np.longlong, + # int, + # float, + # complex, + # np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 + # np.int8, + # np.int16, + # np.int32, + # np.int64, + np.uint, + np.uint8, + np.ubyte, + np.uint16, + np.uint32, + np.uintc, + np.uint64, + np.uintp, + np.ushort, + np.ulonglong, + # np.float16, + # np.float64, + # np.float128, + # np.longfloat, + # np.double, + # np.longdouble, + # np.complex64, + # np.complex128, + # np.complex256, + # np.longcomplex, + # np.longlong, ] Numeric = Union[ @@ -76,6 +86,16 @@ np.int16, np.int32, np.int64, + np.uint, + np.uint8, + np.ubyte, + np.uint16, + np.uint32, + np.uintc, + np.uint64, + np.uintp, + np.ushort, + np.ulonglong, np.float16, np.float64, np.float128, diff --git a/deker/uri.py b/deker/uri.py index f9015a1..bef6640 100644 --- a/deker/uri.py +++ b/deker/uri.py @@ -18,7 +18,7 @@ from collections import OrderedDict, namedtuple from pathlib import Path -from typing import Dict, List, Optional, Tuple, Union +from typing import List, Optional, Tuple, Union from urllib.parse import ParseResult, _NetlocResultMixinStr, parse_qs, quote, urlparse from deker_tools.path import is_path_valid @@ -39,22 +39,22 @@ class Uri(ParseResultWithServers, _NetlocResultMixinStr): __annotations__ = OrderedDict( scheme={"separator": None, "divider": None}, netloc={"separator": "://", "divider": None}, - path={"separator": "/", "divider": None}, - params={"separator": ";", "divider": None}, + servers={"separator": "@", "divider": ","}, + path={"separator": "/", "divider": "/"}, + params={"separator": ";", "divider": ","}, query={"separator": "?", "divider": "&"}, fragment={"separator": "#", "divider": None}, - servers=Optional[List[str]], ) - query: Dict[str, List[str]] - servers: List[str] @property def raw_url(self) -> str: """Get url from raw uri without query string, arguments and fragments.""" - url = self.scheme + "://" # type: ignore[attr-defined] + url = self.scheme + self.__annotations__["netloc"]["separator"] # type: ignore[attr-defined] if self.netloc: # type: ignore[attr-defined] url += self.netloc # type: ignore[attr-defined] - url += quote(str(self.path), safe=":/") # type: ignore[attr-defined] + url += quote( + str(self.path), safe=self.__annotations__["netloc"]["separator"][:-1] # type: ignore[attr-defined] + ) return url @classmethod @@ -64,18 +64,33 @@ def __get_servers_and_netloc(cls, netloc: str, scheme: str) -> Tuple[str, Option :param netloc: Netloc object :param scheme: http or https """ - # If scheme is not http or https, it couldn't work in cluster mode - if "," not in netloc or scheme not in ["http", "https"]: + # If scheme is not http or https, it cannot work in cluster mode + if ( + scheme not in ["http", "https"] + or cls.__annotations__["servers"]["divider"] not in netloc + ): # So servers will be None return netloc, None # Otherwise parse servers - servers = netloc.split(",") + servers = netloc.split(cls.__annotations__["servers"]["divider"]) node_with_possible_auth = servers[0] - if "@" in node_with_possible_auth: - auth, _ = node_with_possible_auth.split("@") - return node_with_possible_auth, [f"{scheme}://{auth}@{host}" for host in servers[1:]] - return node_with_possible_auth, [f"{scheme}://{host}" for host in servers[1:]] + if cls.__annotations__["servers"]["separator"] in node_with_possible_auth: + auth, _ = node_with_possible_auth.split(cls.__annotations__["servers"]["separator"]) + return ( + node_with_possible_auth, + [ + f"{scheme}{cls.__annotations__['netloc']['separator']}" + f"{auth}" + f"{cls.__annotations__['servers']['separator']}" + f"{host}" + for host in servers[1:] + ], + ) + return ( + node_with_possible_auth, + [f"{scheme}{cls.__annotations__['netloc']['separator']}{host}" for host in servers[1:]], + ) @classmethod def __parse(cls, uri: str) -> Uri: @@ -86,7 +101,7 @@ def __parse(cls, uri: str) -> Uri: result = urlparse(uri) if ";" in result.path: - path, params = result.path.split(";") + path, params = result.path.split(cls.__annotations__["params"]["separator"]) else: path, params = result.path, result.params @@ -135,16 +150,16 @@ def __truediv__(self, other: Union[str, Path]) -> Uri: :param other: Path or string to join """ - sep = "/" + sep = self.__annotations__["path"]["separator"] other = str(other) path = sep.join((self.path, other.strip())) # type: ignore[attr-defined] netloc, servers = self.__get_servers_and_netloc(self.netloc, self.scheme) # type: ignore[attr-defined] res = Uri( # type: ignore self.scheme, # type: ignore[attr-defined] netloc, - path, # type: ignore[arg-type] + path, # type: ignore[attr-defined] self.params, # type: ignore[attr-defined] - self.query, # type: ignore[arg-type] + self.query, # type: ignore[attr-defined] self.fragment, # type: ignore[attr-defined] servers, ) diff --git a/tests/test_cases/test_collections/test_collection_methods.py b/tests/test_cases/test_collections/test_collection_methods.py index 6ac8b98..8dda18a 100644 --- a/tests/test_cases/test_collections/test_collection_methods.py +++ b/tests/test_cases/test_collections/test_collection_methods.py @@ -1,8 +1,10 @@ import uuid + from datetime import datetime, timedelta, timezone from io import BytesIO import hdf5plugin +import numpy as np import pytest from deker_local_adapters import HDF5StorageAdapter, LocalCollectionAdapter @@ -71,7 +73,7 @@ def test_clear_collection( array_collection: Collection, collection_adapter: LocalCollectionAdapter, storage_adapter, - array_params + array_params, ): """Test collection clears its data well. @@ -338,6 +340,10 @@ def test_collection_as_dict( BytesIO, set, type, + str, + dict, + tuple, + list, ), ) def test_wrong_dtype(self, dtype: type, array_schema: ArraySchema): diff --git a/tests/test_cases/test_locking/mpt.py b/tests/test_cases/test_locking/mpt.py index d28a8c4..fd48d73 100644 --- a/tests/test_cases/test_locking/mpt.py +++ b/tests/test_cases/test_locking/mpt.py @@ -27,7 +27,6 @@ array_symlinks_directory="array_symlinks", varray_symlinks_directory="varray_symlinks", uri="/tmp/mp_test/", - graceful_shutdown=True, ) diff --git a/tests/test_cases/test_managers/test_managers.py b/tests/test_cases/test_managers/test_managers.py index 5789ddc..8103602 100644 --- a/tests/test_cases/test_managers/test_managers.py +++ b/tests/test_cases/test_managers/test_managers.py @@ -10,7 +10,7 @@ from deker.arrays import Array, VArray from deker.client import Client from deker.collection import Collection -from deker.errors import DekerFilterError, DekerValidationError, DekerArrayError +from deker.errors import DekerArrayError, DekerFilterError, DekerValidationError from deker.schemas import ( ArraySchema, AttributeSchema, diff --git a/tests/test_cases/test_tools/test_tools.py b/tests/test_cases/test_tools/test_tools.py index a32d607..33a3105 100644 --- a/tests/test_cases/test_tools/test_tools.py +++ b/tests/test_cases/test_tools/test_tools.py @@ -6,12 +6,12 @@ from deker_local_adapters import LocalCollectionAdapter -from deker.tools.array import generate_uid from tests.parameters.collection_params import CollectionParams from deker.collection import Collection from deker.errors import DekerInstanceNotExistsError, DekerMemoryError, DekerValidationError from deker.tools import check_memory, convert_human_memory_to_bytes +from deker.tools.array import generate_uid from deker.tools.time import convert_datetime_attrs_to_iso, convert_iso_attrs_to_datetime From b64183a99faaaea6de50c8a77218f01bed20c31d Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Mon, 4 Dec 2023 15:47:26 +0200 Subject: [PATCH 02/22] poetry updated --- poetry.lock | 547 ++++++++++++++++++++++++---------------------------- 1 file changed, 252 insertions(+), 295 deletions(-) diff --git a/poetry.lock b/poetry.lock index 450bdba..fed1984 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.7.0 and should not be changed by hand. [[package]] name = "alabaster" @@ -13,13 +13,13 @@ files = [ [[package]] name = "anyio" -version = "4.0.0" +version = "4.1.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = true python-versions = ">=3.8" files = [ - {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, - {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, + {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, + {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, ] [package.dependencies] @@ -28,9 +28,9 @@ idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.22)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "apeye" @@ -113,15 +113,18 @@ Sphinx = ">=2.2,<8.0" [[package]] name = "babel" -version = "2.13.0" +version = "2.13.1" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, - {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, + {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, + {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, ] +[package.dependencies] +setuptools = {version = "*", markers = "python_version >= \"3.12\""} + [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -238,13 +241,13 @@ redis = ["redis (>=2.10.5)"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] @@ -260,101 +263,101 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.1" +version = "3.3.2" 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.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, - {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] @@ -510,12 +513,12 @@ numpy = ">=1.18,<2.0" [[package]] name = "deker-server-adapters" -version = "1.0.1" +version = "1.0.3" description = "Plugin with server adapters for Deker" optional = true python-versions = ">=3.9,<4.0" files = [ - {file = "deker_server_adapters-1.0.1.tar.gz", hash = "sha256:c7889a8a86ee907a797beaf9ca595d5ba259e51a11d696ba0f46fa3e60d15784"}, + {file = "deker_server_adapters-1.0.3.tar.gz", hash = "sha256:421caf459c3dedf4f1950d56b86079ab73150def1e5cfe84b79627b72b11bfb5"}, ] [package.dependencies] @@ -549,13 +552,13 @@ numpy = ">=1.18" [[package]] name = "dict2css" -version = "0.3.0" +version = "0.3.0.post1" description = "A μ-library for constructing cascading style sheets from Python dictionaries." optional = false python-versions = ">=3.6" files = [ - {file = "dict2css-0.3.0-py3-none-any.whl", hash = "sha256:ef934ce73a225fdd5f811b484fe9e2dd768f7ef14a89fc8f4eb5672597131d00"}, - {file = "dict2css-0.3.0.tar.gz", hash = "sha256:1e8b1bf580dca2083198f88a60ec88c878a8829d760dfe45483ef80fe2905117"}, + {file = "dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d"}, + {file = "dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719"}, ] [package.dependencies] @@ -641,13 +644,13 @@ sphinx = ["sphinx (>=3.2.0)", "sphinx-jinja2-compat (>=0.1.1)", "sphinx-toolbox [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -655,19 +658,19 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.12.4" +version = "3.13.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4"}, - {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"}, + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, ] [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)"] -typing = ["typing-extensions (>=4.7.1)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] [[package]] name = "flake8" @@ -871,17 +874,17 @@ numpy = ">=1.17.3" [[package]] name = "hdf5plugin" -version = "4.2.0" +version = "4.3.0" description = "HDF5 Plugins for Windows, MacOS, and Linux" optional = false python-versions = ">=3.7" files = [ - {file = "hdf5plugin-4.2.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:b20a7f413a52bc6b08cf65b545c79d5cfee4a28d102c9c751635e8f8ab39363f"}, - {file = "hdf5plugin-4.2.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b095623510182d2a3cb5529e06ceb75abad92e36727124ae9ddfd460b80ef1f6"}, - {file = "hdf5plugin-4.2.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a39f3c76165e7a72e87aa066ff9b0bfccf51eb05a3ba6c22ba88687ec92bda03"}, - {file = "hdf5plugin-4.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608162a984b06db9f67c0d46571e2973a6ee75623ee2f8ff5cc78e5652c0a6"}, - {file = "hdf5plugin-4.2.0-py3-none-win_amd64.whl", hash = "sha256:804e93e61cfd2030670500470fea4e2dec44d1d0884a7272a849a9b2012ada32"}, - {file = "hdf5plugin-4.2.0.tar.gz", hash = "sha256:500c3de00fb80b3a588808776e89a90e8f2fc5353f0b5e921750c93030ed2d36"}, + {file = "hdf5plugin-4.3.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:958b7c1d86617d360647ada72d9b07e854dca2a772f06e3bc9a67de653bc297d"}, + {file = "hdf5plugin-4.3.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da7fc3d9cb5a7532efe7e7aa04c58e1463905e3834e50d241d4aab98507db1cd"}, + {file = "hdf5plugin-4.3.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:231c3f7e2e0ca48ad3fbf44413fc3b008f5d3737b4ab7cd0e7603a6a42cd7d54"}, + {file = "hdf5plugin-4.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeb9e16355eb0330e8158d2cae9f1d0c283843670e2fd1e8d9cc7515464e36f4"}, + {file = "hdf5plugin-4.3.0-py3-none-win_amd64.whl", hash = "sha256:cb0562ac61aa9144a5e1a53eb228559ad78d9feac3dd4bedf37f1e3d2f3e760e"}, + {file = "hdf5plugin-4.3.0.tar.gz", hash = "sha256:0face8ee85817f168ab97cd72bd83dfd2803adbe7fc4881c5edf5b064ecb3684"}, ] [package.dependencies] @@ -980,13 +983,13 @@ files = [ [[package]] name = "identify" -version = "2.5.30" +version = "2.5.32" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.30-py2.py3-none-any.whl", hash = "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54"}, - {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"}, + {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"}, + {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"}, ] [package.extras] @@ -994,13 +997,13 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] @@ -1016,20 +1019,20 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] 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"] @@ -1428,36 +1431,47 @@ setuptools = "*" [[package]] name = "numpy" -version = "1.25.2" +version = "1.26.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" files = [ - {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"}, + {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"}, + {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"}, + {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"}, + {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"}, + {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"}, + {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"}, + {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"}, + {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"}, + {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"}, + {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"}, + {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"}, + {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"}, + {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"}, + {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"}, + {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"}, + {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"}, + {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"}, + {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"}, + {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"}, + {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"}, + {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"}, + {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"}, + {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"}, + {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"}, + {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"}, + {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"}, + {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"}, + {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"}, + {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"}, + {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"}, + {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"}, + {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"}, + {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"}, ] [[package]] @@ -1487,107 +1501,50 @@ files = [ [[package]] name = "pandas" -version = "2.1.0" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pandas-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:40dd20439ff94f1b2ed55b393ecee9cb6f3b08104c2c40b0cb7186a2f0046242"}, - {file = "pandas-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d4f38e4fedeba580285eaac7ede4f686c6701a9e618d8a857b138a126d067f2f"}, - {file = "pandas-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e6a0fe052cf27ceb29be9429428b4918f3740e37ff185658f40d8702f0b3e09"}, - {file = "pandas-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d81e1813191070440d4c7a413cb673052b3b4a984ffd86b8dd468c45742d3cc"}, - {file = "pandas-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eb20252720b1cc1b7d0b2879ffc7e0542dd568f24d7c4b2347cb035206936421"}, - {file = "pandas-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:38f74ef7ebc0ffb43b3d633e23d74882bce7e27bfa09607f3c5d3e03ffd9a4a5"}, - {file = "pandas-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cda72cc8c4761c8f1d97b169661f23a86b16fdb240bdc341173aee17e4d6cedd"}, - {file = "pandas-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d97daeac0db8c993420b10da4f5f5b39b01fc9ca689a17844e07c0a35ac96b4b"}, - {file = "pandas-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8c58b1113892e0c8078f006a167cc210a92bdae23322bb4614f2f0b7a4b510f"}, - {file = "pandas-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:629124923bcf798965b054a540f9ccdfd60f71361255c81fa1ecd94a904b9dd3"}, - {file = "pandas-2.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:70cf866af3ab346a10debba8ea78077cf3a8cd14bd5e4bed3d41555a3280041c"}, - {file = "pandas-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:d53c8c1001f6a192ff1de1efe03b31a423d0eee2e9e855e69d004308e046e694"}, - {file = "pandas-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86f100b3876b8c6d1a2c66207288ead435dc71041ee4aea789e55ef0e06408cb"}, - {file = "pandas-2.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28f330845ad21c11db51e02d8d69acc9035edfd1116926ff7245c7215db57957"}, - {file = "pandas-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9a6ccf0963db88f9b12df6720e55f337447aea217f426a22d71f4213a3099a6"}, - {file = "pandas-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99e678180bc59b0c9443314297bddce4ad35727a1a2656dbe585fd78710b3b9"}, - {file = "pandas-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b31da36d376d50a1a492efb18097b9101bdbd8b3fbb3f49006e02d4495d4c644"}, - {file = "pandas-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0164b85937707ec7f70b34a6c3a578dbf0f50787f910f21ca3b26a7fd3363437"}, - {file = "pandas-2.1.0.tar.gz", hash = "sha256:62c24c7fc59e42b775ce0679cfa7b14a5f9bfb7643cfbe708c960699e05fb918"}, -] - -[package.dependencies] -numpy = {version = ">=1.23.2", markers = "python_version >= \"3.11\""} -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.1" - -[package.extras] -all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] -aws = ["s3fs (>=2022.05.0)"] -clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"] -compression = ["zstandard (>=0.17.0)"] -computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"] -feather = ["pyarrow (>=7.0.0)"] -fss = ["fsspec (>=2022.05.0)"] -gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"] -hdf5 = ["tables (>=3.7.0)"] -html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"] -mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"] -parquet = ["pyarrow (>=7.0.0)"] -performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"] -plot = ["matplotlib (>=3.6.1)"] -postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"] -spss = ["pyreadstat (>=1.1.5)"] -sql-other = ["SQLAlchemy (>=1.4.36)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.8.0)"] - -[[package]] -name = "pandas" -version = "2.1.1" +version = "2.1.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" files = [ - {file = "pandas-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58d997dbee0d4b64f3cb881a24f918b5f25dd64ddf31f467bb9b67ae4c63a1e4"}, - {file = "pandas-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02304e11582c5d090e5a52aec726f31fe3f42895d6bfc1f28738f9b64b6f0614"}, - {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffa8f0966de2c22de408d0e322db2faed6f6e74265aa0856f3824813cf124363"}, - {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1f84c144dee086fe4f04a472b5cd51e680f061adf75c1ae4fc3a9275560f8f4"}, - {file = "pandas-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ce97667d06d69396d72be074f0556698c7f662029322027c226fd7a26965cb"}, - {file = "pandas-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:4c3f32fd7c4dccd035f71734df39231ac1a6ff95e8bdab8d891167197b7018d2"}, - {file = "pandas-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e2959720b70e106bb1d8b6eadd8ecd7c8e99ccdbe03ee03260877184bb2877d"}, - {file = "pandas-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25e8474a8eb258e391e30c288eecec565bfed3e026f312b0cbd709a63906b6f8"}, - {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8bd1685556f3374520466998929bade3076aeae77c3e67ada5ed2b90b4de7f0"}, - {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc3657869c7902810f32bd072f0740487f9e030c1a3ab03e0af093db35a9d14e"}, - {file = "pandas-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:05674536bd477af36aa2effd4ec8f71b92234ce0cc174de34fd21e2ee99adbc2"}, - {file = "pandas-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:b407381258a667df49d58a1b637be33e514b07f9285feb27769cedb3ab3d0b3a"}, - {file = "pandas-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c747793c4e9dcece7bb20156179529898abf505fe32cb40c4052107a3c620b49"}, - {file = "pandas-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3bcad1e6fb34b727b016775bea407311f7721db87e5b409e6542f4546a4951ea"}, - {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5ec7740f9ccb90aec64edd71434711f58ee0ea7f5ed4ac48be11cfa9abf7317"}, - {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29deb61de5a8a93bdd033df328441a79fcf8dd3c12d5ed0b41a395eef9cd76f0"}, - {file = "pandas-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f99bebf19b7e03cf80a4e770a3e65eee9dd4e2679039f542d7c1ace7b7b1daa"}, - {file = "pandas-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:84e7e910096416adec68075dc87b986ff202920fb8704e6d9c8c9897fe7332d6"}, - {file = "pandas-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366da7b0e540d1b908886d4feb3d951f2f1e572e655c1160f5fde28ad4abb750"}, - {file = "pandas-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e50e72b667415a816ac27dfcfe686dc5a0b02202e06196b943d54c4f9c7693e"}, - {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc1ab6a25da197f03ebe6d8fa17273126120874386b4ac11c1d687df288542dd"}, - {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0dbfea0dd3901ad4ce2306575c54348d98499c95be01b8d885a2737fe4d7a98"}, - {file = "pandas-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0489b0e6aa3d907e909aef92975edae89b1ee1654db5eafb9be633b0124abe97"}, - {file = "pandas-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cdb0fab0400c2cb46dafcf1a0fe084c8bb2480a1fa8d81e19d15e12e6d4ded2"}, - {file = "pandas-2.1.1.tar.gz", hash = "sha256:fecb198dc389429be557cde50a2d46da8434a17fe37d7d41ff102e3987fd947b"}, + {file = "pandas-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f"}, + {file = "pandas-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb"}, + {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb"}, + {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4"}, + {file = "pandas-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03"}, + {file = "pandas-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e"}, + {file = "pandas-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82"}, + {file = "pandas-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042"}, + {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef"}, + {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58"}, + {file = "pandas-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2"}, + {file = "pandas-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f"}, + {file = "pandas-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140"}, + {file = "pandas-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d"}, + {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e"}, + {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683"}, + {file = "pandas-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00"}, + {file = "pandas-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549"}, + {file = "pandas-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8"}, + {file = "pandas-2.1.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d"}, + {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a"}, + {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2"}, + {file = "pandas-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a"}, + {file = "pandas-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71"}, + {file = "pandas-2.1.3.tar.gz", hash = "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f"}, ] [package.dependencies] numpy = [ - {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" tzdata = ">=2022.1" [package.extras] -all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] +all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] aws = ["s3fs (>=2022.05.0)"] clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"] compression = ["zstandard (>=0.17.0)"] @@ -1607,7 +1564,7 @@ plot = ["matplotlib (>=3.6.1)"] postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"] spss = ["pyreadstat (>=1.1.5)"] sql-other = ["SQLAlchemy (>=1.4.36)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.8.0)"] [[package]] @@ -1638,13 +1595,13 @@ files = [ [[package]] name = "pbr" -version = "5.11.1" +version = "6.0.0" description = "Python Build Reasonableness" optional = false python-versions = ">=2.6" files = [ - {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, - {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, + {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"}, + {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"}, ] [[package]] @@ -1663,13 +1620,13 @@ flake8 = ">=5.0.0" [[package]] name = "platformdirs" -version = "3.11.0" +version = "4.0.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.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, - {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, + {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, + {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, ] [package.extras] @@ -1711,13 +1668,13 @@ virtualenv = ">=20.10.0" [[package]] name = "prompt-toolkit" -version = "3.0.39" +version = "3.0.41" description = "Library for building powerful interactive command lines in Python" optional = true 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"}, + {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, + {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, ] [package.dependencies] @@ -1831,17 +1788,18 @@ files = [ [[package]] name = "pygments" -version = "2.16.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" @@ -2041,13 +1999,13 @@ docutils = ">=0.11,<1.0" [[package]] name = "rich" -version = "13.6.0" +version = "13.7.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.6.0-py3-none-any.whl", hash = "sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245"}, - {file = "rich-13.6.0.tar.gz", hash = "sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef"}, + {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, + {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, ] [package.dependencies] @@ -2059,13 +2017,13 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruamel-yaml" -version = "0.18.1" +version = "0.18.5" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false -python-versions = ">=3" +python-versions = ">=3.7" files = [ - {file = "ruamel.yaml-0.18.1-py3-none-any.whl", hash = "sha256:93907ef6c731ec1bcb41ab7ff99413945f5acfd7eee27785f2cb18b175dd5aae"}, - {file = "ruamel.yaml-0.18.1.tar.gz", hash = "sha256:649a301890441d36ea9cb0f48d07353de82b8cbde2244387e7ef6b1d3b9ee6cd"}, + {file = "ruamel.yaml-0.18.5-py3-none-any.whl", hash = "sha256:a013ac02f99a69cdd6277d9664689eb1acba07069f912823177c5eced21a6ada"}, + {file = "ruamel.yaml-0.18.5.tar.gz", hash = "sha256:61917e3a35a569c1133a8f772e1226961bf5a1198bea7e23f06a0841dea1ab0e"}, ] [package.dependencies] @@ -2136,17 +2094,17 @@ files = [ [[package]] name = "setuptools" -version = "68.2.2" +version = "69.0.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, + {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, + {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "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] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -2261,13 +2219,13 @@ type-comment = ["typed-ast (>=1.5.4)"] [[package]] name = "sphinx-jinja2-compat" -version = "0.2.0" +version = "0.2.0.post1" description = "Patches Jinja2 v3 to restore compatibility with earlier Sphinx versions." optional = false python-versions = ">=3.6" files = [ - {file = "sphinx_jinja2_compat-0.2.0-py3-none-any.whl", hash = "sha256:a5f3112d6873991c2cf28e37287163a0485d9c0812863b8aa4df7182722501fb"}, - {file = "sphinx_jinja2_compat-0.2.0.tar.gz", hash = "sha256:c41346d859653e202b623f4236da8936243ed734abf5984adc3bef59d6f9a946"}, + {file = "sphinx_jinja2_compat-0.2.0.post1-py3-none-any.whl", hash = "sha256:f9d329174bdde8db19dc12c62528367196eb2f6b46c91754eca604acd0c0f6ad"}, + {file = "sphinx_jinja2_compat-0.2.0.post1.tar.gz", hash = "sha256:974289a12a9f402108dead621e9c15f7004e945d5cfcaea8d6419e94d3fa95a3"}, ] [package.dependencies] @@ -2523,13 +2481,13 @@ widechars = ["wcwidth"] [[package]] name = "termcolor" -version = "2.3.0" +version = "2.4.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, - {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, + {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, + {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, ] [package.extras] @@ -2636,36 +2594,35 @@ files = [ [[package]] name = "urllib3" -version = "2.0.7" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, ] [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)"] [[package]] name = "virtualenv" -version = "20.24.6" +version = "20.25.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, - {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" +platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] @@ -2673,13 +2630,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "wcwidth" -version = "0.2.8" +version = "0.2.12" description = "Measures the displayed width of unicode strings in a terminal" optional = true python-versions = "*" files = [ - {file = "wcwidth-0.2.8-py2.py3-none-any.whl", hash = "sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704"}, - {file = "wcwidth-0.2.8.tar.gz", hash = "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"}, + {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, + {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, ] [[package]] @@ -2695,13 +2652,13 @@ files = [ [[package]] name = "xarray" -version = "2023.10.1" +version = "2023.11.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.9" files = [ - {file = "xarray-2023.10.1-py3-none-any.whl", hash = "sha256:71ea549e9be6dfeab19c2736acf659967b861aad2397691a80e5fad0c61db2ad"}, - {file = "xarray-2023.10.1.tar.gz", hash = "sha256:9eeee170c3fc2f3321eb6ba40c17ffe4d8c98d49d55e4a3fba66a75bdc7dd9e5"}, + {file = "xarray-2023.11.0-py3-none-any.whl", hash = "sha256:933b5101e965120ed58e29525667ab34aafcea1886c236ade72a34d7bb465d9c"}, + {file = "xarray-2023.11.0.tar.gz", hash = "sha256:9a45e10741844b5f948d8e1e768b460df7e90696d18e2eff2c1d47f5d9d50252"}, ] [package.dependencies] @@ -2710,7 +2667,7 @@ packaging = ">=21.3" pandas = ">=1.4" [package.extras] -accel = ["bottleneck", "flox", "numbagg", "scipy"] +accel = ["bottleneck", "flox", "numbagg", "opt-einsum", "scipy"] complete = ["xarray[accel,io,parallel,viz]"] io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap", "scipy", "zarr"] parallel = ["dask[complete]"] From f3ca631305aedcc4986eed11f8e7c9dadef7d312 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Mon, 4 Dec 2023 15:55:52 +0200 Subject: [PATCH 03/22] types uncommented --- deker/types/private/typings.py | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/deker/types/private/typings.py b/deker/types/private/typings.py index e14f5b9..c5372ef 100644 --- a/deker/types/private/typings.py +++ b/deker/types/private/typings.py @@ -46,14 +46,14 @@ EllipsisType = Type[Ellipsis] NumericDtypes = [ - # int, - # float, - # complex, - # np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 - # np.int8, - # np.int16, - # np.int32, - # np.int64, + int, + float, + complex, + np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 + np.int8, + np.int16, + np.int32, + np.int64, np.uint, np.uint8, np.ubyte, @@ -64,17 +64,17 @@ np.uintp, np.ushort, np.ulonglong, - # np.float16, - # np.float64, - # np.float128, - # np.longfloat, - # np.double, - # np.longdouble, - # np.complex64, - # np.complex128, - # np.complex256, - # np.longcomplex, - # np.longlong, + np.float16, + np.float64, + np.float128, + np.longfloat, + np.double, + np.longdouble, + np.complex64, + np.complex128, + np.complex256, + np.longcomplex, + np.longlong, ] Numeric = Union[ From 33d4870b3c4aaca2a4ed44965b5f298ec9267fb1 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Mon, 4 Dec 2023 17:13:19 +0200 Subject: [PATCH 04/22] tests fixed, float32 restored --- deker/ABC/base_schemas.py | 17 +++++++++-------- deker/types/private/typings.py | 2 ++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/deker/ABC/base_schemas.py b/deker/ABC/base_schemas.py index 9f04704..95f0310 100644 --- a/deker/ABC/base_schemas.py +++ b/deker/ABC/base_schemas.py @@ -27,7 +27,7 @@ from deker.errors import DekerInvalidSchemaError, DekerValidationError from deker.tools.schema import get_default_fill_value from deker.types.private.enums import DTypeEnum -from deker.types.private.typings import Numeric +from deker.types.private.typings import Numeric, NumericDtypes @dataclass(repr=True) @@ -121,6 +121,9 @@ def __attrs_post_init__(self) -> None: if len({d.name for d in self.dimensions}) < len(self.dimensions): raise DekerValidationError("Dimensions shall have unique names") + if self.dtype not in NumericDtypes: + raise DekerValidationError(f"Invalid dtype {self.dtype}") + try: if self.dtype == int: self.dtype = np.int64 @@ -163,10 +166,10 @@ def named_shape(self) -> Tuple[Tuple[str, int], ...]: @property def as_dict(self) -> dict: """Serialize as dict.""" - if not issubclass(self.dtype, Numeric): # type: ignore[arg-type] - raise DekerInvalidSchemaError( - f'Schema "{self.__class__.__name__}" is invalid/corrupted: wrong dtype {self.dtype}' - ) + error = f'Schema "{self.__class__.__name__}" is invalid/corrupted: ' + + if self.dtype not in NumericDtypes: + raise DekerInvalidSchemaError(error + f"wrong dtype {self.dtype}") try: dtype = DTypeEnum.get_name(DTypeEnum(self.dtype)) fill_value = None if np.isnan(self.fill_value) else str(self.fill_value) # type: ignore[arg-type] @@ -180,6 +183,4 @@ def as_dict(self) -> dict: "fill_value": fill_value, } except (KeyError, ValueError) as e: - raise DekerInvalidSchemaError( - f'Schema "{self.__class__.__name__}" is invalid/corrupted: {e}' - ) + raise DekerInvalidSchemaError(error + str(e)) diff --git a/deker/types/private/typings.py b/deker/types/private/typings.py index c5372ef..0ab14a0 100644 --- a/deker/types/private/typings.py +++ b/deker/types/private/typings.py @@ -65,6 +65,7 @@ np.ushort, np.ulonglong, np.float16, + np.float32, np.float64, np.float128, np.longfloat, @@ -97,6 +98,7 @@ np.ushort, np.ulonglong, np.float16, + np.float32, np.float64, np.float128, np.longfloat, From e9368a800f0270e8354daf1161e692b217646345 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Tue, 5 Dec 2023 12:33:29 +0200 Subject: [PATCH 05/22] VArrayWriteLock does not acquire lock on json; DekerMemoryError message improved --- deker/ABC/base_schemas.py | 4 +--- deker/client.py | 12 ++++++++---- deker/locks.py | 19 +++++++++++++++++-- deker/schemas.py | 7 +++++-- deker/tools/array.py | 25 +++++++++++++++++++++---- tests/parameters/schemas_params.py | 4 ++-- 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/deker/ABC/base_schemas.py b/deker/ABC/base_schemas.py index 95f0310..1ee0009 100644 --- a/deker/ABC/base_schemas.py +++ b/deker/ABC/base_schemas.py @@ -177,9 +177,7 @@ def as_dict(self) -> dict: return { "dimensions": tuple(dim.as_dict for dim in self.dimensions), "dtype": dtype, - "attributes": tuple(attr.as_dict for attr in self.attributes) - if self.attributes is not None - else tuple(), + "attributes": tuple(attr.as_dict for attr in self.attributes), "fill_value": fill_value, } except (KeyError, ValueError) as e: diff --git a/deker/client.py b/deker/client.py index 75ac531..06c6897 100644 --- a/deker/client.py +++ b/deker/client.py @@ -214,16 +214,20 @@ def __init__( try: set_logging_level(loglevel.upper()) self.__get_plugins() - mem_limit = convert_human_memory_to_bytes(memory_limit) + total_available_mem = virtual_memory().total + swap_memory().total + memory_limit = convert_human_memory_to_bytes(memory_limit) + if memory_limit >= total_available_mem or memory_limit <= 0: + mem_limit = total_available_mem + else: + mem_limit = memory_limit + self.__config = DekerConfig( # type: ignore[call-arg] uri=uri, workers=workers if workers is not None else cpu_count() + 4, write_lock_timeout=write_lock_timeout, write_lock_check_interval=write_lock_check_interval, loglevel=loglevel.upper(), - memory_limit=( - virtual_memory().total + swap_memory().total if mem_limit <= 0 else mem_limit - ), + memory_limit=mem_limit, ) self.__uri: Uri = Uri.create(self.__config.uri) self.__is_closed: bool = True diff --git a/deker/locks.py b/deker/locks.py index 212f666..eba4461 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -181,7 +181,13 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: class WriteVarrayLock(BaseLock): - """Write lock for VArrays.""" + """Write lock for VArrays. + + VArray shall not be locked itself when writing data. + Only inner Arrays shall be locked. + If updating subsets do not intersect - it's OK, otherwise the first, + which managed to obtain all Array locks, will survive. + """ ALLOWED_TYPES = ["VSubset"] @@ -310,18 +316,27 @@ def release(self, e: Optional[Exception] = None) -> None: # noqa[ARG002] Path(f"{lock}:{os.getpid()}{LocksExtensions.varray_lock.value}").unlink(missing_ok=True) super().release() + def acquire(self, path: Optional[Path]) -> None: + """VArray shall not be locked itself. + + :param path: path to the file to be locked + """ + pass + @staticmethod def _inner_method_logic( lock: "WriteVarrayLock", args: Sequence, kwargs: Dict, func: Callable ) -> Any: """Logic of acquiring lock and getting result. + When writing in VArray + :param lock: The lock that will be acquired :param func: decorated function :param args: arguments of decorated function :param kwargs: keyword arguments of decorated function """ - # If we want to skip logic of lock (e.g when we use server adapters) + # If we want to skip logic of lock (e.g. when we use server adapters) if lock.skip_lock: return lock.get_result(func, args, kwargs) return super()._inner_method_logic(lock, args, kwargs, func) diff --git a/deker/schemas.py b/deker/schemas.py index 53972ec..c83369b 100644 --- a/deker/schemas.py +++ b/deker/schemas.py @@ -265,6 +265,9 @@ def __common_arrays_attributes_post_init__(self: BaseArraysSchema) -> None: # n :param self: ArraySchema or VArraySchema instance """ + if self.attributes is None: + self.attributes = tuple() + if not isinstance(self.attributes, (tuple, list)): raise DekerValidationError("Attributes shall be a list or tuple of AttributeSchema") if any(not isinstance(a, AttributeSchema) for a in self.attributes): @@ -333,7 +336,7 @@ class VArraySchema(SelfLoggerMixin, BaseArraysSchema): vgrid: Optional[Union[List[int], Tuple[int, ...]]] = None arrays_shape: Optional[Union[List[int], Tuple[int, ...]]] = None fill_value: Union[Numeric, type(np.nan), None] = None # type: ignore[valid-type] - attributes: Union[List[AttributeSchema], Tuple[AttributeSchema, ...]] = tuple() + attributes: Union[List[AttributeSchema], Tuple[AttributeSchema, ...], None] = None def __attrs_post_init__(self) -> None: """Validate schema, convert `vgrid` or `arrays_shape` to tuple and calculate the other grid splitter.""" @@ -423,7 +426,7 @@ class ArraySchema(SelfLoggerMixin, BaseArraysSchema): """ fill_value: Union[Numeric, type(np.nan), None] = None # type: ignore[valid-type] - attributes: Union[List[AttributeSchema], Tuple[AttributeSchema, ...]] = tuple() + attributes: Union[List[AttributeSchema], Tuple[AttributeSchema, ...], None] = None def __attrs_post_init__(self) -> None: """Validate schema.""" diff --git a/deker/tools/array.py b/deker/tools/array.py index d122a43..59f33c4 100644 --- a/deker/tools/array.py +++ b/deker/tools/array.py @@ -43,10 +43,10 @@ def convert_human_memory_to_bytes(memory_limit: Union[int, str]) -> int: :param memory_limit: memory limit provided by the user """ bytes_ = 1024 - mapping: Dict[str, int] = {"k": bytes_, "m": bytes_**2, "g": bytes_**3} + mapping: Dict[str, int] = {"k": bytes_, "m": bytes_**2, "g": bytes_**3, "t": bytes_**4} error = ( f"invalid memory_limit value: {memory_limit}; expected `int` or `str` in format [number][unit] " - f'where unit is one of ["k", "K", "m", "M", "g", "G"], e.g. "8G" or "512m"' + f'where unit is one of ["k", "K", "m", "M", "g", "G", "t", "T"], e.g. "8G" or "512m"' ) if not isinstance(memory_limit, (int, str)): raise DekerValidationError(error) @@ -81,15 +81,32 @@ def check_memory(shape: tuple, dtype: type, mem_limit_from_settings: int) -> Non array_size_bytes = np.dtype(dtype).itemsize * array_values array_size_human = convert_size_to_human(array_size_bytes) + total_machine_mem = virtual_memory().total + swap_memory().total + total_human_mem = convert_size_to_human(total_machine_mem) current_limit = virtual_memory().available + swap_memory().free limit = min(mem_limit_from_settings, current_limit) limit_human = convert_size_to_human(limit) + config_human_limit = convert_size_to_human(mem_limit_from_settings) + + deker_limit = f"{config_human_limit} ({mem_limit_from_settings} bytes). " + limit_message = ( + "Deker Client memory usage is limited to the total memory available on this machine: " + + deker_limit + ) + advise = "" + if total_machine_mem > mem_limit_from_settings: + limit_message = ( + f"Total memory available on this machine is {total_human_mem} ({total_machine_mem} bytes). " + f"Deker Client memory usage is manually limited to " + deker_limit + ) + advise = " Also, you may try to increase the value of Deker Client memory limit." if array_size_bytes > limit: raise DekerMemoryError( f"Can not allocate {array_size_human} for array/subset with shape {shape} and dtype {dtype}. " - f"Current Deker limit per array/subset is {limit_human}. Value in config: {mem_limit_from_settings} bytes. " - f"Reduce shape or dtype of your array/subset or increase Deker RAM limit." + f"{limit_message}" + f"Current available free memory per array/subset is {limit_human} ({limit} bytes). " + f"Reduce your schema or the `shape` of your subset or revise other processes memory usage.{advise}" ) diff --git a/tests/parameters/schemas_params.py b/tests/parameters/schemas_params.py index c3e7f05..b22914a 100644 --- a/tests/parameters/schemas_params.py +++ b/tests/parameters/schemas_params.py @@ -520,7 +520,7 @@ def _generate_types( datetime.now(), Scale(0.1, 0.2), ]: - if exception_types and type(item) in exception_types: + if exception_types and type(item) in exception_types or item is None: continue result.append({**base_dict.copy(), key: item}) if key == "scale": @@ -545,7 +545,7 @@ def WRONG_params_dataclass_raises(cls) -> List[Any]: *cls._generate_types( base_dict={"dtype": dtype, "dimensions": dimensions}, key="attributes", - exception_types=[tuple, list], + exception_types=[tuple, list, NoneType], ), ] From 9f386cec977302c27fa0cc079e4c8afd6e38d47c Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Tue, 5 Dec 2023 13:20:50 +0200 Subject: [PATCH 06/22] Conversation fixes --- deker/locks.py | 2 +- tests/parameters/schemas_params.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deker/locks.py b/deker/locks.py index eba4461..448e881 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -317,7 +317,7 @@ def release(self, e: Optional[Exception] = None) -> None: # noqa[ARG002] super().release() def acquire(self, path: Optional[Path]) -> None: - """VArray shall not be locked itself. + """VArray shall not lock itself. :param path: path to the file to be locked """ diff --git a/tests/parameters/schemas_params.py b/tests/parameters/schemas_params.py index b22914a..039c6d2 100644 --- a/tests/parameters/schemas_params.py +++ b/tests/parameters/schemas_params.py @@ -520,7 +520,7 @@ def _generate_types( datetime.now(), Scale(0.1, 0.2), ]: - if exception_types and type(item) in exception_types or item is None: + if exception_types and type(item) in exception_types: continue result.append({**base_dict.copy(), key: item}) if key == "scale": From 4cbb105294cc74ace23ea4534b85ffa3b53a6e4d Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Tue, 5 Dec 2023 20:40:59 +0200 Subject: [PATCH 07/22] docs upgraded, numpy types aliases added --- deker/types/private/enums.py | 13 ++- deker/types/private/typings.py | 32 ++++-- docs/deker/collection_schema.rst | 188 ++++++++++++++++++++++++++----- docs/deker/data_access.rst | 26 ++++- docs/deker/fine_tuning.rst | 7 +- 5 files changed, 223 insertions(+), 43 deletions(-) diff --git a/deker/types/private/enums.py b/deker/types/private/enums.py index 54b1857..882f6ed 100644 --- a/deker/types/private/enums.py +++ b/deker/types/private/enums.py @@ -30,30 +30,39 @@ class DTypeEnum(Enum): float = float complex = complex int8 = np.int8 + byte = np.byte int16 = np.int16 + short = np.short int32 = np.int32 + intc = np.intc int64 = np.int64 + intp = np.intp int_ = np.int64 longlong = np.longlong uint = np.uint uint8 = np.uint8 ubyte = np.ubyte uint16 = np.uint16 + ushort = np.ushort uint32 = np.uint32 uintc = np.uintc uint64 = np.uint64 uintp = np.uintp - ushort = np.ushort ulonglong = np.ulonglong float16 = np.float16 + cfloat = np.cfloat + cdouble = np.cdouble float32 = np.float32 + clongfloat = np.clongfloat float64 = np.float64 + double = np.double float128 = np.float128 longfloat = np.longfloat - double = np.double longdouble = np.longdouble complex64 = np.complex64 + singlecomplex = np.singlecomplex complex128 = np.complex128 + complex_ = np.complex_ complex256 = np.complex256 longcomplex = np.longcomplex string = str diff --git a/deker/types/private/typings.py b/deker/types/private/typings.py index 0ab14a0..728a718 100644 --- a/deker/types/private/typings.py +++ b/deker/types/private/typings.py @@ -49,66 +49,82 @@ int, float, complex, - np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 np.int8, np.int16, + np.short, np.int32, + np.intc, np.int64, + np.intp, + np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 + np.longlong, np.uint, np.uint8, np.ubyte, np.uint16, + np.ushort, np.uint32, np.uintc, np.uint64, np.uintp, - np.ushort, np.ulonglong, np.float16, + np.cfloat, + np.cdouble, np.float32, + np.clongfloat, np.float64, + np.double, np.float128, np.longfloat, - np.double, np.longdouble, np.complex64, + np.singlecomplex, np.complex128, + np.complex_, np.complex256, np.longcomplex, - np.longlong, ] Numeric = Union[ int, float, complex, - np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 np.int8, np.int16, + np.short, np.int32, + np.intc, np.int64, + np.intp, + np.int_, # alias for np.compat.long, deprecated in numpy version 1.25, equals to np.int64 + np.longlong, np.uint, np.uint8, np.ubyte, np.uint16, + np.ushort, np.uint32, np.uintc, np.uint64, np.uintp, - np.ushort, np.ulonglong, np.float16, + np.cfloat, + np.cdouble, np.float32, + np.clongfloat, np.float64, + np.double, np.float128, np.longfloat, - np.double, np.longdouble, np.complex64, + np.singlecomplex, np.complex128, + np.complex_, np.complex256, np.longcomplex, - np.longlong, ] Data = Union[list, tuple, np.ndarray, Numeric] diff --git a/docs/deker/collection_schema.rst b/docs/deker/collection_schema.rst index 513dce8..037542d 100755 --- a/docs/deker/collection_schema.rst +++ b/docs/deker/collection_schema.rst @@ -484,28 +484,160 @@ Data Type --------- Deker has a strong data typing. All the values of all the ``Array`` or ``VArray`` objects in one -``Collection`` shall be of the same data type. Deker accepts numeric data of the following NumPy -data types: - - * ``numpy.int8`` - * ``numpy.int16`` - * ``numpy.int32`` - * ``numpy.int64`` - * ``numpy.float16`` - * ``numpy.float64`` - * ``numpy.float128`` - * ``numpy.longfloat`` - * ``numpy.double`` - * ``numpy.longdouble`` - * ``numpy.complex64`` - * ``numpy.complex128`` - * ``numpy.complex256`` - * ``numpy.longcomplex`` - * ``numpy.longlong`` - -Python ``int``, ``float`` and ``complex`` are also acceptable. They are correspondingly converted -to ``numpy.int32``, ``numpy.float64`` and ``numpy.complex128``. - +``Collection`` shall be of the same data type. Deker accepts numeric data of the following Python +and NumPy data types: + + .. list-table:: Integers + :align: center + :widths: 10 6 6 50 + :header-rows: 1 + + * - Type + - Bits + - Bytes + - Range + * - Python ``int`` + - 64 + - 8 + - -9223372036854775808 ... 9223372036854775807 + * - ``numpy.int8`` |br| ``numpy.byte`` + - 8 + - 1 + - -128 ... 127 + * - ``numpy.int16`` |br| ``numpy.short`` + - 16 + - 2 + - -32768 ... 32767 + * - ``numpy.int32`` |br| ``numpy.intc`` + - 32 + - 4 + - -2147483648 ... 2147483647 + * - ``numpy.int64`` |br| ``numpy.longlong`` |br| ``numpy.intp`` |br| ``numpy.int_`` + - 64 + - 8 + - -9223372036854775808 ... 9223372036854775 + + + .. list-table:: Unsigned Integers + :align: center + :widths: 10 6 6 50 + :header-rows: 1 + + * - Type + - Bits + - Bytes + - Range + * - ``numpy.uint8`` |br| ``numpy.ubyte`` + - 8 + - 1 + - 0 ... 255 + * - ``numpy.uint16`` |br| ``numpy.ushort`` + - 16 + - 2 + - 0 ... 65535 + * - ``numpy.uint32`` |br| ``numpy.uintc`` + - 32 + - 4 + - 0 ... 4294967295 + * - ``numpy.uint`` |br| ``numpy.uint64`` |br| ``numpy.uintp`` |br| ``numpy.ulonglong`` + - 64 + - 8 + - 0 ... 18446744073709551615 + + .. list-table:: Floating points + :align: center + :widths: 10 6 6 50 + :header-rows: 1 + + * - Type + - Bits + - Bytes + - Range + * - Python ``float`` + - 64 + - 8 + - -1.7976931348623157*10^308 ... |br| 1.7976931348623157*10^308 + * - ``numpy.float16`` |br| ``numpy.cfloat`` |br| ``numpy.cdouble`` + - 16 + - 2 + - -65500.0 ... 65500.0 + * - ``numpy.float32`` |br| ``numpy.clongfloat`` + - 32 + - 4 + - -3.4028235*10^38 ... 3.4028235*10^38 + * - ``numpy.float64`` |br| ``numpy.double`` + - 64 + - 8 + - -1.7976931348623157*10^308 ... |br| 1.7976931348623157*10^308 + * - ``numpy.float128`` |br| ``numpy.longfloat`` |br| ``numpy.longdouble`` + - 128 + - 16 + - -1.189731495357231765*10^4932 ... |br| 1.189731495357231765*10^4932 + + + + .. list-table:: Complex + :align: center + :widths: 10 6 6 25 + :header-rows: 1 + + * - Type + - Bits + - Bytes + - Range + * - Python ``complex`` + - 128 + - 16 + - -1.189731495357231765*10^4932-1.189731495357231765*10^4932j ... |br| + 1.189731495357231765*10^4932+1.189731495357231765*10^4932j + * - ``numpy.complex64`` |br| ``numpy.singlecomplex`` + - 64 + - 8 + - -1.7976931348623157*10^308-1.7976931348623157*10^308j ... |br| + 1.7976931348623157*10^308+1.7976931348623157*10^308j + * - ``numpy.complex128`` |br| ``numpy.complex_`` + - 128 + - 16 + - -1.189731495357231765*10^4932-1.189731495357231765*10^4932j ... |br| + 1.189731495357231765*10^4932+1.189731495357231765*10^4932j + * - ``numpy.complex256`` |br| ``numpy.longcomplex`` + - 256 + - 32 + - `even more` + + +Python ``int``, ``float`` and ``complex`` are correspondingly converted to ``numpy.int64``, +``numpy.float64`` and ``numpy.complex128``. + +.. |br| raw:: html + +
+ +**What influence is caused by a chosen data type?** + +Insofar as any data type has its own size it influences the memory: virtual and physical. +Thus, we can predict how much memory and space we will need for an array with this or that +`shape` and `dtype`. Let's say, we have an array with shape `(10, 10, 10)`:: + + np.int32 = 32 bits / 8 bits = 4 bytes + shape (10, 10, 10) * 4 b = 10 * 10 * 10 * 4 = 4000 b / 1024 b = 3.9 Kb + + np.float64 = 64 bits / 8 bits = 8 bytes + shape (10, 10, 10) * 8 b = 10 * 10 * 10 * 8 = 8000 b / 1024 b = 7.8 Kb + + np.complex128 = 128 bits / 8 bits = 16 bytes + shape (10, 10, 10) * 16 b = 10 * 10 * 10 * 16 = 16000 b / 1024 b = 15.6 Kb + + + +Also, it influences minimal and maximal values of your data. |br| For example, +the range of ``numpy.int8`` is insufficient for displaying Kelvin zero +in Celsius integer degrees, as the limit is -128 and 0°K ~= -273.15°C. + + + + +And it influences the ``fill value``. Fill Value ---------- @@ -518,10 +650,10 @@ Rules are the following: 1. ``fill_value`` **shall not be significant** for your data. 2. ``fill_value`` **is optional** - you may not provide it. In this case Deker will choose it - automatically basing on the provided ``dtype``. For ``integer`` data types it will be the lowest - value for the correspondent data type bit capacity. For example, it will be ``-128`` for - ``numpy.int8``. For ``float`` data types (including ``complex``) it will be ``numpy.nan`` as - this type is also ``floating``. + automatically basing on the provided ``dtype``. For ``integer`` and ``unsigned integer`` data + types it will be the lowest value for the correspondent data type bit capacity. For example, + it will be ``-128`` for ``numpy.int8``. For ``float`` and ``complex`` data types it will be + ``numpy.nan`` as this type is also ``floating``. 3. If you would like to set it manually, ``fill_value`` shall be of the same data type, that was passed to the ``dtype`` parameter. If all the values of the correspondent ``dtype`` are significant for you, you shall choose a data type of a greater bit capacity. For example, if all @@ -570,8 +702,8 @@ And schema of ``Collection`` of ``VArray``:: dimensions=dimensions, dtype=np.int64, fill_value=-99999, - vgrid=(50, 20) - # attributes are not passed as they are optional + vgrid=(50, 20), + attributes=None # attributes are optional ) diff --git a/docs/deker/data_access.rst b/docs/deker/data_access.rst index d3801d7..a0b6d53 100755 --- a/docs/deker/data_access.rst +++ b/docs/deker/data_access.rst @@ -2,7 +2,6 @@ Data Access *********** - Collections =========== @@ -599,3 +598,28 @@ It provides even more opportunities. Refer to ``xarray.DataArray`` API_ for deta .. _Installation: installation.html#extra-dependencies .. _Xarray: https://docs.xarray.dev/en/stable/ .. _API: https://docs.xarray.dev/en/stable/generated/xarray.DataArray.html + +Locks +====== +Deker is thread and process safe. It uses its own locks for the majority of operations. +Deker locks can be divided into two groups: +- read locks +- write locks + +*Read locks* can be shared between threads and processes with no risk of data corruption. + +*Write locks* are exclusive and are taken for the files with correspondent data content. +Only the process/thread, which has already acquired a write lock, may produce any changes +in the data. + +It means that if one process is already writing some data into a ``HDF5`` file (or into +an ``Array``) and some other processes want to read from it or to write some other data +into the same file, they will receive a ``DekerLockError``. + +.. note:: + Reading data from an ``Array``, which is locked for writing, is impossible. + +Speaking about ``VArray`` it means that several processes are able to update data +in several non-intersecting ``VSubsets``. In case if any updating ``VSubset`` intersects +with another one, the update operation will be rejected for the ``VSubset``, which met +the write lock. diff --git a/docs/deker/fine_tuning.rst b/docs/deker/fine_tuning.rst index 165ae2d..31f1c64 100755 --- a/docs/deker/fine_tuning.rst +++ b/docs/deker/fine_tuning.rst @@ -124,8 +124,8 @@ request requires too much memory or you are trying to create a ``Collection`` wi may cause a memory overflow in future, ``DekerMemoryError`` will be immediately raised. You can lower the default value by passing a certain number of ``bytes`` or by passing a human -readable representation of kilobytes, megabytes or gigabytes, for example: ``"1024K"``, ``"512M"``, -``"8G"``:: +readable representation of kilobytes, megabytes, gigabytes ot terabytes, for example: ``"1024K"``, +``"512M"``, ``"8G"``, ``"1T"``:: from deker import Client @@ -133,7 +133,7 @@ readable representation of kilobytes, megabytes or gigabytes, for example: ``"10 client = Client(uri, memory_limit=4096) # 4096 bytes Only integers are acceptable for both of bytes and human representation. Capitalization of units -suffix is ignored: ``"1024k"``, ``"512m"``, ``"8g"`` will work. +suffix is ignored: ``"1024k"``, ``"512m"``, ``"8g"``, ``"1t"`` will work. .. note:: You definitely may want to use it in **Docker**. @@ -141,7 +141,6 @@ suffix is ignored: ``"1024k"``, ``"512m"``, ``"8g"`` will work. If you set a memory limit to your container, you'd better limit Deker to the same value. Otherwise your container may be killed because of memory overflow. - HDF5 Options ============ From 753fa68454cab8d391dea4a684954ae4502b7d84 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Tue, 5 Dec 2023 20:55:22 +0200 Subject: [PATCH 08/22] np.ints max fix --- docs/deker/collection_schema.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/deker/collection_schema.rst b/docs/deker/collection_schema.rst index 037542d..6bf96db 100755 --- a/docs/deker/collection_schema.rst +++ b/docs/deker/collection_schema.rst @@ -515,7 +515,7 @@ and NumPy data types: * - ``numpy.int64`` |br| ``numpy.longlong`` |br| ``numpy.intp`` |br| ``numpy.int_`` - 64 - 8 - - -9223372036854775808 ... 9223372036854775 + - -9223372036854775808 ... 9223372036854775807 .. list-table:: Unsigned Integers From f11825d4eb94c1fd6fe1b3606bd332d31553917b Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Tue, 5 Dec 2023 21:06:31 +0200 Subject: [PATCH 09/22] locks fix --- docs/deker/data_access.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/deker/data_access.rst b/docs/deker/data_access.rst index a0b6d53..0ba9503 100755 --- a/docs/deker/data_access.rst +++ b/docs/deker/data_access.rst @@ -602,13 +602,11 @@ It provides even more opportunities. Refer to ``xarray.DataArray`` API_ for deta Locks ====== Deker is thread and process safe. It uses its own locks for the majority of operations. -Deker locks can be divided into two groups: -- read locks -- write locks +Deker locks can be divided into two groups: **read** and **write** locks -*Read locks* can be shared between threads and processes with no risk of data corruption. +**Read locks** can be shared between threads and processes with no risk of data corruption. -*Write locks* are exclusive and are taken for the files with correspondent data content. +**Write locks** are exclusive and are taken for the files with correspondent data content. Only the process/thread, which has already acquired a write lock, may produce any changes in the data. From d5eca8562277950c1499313b37d39eb721e2eaff Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Wed, 6 Dec 2023 19:06:15 +0200 Subject: [PATCH 10/22] tests for intersecting vsubsets --- deker/locks.py | 2 +- .../test_concurrency/test_in_processes.py | 167 +++++++++++++++++- 2 files changed, 163 insertions(+), 6 deletions(-) diff --git a/deker/locks.py b/deker/locks.py index 448e881..01887c3 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -294,12 +294,12 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: currently_locked = self.check_arrays_locks(arrays_positions, adapter, varray) if not currently_locked and len(self.locks) == len(arrays_positions): return + # Wait till there are no more read locks start_time = time.monotonic() while (time.monotonic() - start_time) <= adapter.ctx.config.write_lock_timeout: if not self.check_arrays_locks(arrays_positions, adapter, varray): return - sleep(adapter.ctx.config.write_lock_check_interval) # Release all locks self.release() diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index 5372394..1951583 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -6,6 +6,7 @@ correctly. """ import os +import time import traceback from multiprocessing import Event, Manager, Process, cpu_count @@ -18,12 +19,14 @@ import numpy as np import pytest +from deker_tools.slices import create_shape_from_slice, slice_converter + from tests.parameters.uri import embedded_uri from deker.arrays import Array, VArray from deker.client import Client from deker.collection import Collection -from deker.errors import DekerLockError +from deker.errors import DekerLockError, DekerVSubsetError from deker.locks import ( CollectionLock, Flock, @@ -34,7 +37,7 @@ ) from deker.schemas import ArraySchema, DimensionSchema, VArraySchema from deker.tools import get_paths -from deker.types import LocksExtensions +from deker.types import LocksExtensions, Numeric UPDATED_CUSTOM_ATTR = 20 @@ -74,6 +77,8 @@ def call_array_method( is_virtual: bool = False, primary_attributes: Dict = None, custom_attributes: Dict = None, + subset_slice: str = "[:]", + value: Numeric = 0, ): """Call a method on an Array object. @@ -87,9 +92,11 @@ def call_array_method( :param is_virtual: VArray flag :param primary_attributes: primary attributes dict :param custom_attributes: custom attributes dict + :param subset_slice: slice string from slice_converter to make a subset from array """ client = Client(uri, write_lock_timeout=1, loglevel="ERROR") collection = client.get_collection(collection_name) + subset_slice = slice_converter[subset_slice] # Get Array object if method == "create": @@ -109,6 +116,9 @@ def call_array_method( array = collection.filter({"id": id_}).last() except DekerLockError: return DekerLockError + except DekerVSubsetError: + return DekerVSubsetError + if is_virtual: lock = WriteVarrayLock schema = collection.varray_schema @@ -121,13 +131,17 @@ def call_array_method( with patch.object( lock, "release", wait_unlock(lock.release, lock_set, funcs_finished, wait) ): - array[:].update(np.zeros(shape=schema.shape)) + data = np.ndarray( + shape=create_shape_from_slice(schema.shape, subset_slice), dtype=schema.dtype + ) + data.fill(value) + array[subset_slice].update(data) elif method == "clear": with patch.object( lock, "release", wait_unlock(lock.release, lock_set, funcs_finished, wait) ): - array[:].clear() + array[subset_slice].clear() # Read used in varray only. elif method == "read": @@ -138,7 +152,7 @@ def call_array_method( wait_unlock(ReadArrayLock.release, lock_set, funcs_finished, wait), ): # patch timeout time - array[:].read() + array[subset_slice].read() elif method == "update_meta_custom_attributes": if wait: @@ -334,6 +348,149 @@ def test_varray_locks_inner_arrays( func_finished.set() except Exception: proc.kill() + raise + + def test_non_intersecting_vsubsets_update_OK( + self, inserted_varray: VArray, root_path, varray_collection: Collection + ): + """Test that as we lock varray, inner varrays also locked.""" + manager = Manager() + lock_set = manager.Event() + func_finished = manager.Event() + inserted_varray[:].clear() + value = -9999.9 + proc1 = Process( + target=call_array_method, + args=( + inserted_varray.collection, + str(embedded_uri(root_path)), + inserted_varray.id, + "update", + lock_set, + func_finished, + False, + True, + None, + None, + slice_converter[:2, :2, :2], + value, + ), + ) + proc2 = Process( + target=call_array_method, + args=( + inserted_varray.collection, + str(embedded_uri(root_path)), + inserted_varray.id, + "update", + lock_set, + func_finished, + False, + True, + None, + None, + slice_converter[8:, 8:, 8:], + value, + ), + ) + proc1.start() + proc2.start() + proc1.join() + proc2.join() + + try: + for slice_ in (np.index_exp[:2, :2, :2], np.index_exp[8:, 8:, 8:]): + subset = inserted_varray[slice_] + data = np.ndarray(shape=subset.shape, dtype=subset.dtype) + data.fill(value) + result = subset.read() + assert not proc1.is_alive() + assert not proc2.is_alive() + assert np.all(result == data) + assert not np.all(inserted_varray[:].read() == value) + except AssertionError: + raise + except Exception: + proc1.kill() + proc2.kill() + raise + finally: + print(inserted_varray[:].read(), flush=True) + + def test_intersecting_vsubsets_update_fail( + self, inserted_varray: VArray, root_path, varray_collection: Collection + ): + """Test that as we lock varray, inner varrays also locked.""" + manager = Manager() + lock_set = manager.Event() + func_finished = manager.Event() + inserted_varray[:].clear() + value = -9999.9 + slices = ( + np.index_exp[1:4, 1:2, 1:4], + np.index_exp[:2, 0:2, 0:2], + np.index_exp[3, 2, 1], + np.index_exp[:6, 0:6, 0:6], + ) + # Call read process to lock arrays for reading + proc = Process( + target=call_array_method, + args=( + inserted_varray.collection, + str(embedded_uri(root_path)), + inserted_varray.id, + "update", + lock_set, + func_finished, + True, + True, + None, + None, + slice_converter[:], + value, + ), + ) + # try: + proc.start() + # proc.join() + + lock_set.wait() + time.sleep(1) + try: + result = None + with Pool(WORKERS) as pool: + result = pool.starmap( + call_array_method, + [ + ( + inserted_varray.collection, + str(embedded_uri(root_path)), + inserted_varray.id, + "update", + lock_set, + func_finished, + False, + True, + None, + None, + slice_converter[subset_slice], + 100, + ) + for subset_slice in slices + ], + ) + print(111111111, result, flush=True) + # assert result.count(DekerLockError) == len(slices) + assert result.count(DekerVSubsetError) == len(slices) + func_finished.set() + except AssertionError: + raise + # except DekerVSubsetError: + # pass + finally: + print(inserted_varray[:].read()) + func_finished.set() + proc.kill() def test_varray_locks_release_arrays( self, From d3db463bd9384b3d270e96774196509cc3afb535 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Thu, 7 Dec 2023 13:16:13 +0200 Subject: [PATCH 11/22] Added custom attrs update in locks description --- docs/deker/data_access.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/deker/data_access.rst b/docs/deker/data_access.rst index 0ba9503..09e2774 100755 --- a/docs/deker/data_access.rst +++ b/docs/deker/data_access.rst @@ -621,3 +621,6 @@ Speaking about ``VArray`` it means that several processes are able to update dat in several non-intersecting ``VSubsets``. In case if any updating ``VSubset`` intersects with another one, the update operation will be rejected for the ``VSubset``, which met the write lock. + +Please note that operation of custom attributes updating also locks Array or VArray files +for writing. From 485052e99d71b8728bda18bd25dedc90a767bf9c Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Thu, 7 Dec 2023 15:00:47 +0200 Subject: [PATCH 12/22] intersecting subset locks test passes --- deker/subset.py | 11 ++-- .../test_concurrency/test_in_processes.py | 51 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/deker/subset.py b/deker/subset.py index ed485d2..15a4598 100644 --- a/deker/subset.py +++ b/deker/subset.py @@ -24,7 +24,7 @@ from numpy import ndarray from deker.ABC.base_subset import BaseSubset -from deker.errors import DekerArrayError, DekerVSubsetError +from deker.errors import DekerArrayError, DekerLockError, DekerVSubsetError from deker.locks import WriteVarrayLock from deker.schemas import TimeDimensionSchema from deker.tools import not_deleted @@ -631,7 +631,10 @@ def _update(array_data: ArrayPositionedData) -> None: try: list(results) except Exception as e: - raise DekerVSubsetError( - f"ATTENTION: Data in {self!s} IS NOW CORRUPTED due to the exception above" - ).with_traceback(e.__traceback__) + if isinstance(e, DekerLockError): + raise e + else: + raise DekerVSubsetError( + f"ATTENTION: Data in {self!s} IS NOW CORRUPTED due to the exception above" + ).with_traceback(e.__traceback__) self.logger.info(f"{self!s} data updated OK") diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index 1951583..f1c5bf2 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -78,7 +78,7 @@ def call_array_method( primary_attributes: Dict = None, custom_attributes: Dict = None, subset_slice: str = "[:]", - value: Numeric = 0, + fill_value: Numeric = 0, ): """Call a method on an Array object. @@ -93,6 +93,7 @@ def call_array_method( :param primary_attributes: primary attributes dict :param custom_attributes: custom attributes dict :param subset_slice: slice string from slice_converter to make a subset from array + :param fill_value: value to fill the subset """ client = Client(uri, write_lock_timeout=1, loglevel="ERROR") collection = client.get_collection(collection_name) @@ -116,8 +117,6 @@ def call_array_method( array = collection.filter({"id": id_}).last() except DekerLockError: return DekerLockError - except DekerVSubsetError: - return DekerVSubsetError if is_virtual: lock = WriteVarrayLock @@ -134,7 +133,13 @@ def call_array_method( data = np.ndarray( shape=create_shape_from_slice(schema.shape, subset_slice), dtype=schema.dtype ) - data.fill(value) + try: + if data.shape == (): + data = fill_value + else: + data.fill(fill_value) + except Exception: + raise array[subset_slice].update(data) elif method == "clear": @@ -424,13 +429,14 @@ def test_intersecting_vsubsets_update_fail( manager = Manager() lock_set = manager.Event() func_finished = manager.Event() - inserted_varray[:].clear() - value = -9999.9 + check_data = inserted_varray[:].read() + blocking_slice = np.index_exp[:4, :4, :4] + blocking_value = -9999.9 slices = ( - np.index_exp[1:4, 1:2, 1:4], - np.index_exp[:2, 0:2, 0:2], - np.index_exp[3, 2, 1], - np.index_exp[:6, 0:6, 0:6], + (np.index_exp[1:4, 1:2, 1:4], 100), + (np.index_exp[:2, 0:2, 0:2], 200), + (np.index_exp[3, 2, 1], 300), + (np.index_exp[0:6, 0:6, 0:6], 400), ) # Call read process to lock arrays for reading proc = Process( @@ -446,18 +452,14 @@ def test_intersecting_vsubsets_update_fail( True, None, None, - slice_converter[:], - value, + slice_converter[blocking_slice], + blocking_value, ), ) - # try: proc.start() - # proc.join() - lock_set.wait() - time.sleep(1) + result = None try: - result = None with Pool(WORKERS) as pool: result = pool.starmap( call_array_method, @@ -474,23 +476,22 @@ def test_intersecting_vsubsets_update_fail( None, None, slice_converter[subset_slice], - 100, + val, ) - for subset_slice in slices + for subset_slice, val in slices ], ) print(111111111, result, flush=True) - # assert result.count(DekerLockError) == len(slices) - assert result.count(DekerVSubsetError) == len(slices) + assert result.count(DekerLockError) == len(slices) func_finished.set() - except AssertionError: + except Exception: raise - # except DekerVSubsetError: - # pass finally: - print(inserted_varray[:].read()) + print() func_finished.set() proc.kill() + check_data[blocking_slice].fill(blocking_value) + assert np.all(inserted_varray[:].read() == check_data) def test_varray_locks_release_arrays( self, From 4dab4ae10cc18e19ee30ca013f179ceb201af8b0 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Thu, 7 Dec 2023 16:43:33 +0200 Subject: [PATCH 13/22] unstable test --- .../test_concurrency/test_in_processes.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index f1c5bf2..0f4a158 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -422,10 +422,10 @@ def test_non_intersecting_vsubsets_update_OK( finally: print(inserted_varray[:].read(), flush=True) - def test_intersecting_vsubsets_update_fail( - self, inserted_varray: VArray, root_path, varray_collection: Collection - ): + def test_intersecting_vsubsets_update_fail(self, root_path, varray_collection: Collection): """Test that as we lock varray, inner varrays also locked.""" + inserted_varray: VArray = varray_collection.create() + inserted_varray[:].update(np.zeros(inserted_varray.shape, inserted_varray.dtype)) manager = Manager() lock_set = manager.Event() func_finished = manager.Event() @@ -437,6 +437,7 @@ def test_intersecting_vsubsets_update_fail( (np.index_exp[:2, 0:2, 0:2], 200), (np.index_exp[3, 2, 1], 300), (np.index_exp[0:6, 0:6, 0:6], 400), + (np.index_exp[:5, 3:, :], 500), ) # Call read process to lock arrays for reading proc = Process( @@ -481,17 +482,20 @@ def test_intersecting_vsubsets_update_fail( for subset_slice, val in slices ], ) - print(111111111, result, flush=True) - assert result.count(DekerLockError) == len(slices) - func_finished.set() except Exception: raise finally: - print() func_finished.set() proc.kill() - check_data[blocking_slice].fill(blocking_value) - assert np.all(inserted_varray[:].read() == check_data) + print(111111111, result, flush=True) + try: + assert result.count(DekerLockError) == len(slices) + check_data[blocking_slice].fill(blocking_value) + assert np.all(inserted_varray[:].read() == check_data) + except Exception: + raise + finally: + inserted_varray.delete() def test_varray_locks_release_arrays( self, From 11e0f6e8dfb969ba0a5605e6f506723c6059de22 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Thu, 7 Dec 2023 17:33:46 +0200 Subject: [PATCH 14/22] unstable test, refactored --- .../test_concurrency/test_in_processes.py | 103 +++++++----------- 1 file changed, 41 insertions(+), 62 deletions(-) diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index 0f4a158..ca1fa8e 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -358,86 +358,65 @@ def test_varray_locks_inner_arrays( def test_non_intersecting_vsubsets_update_OK( self, inserted_varray: VArray, root_path, varray_collection: Collection ): - """Test that as we lock varray, inner varrays also locked.""" + """Test varray allows writing into non-intersecting subsets.""" manager = Manager() lock_set = manager.Event() func_finished = manager.Event() - inserted_varray[:].clear() value = -9999.9 - proc1 = Process( - target=call_array_method, - args=( - inserted_varray.collection, - str(embedded_uri(root_path)), - inserted_varray.id, - "update", - lock_set, - func_finished, - False, - True, - None, - None, - slice_converter[:2, :2, :2], - value, - ), - ) - proc2 = Process( - target=call_array_method, - args=( - inserted_varray.collection, - str(embedded_uri(root_path)), - inserted_varray.id, - "update", - lock_set, - func_finished, - False, - True, - None, - None, - slice_converter[8:, 8:, 8:], - value, - ), - ) - proc1.start() - proc2.start() - proc1.join() - proc2.join() + slices = (np.index_exp[:2, :2, :2], np.index_exp[8:, 8:, 8:]) + with Pool(WORKERS) as pool: + pool.starmap( + call_array_method, + [ + ( + inserted_varray.collection, + str(embedded_uri(root_path)), + inserted_varray.id, + "update", + lock_set, + func_finished, + False, + True, + None, + None, + slice_converter[subset_slice], + value, + ) + for subset_slice in slices + ], + ) try: - for slice_ in (np.index_exp[:2, :2, :2], np.index_exp[8:, 8:, 8:]): + for slice_ in slices: subset = inserted_varray[slice_] data = np.ndarray(shape=subset.shape, dtype=subset.dtype) data.fill(value) result = subset.read() - assert not proc1.is_alive() - assert not proc2.is_alive() assert np.all(result == data) - assert not np.all(inserted_varray[:].read() == value) - except AssertionError: - raise + assert np.all(inserted_varray[2:8].read() != value) except Exception: - proc1.kill() - proc2.kill() raise - finally: - print(inserted_varray[:].read(), flush=True) + # finally: + # print(inserted_varray[:].read(), flush=True) - def test_intersecting_vsubsets_update_fail(self, root_path, varray_collection: Collection): - """Test that as we lock varray, inner varrays also locked.""" - inserted_varray: VArray = varray_collection.create() - inserted_varray[:].update(np.zeros(inserted_varray.shape, inserted_varray.dtype)) + def test_intersecting_vsubsets_update_fail( + self, inserted_varray: VArray, root_path, varray_collection: Collection + ): + """Test VArray not allows writing into intersecting subsets.""" + inserted_varray[:].update(np.ones(shape=inserted_varray.shape, dtype=inserted_varray.dtype)) + check_data = inserted_varray[:].read() manager = Manager() lock_set = manager.Event() func_finished = manager.Event() - check_data = inserted_varray[:].read() blocking_slice = np.index_exp[:4, :4, :4] blocking_value = -9999.9 slices = ( - (np.index_exp[1:4, 1:2, 1:4], 100), - (np.index_exp[:2, 0:2, 0:2], 200), - (np.index_exp[3, 2, 1], 300), - (np.index_exp[0:6, 0:6, 0:6], 400), - (np.index_exp[:5, 3:, :], 500), + (np.index_exp[0:2, 1:3, 2:4], 100), # shall be blocked + (np.index_exp[2:3, 0:2, 0], 200), # shall be blocked + (np.index_exp[3, 2, 1], 300), # shall be blocked + (np.index_exp[0:6, 0:6, 0:6], 400), # shall be blocked + (np.index_exp[:5, 3:, :], 500), # shall be blocked + (np.index_exp[8:, 8:, 8:], blocking_value), # shall proceed as non-locked ) # Call read process to lock arrays for reading proc = Process( @@ -489,8 +468,9 @@ def test_intersecting_vsubsets_update_fail(self, root_path, varray_collection: C proc.kill() print(111111111, result, flush=True) try: - assert result.count(DekerLockError) == len(slices) + assert result.count(DekerLockError) == len(slices) - 1 check_data[blocking_slice].fill(blocking_value) + check_data[8:, 8:, 8:].fill(blocking_value) assert np.all(inserted_varray[:].read() == check_data) except Exception: raise @@ -507,7 +487,6 @@ def test_varray_locks_release_arrays( """Test that varray lock release all flocks and delete varraylock""" # Check that sequential update are fine inserted_varray[:].update(np.zeros(shape=varray_collection.varray_schema.shape)) - inserted_varray[:].update(np.zeros(shape=varray_collection.varray_schema.shape)) # Check that there is no flocks or extra files. locks = [] From b14d7a7cd1a4cfbe8863305bbb8049f585a9a39a Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Sat, 9 Dec 2023 14:33:57 +0200 Subject: [PATCH 15/22] byte alias added --- deker/types/private/typings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deker/types/private/typings.py b/deker/types/private/typings.py index 728a718..090b7e1 100644 --- a/deker/types/private/typings.py +++ b/deker/types/private/typings.py @@ -50,6 +50,7 @@ float, complex, np.int8, + np.byte, np.int16, np.short, np.int32, @@ -91,6 +92,7 @@ float, complex, np.int8, + np.byte, np.int16, np.short, np.int32, From e3230cb13c8e44fb74e7159bac29f6df38796af0 Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Mon, 18 Dec 2023 10:56:17 +0100 Subject: [PATCH 16/22] Fixed Locks behaviour. - Fixed WriteVarrayLock - Fixed CreateArrayLock - Fixed related tests --- deker/locks.py | 71 ++++++++++++++----- .../test_concurrency/test_in_processes.py | 41 +++++++---- 2 files changed, 80 insertions(+), 32 deletions(-) diff --git a/deker/locks.py b/deker/locks.py index 01887c3..c822d44 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -23,7 +23,7 @@ from pathlib import Path from threading import get_native_id from time import sleep -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Union, Tuple from uuid import uuid4 from deker.ABC.base_locks import BaseLock @@ -94,7 +94,14 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: dir_path = get_main_path(id_, self.instance.collection_path / self.instance.data_dir) path = dir_path / (id_ + self.instance.file_ext) - + for file in dir_path.iterdir(): + # Skip lock from current process. + if file.name.endswith(f"{os.getpid()}{LocksExtensions.varray_lock.value}"): + self.is_locked_with_varray = True + return + # If we've found another varray lock, that not from current process. + if file.name.endswith(LocksExtensions.varray_lock.value): # type: ignore + raise DekerLockError(f"Array {array} is locked with {file.name}") try: with open(path, "r") as f: fcntl.flock(f, fcntl.LOCK_SH | fcntl.LOCK_NB) @@ -129,6 +136,8 @@ class WriteArrayLock(BaseLock): ALLOWED_TYPES = ["LocalArrayAdapter"] + is_locked_with_varray: bool = False + def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: """Get path to the file for locking. @@ -147,9 +156,6 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: :param func_args: arguments of method call :param func_kwargs: keyword arguments of method call """ - # Increment write lock, to prevent more read locks coming. - self.acquire(self.get_path(func_args, func_kwargs)) - # Check current read locks array = func_kwargs.get("array") or func_args[1] # zero arg is 'self' dir_path = get_main_path(array.id, self.instance.collection_path / self.instance.data_dir) @@ -159,11 +165,15 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: for file in dir_path.iterdir(): # Skip lock from current process. if file.name.endswith(f"{os.getpid()}{LocksExtensions.varray_lock.value}"): - continue + self.is_locked_with_varray = True + return # If we've found another varray lock, that not from current process. if file.name.endswith(LocksExtensions.varray_lock.value): # type: ignore raise DekerLockError(f"Array {array} is locked with {file.name}") + # Increment write lock, to prevent more read locks coming. + self.acquire(self.get_path(func_args, func_kwargs)) + # Pattern that has to find any read locks glob_pattern = f"{array.id}:*{LocksExtensions.array_read_lock.value}" @@ -179,6 +189,17 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: self.release() raise DekerLockError(f"Array {array} is locked with read locks") + def release(self, e: Optional[Exception] = None) -> None: + if self.is_locked_with_varray: + return + + super().release(e) + + def acquire(self, path: Optional[Path]) -> None: + if self.is_locked_with_varray: + return + super().acquire(path) + class WriteVarrayLock(BaseLock): """Write lock for VArrays. @@ -192,7 +213,7 @@ class WriteVarrayLock(BaseLock): ALLOWED_TYPES = ["VSubset"] # Locks that have been acquired by varray - locks: List[Path] = [] + locks: List[Tuple[Flock, Path]] = [] skip_lock: bool = False # shows that we must skip this lock (e.g server adapters for subset) def check_type(self) -> None: @@ -228,9 +249,9 @@ def check_locks_for_array_and_set_flock(self, filename: Path) -> Flock: """ # Check read lock first array_id = filename.name.split(".")[0] - glob_pattern = f"{array_id}:*{LocksExtensions.array_read_lock.value}" + glob_pattern = f"{array_id}:*" for _ in filename.parent.rglob(glob_pattern): - raise DekerLockError(f"Array {array_id} is locked on read") + raise DekerLockError(f"Array {array_id} is locked") # Check write lock and set it lock = Flock(filename) @@ -267,8 +288,8 @@ def check_arrays_locks( # Path to the main file (not symlink) filename = filename.resolve() try: - self.check_locks_for_array_and_set_flock(filename) - self.locks.append(filename) + lock = self.check_locks_for_array_and_set_flock(filename) + self.locks.append((lock, filename)) except DekerLockError: currently_locked.append(filename) @@ -292,7 +313,8 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: # Iterate over Arrays in VArray and try to lock them. If locking fails - wait. # If it fails again - release all locks. currently_locked = self.check_arrays_locks(arrays_positions, adapter, varray) - if not currently_locked and len(self.locks) == len(arrays_positions): + if not currently_locked and (len(self.locks) == len(arrays_positions)): + # Release array locks return # Wait till there are no more read locks @@ -311,9 +333,11 @@ def release(self, e: Optional[Exception] = None) -> None: # noqa[ARG002] :param e: Exception that may have been raised. """ # Release array locks - for lock in self.locks: - Flock(lock).release() - Path(f"{lock}:{os.getpid()}{LocksExtensions.varray_lock.value}").unlink(missing_ok=True) + for lock, filename in self.locks: + lock.release() + Path(f"{filename}:{os.getpid()}{LocksExtensions.varray_lock.value}").unlink( + missing_ok=True + ) super().release() def acquire(self, path: Optional[Path]) -> None: @@ -346,7 +370,8 @@ class CreateArrayLock(BaseLock): """Lock that we set when we want to create an array.""" ALLOWED_TYPES = ["LocalArrayAdapter", "LocalVArrayAdapter"] - + + path: Optional[Path] = None def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: """Return path to the file that should be locked. @@ -357,7 +382,7 @@ def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: array = func_kwargs.get("array") or func_args[1] # zero arg is 'self' # Get file directory path - dir_path = get_main_path(array.id, self.instance.collection_path / self.instance.data_dir) + dir_path = self.instance.collection_path filename = META_DIVIDER.join( [ f"{array.id}", @@ -366,8 +391,12 @@ def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: f"{get_native_id()}", ] ) - # Create read lock file + # Create lock file path = dir_path / f"{filename}{LocksExtensions.array_lock.value}" + if not path.exists(): + path.open("w").close() + + self.path = path self.logger.debug(f"got path for array.id {array.id} lock file: {path}") return path @@ -390,7 +419,7 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: array_type = Array if adapter == self.ALLOWED_TYPES[0] else VArray array = array_type(**array) - dir_path = get_main_path(array.id, self.instance.collection_path / self.instance.data_dir) + dir_path = self.instance.collection_path # Pattern that has to find any create locks glob_pattern = f"{array.id}:*{LocksExtensions.array_lock.value}" @@ -414,6 +443,10 @@ def get_result(self, func: Callable, args: Any, kwargs: Any) -> Any: else: result = func(*args, **kwargs) return result + + def release(self, e: Optional[Exception] = None) -> None: + self.path.unlink(missing_ok=True) + super().release(e) class UpdateMetaAttributeLock(BaseLock): diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index ca1fa8e..b70ba6b 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -12,8 +12,10 @@ from multiprocessing import Event, Manager, Process, cpu_count from multiprocessing.pool import Pool from pathlib import Path +from threading import get_native_id from typing import Callable, Dict, Literal from unittest.mock import patch +from uuid import uuid4 import h5py import numpy as np @@ -131,7 +133,8 @@ def call_array_method( lock, "release", wait_unlock(lock.release, lock_set, funcs_finished, wait) ): data = np.ndarray( - shape=create_shape_from_slice(schema.shape, subset_slice), dtype=schema.dtype + shape=create_shape_from_slice(schema.shape, subset_slice), + dtype=schema.dtype, ) try: if data.shape == (): @@ -325,7 +328,7 @@ def test_varray_lock_wait_till_read_timeout( def test_varray_locks_inner_arrays( self, inserted_varray: VArray, root_path, varray_collection: Collection ): - """Test that as we lock varray, inner varrays also locked.""" + """Test that as we lock varray, inner arrays also locked.""" manager = Manager() lock_set = manager.Event() func_finished = manager.Event() @@ -346,14 +349,10 @@ def test_varray_locks_inner_arrays( ) proc.start() lock_set.wait() - try: - for array in varray_collection.arrays: - with pytest.raises(DekerLockError): - array[:].update(np.zeros(shape=varray_collection.array_schema.shape)) - func_finished.set() - except Exception: - proc.kill() - raise + with pytest.raises(DekerLockError): + for _ in varray_collection.arrays: + pass + func_finished.set() def test_non_intersecting_vsubsets_update_OK( self, inserted_varray: VArray, root_path, varray_collection: Collection @@ -465,8 +464,6 @@ def test_intersecting_vsubsets_update_fail( raise finally: func_finished.set() - proc.kill() - print(111111111, result, flush=True) try: assert result.count(DekerLockError) == len(slices) - 1 check_data[blocking_slice].fill(blocking_value) @@ -659,10 +656,27 @@ def test_array_with_attributes_create_multiple_processes( manager = Manager() lock_set = manager.Event() func_finished = manager.Event() + proc = Process( + target=call_array_method, + args=( + array_with_attributes.collection, + str(embedded_uri(root_path)), + array_with_attributes.id, + "create", + lock_set, + func_finished, + True, + False, + array_with_attributes.primary_attributes, + array_with_attributes.custom_attributes, + ), + ) + proc.start() + lock_set.wait() methods = ["create"] * 3 with Pool(WORKERS - 1) as pool: - pool.starmap( + result = pool.starmap( call_array_method, [ ( @@ -681,6 +695,7 @@ def test_array_with_attributes_create_multiple_processes( ], ) lock_set.wait() + assert result.count(DekerLockError) == len(methods) func_finished.set() paths = get_paths( From 11e500960ff104cc8033ce58f17e6c51f93b2b0f Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Mon, 18 Dec 2023 10:57:10 +0100 Subject: [PATCH 17/22] Fixed Locks behaviour. - Fixed WriteVarrayLock - Fixed CreateArrayLock - Fixed related tests --- deker/locks.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/deker/locks.py b/deker/locks.py index c822d44..3df05ce 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -370,8 +370,9 @@ class CreateArrayLock(BaseLock): """Lock that we set when we want to create an array.""" ALLOWED_TYPES = ["LocalArrayAdapter", "LocalVArrayAdapter"] - - path: Optional[Path] = None + + path: Optional[Path] = None + def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: """Return path to the file that should be locked. @@ -395,7 +396,7 @@ def get_path(self, func_args: Sequence, func_kwargs: Dict) -> Path: path = dir_path / f"{filename}{LocksExtensions.array_lock.value}" if not path.exists(): path.open("w").close() - + self.path = path self.logger.debug(f"got path for array.id {array.id} lock file: {path}") return path @@ -443,7 +444,7 @@ def get_result(self, func: Callable, args: Any, kwargs: Any) -> Any: else: result = func(*args, **kwargs) return result - + def release(self, e: Optional[Exception] = None) -> None: self.path.unlink(missing_ok=True) super().release(e) From b9dd3922d52aeab40c4865e2c434df1eceb68a0d Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Mon, 18 Dec 2023 11:11:15 +0100 Subject: [PATCH 18/22] Linters --- deker/locks.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/deker/locks.py b/deker/locks.py index 3df05ce..1a789bf 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -190,12 +190,22 @@ def check_existing_lock(self, func_args: Sequence, func_kwargs: Dict) -> None: raise DekerLockError(f"Array {array} is locked with read locks") def release(self, e: Optional[Exception] = None) -> None: + """Release Flock. + + If array is locked from Varary from current Process, do nothing + :param e: exception that might have been raised + """ if self.is_locked_with_varray: return super().release(e) def acquire(self, path: Optional[Path]) -> None: + """Make lock using flock. + + If array is locked from Varary from current Process, do nothing + :param path: Path to file that should be flocked + """ if self.is_locked_with_varray: return super().acquire(path) From 64acb85842e687dc4e2fa8b500f14e7b832c2b23 Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Mon, 18 Dec 2023 13:41:59 +0100 Subject: [PATCH 19/22] Linters & Create Tests --- deker/locks.py | 4 ++++ tests/test_cases/test_concurrency/test_in_processes.py | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/deker/locks.py b/deker/locks.py index 1a789bf..ac1053a 100644 --- a/deker/locks.py +++ b/deker/locks.py @@ -456,6 +456,10 @@ def get_result(self, func: Callable, args: Any, kwargs: Any) -> Any: return result def release(self, e: Optional[Exception] = None) -> None: + """Release Flock. + + :param e: exception that might have been raised + """ self.path.unlink(missing_ok=True) super().release(e) diff --git a/tests/test_cases/test_concurrency/test_in_processes.py b/tests/test_cases/test_concurrency/test_in_processes.py index b70ba6b..ccb0e5b 100644 --- a/tests/test_cases/test_concurrency/test_in_processes.py +++ b/tests/test_cases/test_concurrency/test_in_processes.py @@ -36,6 +36,7 @@ UpdateMetaAttributeLock, WriteArrayLock, WriteVarrayLock, + CreateArrayLock, ) from deker.schemas import ArraySchema, DimensionSchema, VArraySchema from deker.tools import get_paths @@ -104,7 +105,9 @@ def call_array_method( # Get Array object if method == "create": with patch.object( - Flock, "release", wait_unlock(Flock.release, lock_set, funcs_finished, wait) + CreateArrayLock, + "release", + wait_unlock(CreateArrayLock.release, lock_set, funcs_finished, wait), ): with patch("deker.ABC.base_array.get_id", lambda *a: id_): try: From 1aca1cf69e84d09e23e4b83b771806c1d155a0d1 Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Thu, 28 Dec 2023 15:06:58 +0100 Subject: [PATCH 20/22] updated versions of adapters --- poetry.lock | 190 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 95 insertions(+), 97 deletions(-) diff --git a/poetry.lock b/poetry.lock index fed1984..6748a90 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -13,19 +13,20 @@ files = [ [[package]] name = "anyio" -version = "4.1.0" +version = "4.2.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = true python-versions = ">=3.8" files = [ - {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, - {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, + {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, + {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] @@ -113,18 +114,15 @@ Sphinx = ">=2.2,<8.0" [[package]] name = "babel" -version = "2.13.1" +version = "2.14.0" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, - {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] -[package.dependencies] -setuptools = {version = "*", markers = "python_version >= \"3.12\""} - [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -497,16 +495,16 @@ optimize = ["orjson"] [[package]] name = "deker-local-adapters" -version = "1.0.1" +version = "1.1.0" description = "Plugin with local adapters for deker" optional = false python-versions = ">=3.9,<4.0" files = [ - {file = "deker_local_adapters-1.0.1.tar.gz", hash = "sha256:d7ed69c122a132e79b557e96fdaccd554e57eacaa2feb42ac1f9a064905023c1"}, + {file = "deker_local_adapters-1.1.0.tar.gz", hash = "sha256:ddbc9197f687a6f2121471fb2a60bd951b37e331bce76471b1726cbe6c4e39b3"}, ] [package.dependencies] -deker-tools = "1.0.0" +deker-tools = ">=1.0.0,<2.0.0" h5py = ">=3.8.0,<4.0.0" hdf5plugin = ">=4.0.1,<5.0.0" numpy = ">=1.18,<2.0" @@ -539,16 +537,16 @@ ptpython = "3.0.23" [[package]] name = "deker-tools" -version = "1.0.0" -description = "Interactive shell for Deker" +version = "1.1.0" +description = "Shared functions library for Deker components" optional = false -python-versions = ">=3.9" +python-versions = ">=3.9,<4.0" files = [ - {file = "deker_tools-1.0.0.tar.gz", hash = "sha256:6c07be35db122c1dfc6da2239b468b40ce232a994c17b1aabcd11a576aa615ee"}, + {file = "deker_tools-1.1.0.tar.gz", hash = "sha256:617d8e404e96022ca1ccb529998605c738716b6049ddfab50d0f29ced57dd5a6"}, ] [package.dependencies] -numpy = ">=1.18" +numpy = ">=1.18,<2.0" [[package]] name = "dict2css" @@ -567,13 +565,13 @@ domdf-python-tools = ">=2.2.0" [[package]] name = "distlib" -version = "0.3.7" +version = "0.3.8" 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"}, + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] @@ -606,13 +604,13 @@ files = [ [[package]] name = "domdf-python-tools" -version = "3.7.0" +version = "3.8.0.post2" description = "Helpful functions for Python 🐍 🛠️" optional = false python-versions = ">=3.6" files = [ - {file = "domdf_python_tools-3.7.0-py3-none-any.whl", hash = "sha256:7b4d1c3bdb7402b872d43953824bf921ae2e52f893adbe5c0052a21a6efa2fe4"}, - {file = "domdf_python_tools-3.7.0.tar.gz", hash = "sha256:df1af9a91649af0fb2a4e7b3a4b0a0936e4f78389dd7280dd6fd2f53a339ca71"}, + {file = "domdf_python_tools-3.8.0.post2-py3-none-any.whl", hash = "sha256:ad2c763c8d00850a7fa92ad95e9891a1918281ea25322c4dbb1734fd32f905dd"}, + {file = "domdf_python_tools-3.8.0.post2.tar.gz", hash = "sha256:a1fd255ea29f767b08de462d2da39d360262304389227d980bc307ee8aa3366a"}, ] [package.dependencies] @@ -983,13 +981,13 @@ files = [ [[package]] name = "identify" -version = "2.5.32" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"}, - {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] @@ -1019,13 +1017,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.0.0" +version = "7.0.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, - {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] [package.dependencies] @@ -1501,36 +1499,36 @@ files = [ [[package]] name = "pandas" -version = "2.1.3" +version = "2.1.4" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" files = [ - {file = "pandas-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f"}, - {file = "pandas-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb"}, - {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb"}, - {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4"}, - {file = "pandas-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03"}, - {file = "pandas-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e"}, - {file = "pandas-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82"}, - {file = "pandas-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042"}, - {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef"}, - {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58"}, - {file = "pandas-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2"}, - {file = "pandas-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f"}, - {file = "pandas-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140"}, - {file = "pandas-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d"}, - {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e"}, - {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683"}, - {file = "pandas-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00"}, - {file = "pandas-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549"}, - {file = "pandas-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8"}, - {file = "pandas-2.1.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d"}, - {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a"}, - {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2"}, - {file = "pandas-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a"}, - {file = "pandas-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71"}, - {file = "pandas-2.1.3.tar.gz", hash = "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f"}, + {file = "pandas-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdec823dc6ec53f7a6339a0e34c68b144a7a1fd28d80c260534c39c62c5bf8c9"}, + {file = "pandas-2.1.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:294d96cfaf28d688f30c918a765ea2ae2e0e71d3536754f4b6de0ea4a496d034"}, + {file = "pandas-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b728fb8deba8905b319f96447a27033969f3ea1fea09d07d296c9030ab2ed1d"}, + {file = "pandas-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00028e6737c594feac3c2df15636d73ace46b8314d236100b57ed7e4b9ebe8d9"}, + {file = "pandas-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:426dc0f1b187523c4db06f96fb5c8d1a845e259c99bda74f7de97bd8a3bb3139"}, + {file = "pandas-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:f237e6ca6421265643608813ce9793610ad09b40154a3344a088159590469e46"}, + {file = "pandas-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b7d852d16c270e4331f6f59b3e9aa23f935f5c4b0ed2d0bc77637a8890a5d092"}, + {file = "pandas-2.1.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7d5f2f54f78164b3d7a40f33bf79a74cdee72c31affec86bfcabe7e0789821"}, + {file = "pandas-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aa6e92e639da0d6e2017d9ccff563222f4eb31e4b2c3cf32a2a392fc3103c0d"}, + {file = "pandas-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d797591b6846b9db79e65dc2d0d48e61f7db8d10b2a9480b4e3faaddc421a171"}, + {file = "pandas-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2d3e7b00f703aea3945995ee63375c61b2e6aa5aa7871c5d622870e5e137623"}, + {file = "pandas-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:dc9bf7ade01143cddc0074aa6995edd05323974e6e40d9dbde081021ded8510e"}, + {file = "pandas-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:482d5076e1791777e1571f2e2d789e940dedd927325cc3cb6d0800c6304082f6"}, + {file = "pandas-2.1.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8a706cfe7955c4ca59af8c7a0517370eafbd98593155b48f10f9811da440248b"}, + {file = "pandas-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0513a132a15977b4a5b89aabd304647919bc2169eac4c8536afb29c07c23540"}, + {file = "pandas-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9f17f2b6fc076b2a0078862547595d66244db0f41bf79fc5f64a5c4d635bead"}, + {file = "pandas-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:45d63d2a9b1b37fa6c84a68ba2422dc9ed018bdaa668c7f47566a01188ceeec1"}, + {file = "pandas-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:f69b0c9bb174a2342818d3e2778584e18c740d56857fc5cdb944ec8bbe4082cf"}, + {file = "pandas-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3f06bda01a143020bad20f7a85dd5f4a1600112145f126bc9e3e42077c24ef34"}, + {file = "pandas-2.1.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab5796839eb1fd62a39eec2916d3e979ec3130509930fea17fe6f81e18108f6a"}, + {file = "pandas-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edbaf9e8d3a63a9276d707b4d25930a262341bca9874fcb22eff5e3da5394732"}, + {file = "pandas-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ebfd771110b50055712b3b711b51bee5d50135429364d0498e1213a7adc2be8"}, + {file = "pandas-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8ea107e0be2aba1da619cc6ba3f999b2bfc9669a83554b1904ce3dd9507f0860"}, + {file = "pandas-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:d65148b14788b3758daf57bf42725caa536575da2b64df9964c563b015230984"}, + {file = "pandas-2.1.4.tar.gz", hash = "sha256:fcb68203c833cc735321512e13861358079a96c174a61f5116a1de89c58c0ef7"}, ] [package.dependencies] @@ -1620,13 +1618,13 @@ flake8 = ">=5.0.0" [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, - {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -1668,13 +1666,13 @@ virtualenv = ">=20.10.0" [[package]] name = "prompt-toolkit" -version = "3.0.41" +version = "3.0.43" description = "Library for building powerful interactive command lines in Python" optional = true python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, - {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, + {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, + {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, ] [package.dependencies] @@ -1682,27 +1680,27 @@ wcwidth = "*" [[package]] name = "psutil" -version = "5.9.6" +version = "5.9.7" 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.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, - {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, - {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, - {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, - {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, - {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, - {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, - {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, - {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, - {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, + {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"}, + {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"}, + {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"}, + {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"}, + {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"}, + {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"}, + {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"}, + {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"}, + {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"}, + {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"}, ] [package.extras] @@ -2042,24 +2040,24 @@ python-versions = ">=3.6" files = [ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d92f81886165cb14d7b067ef37e142256f1c6a90a65cd156b063a43da1708cfd"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b5edda50e5e9e15e54a6a8a0070302b00c518a9d32accc2346ad6c984aacd279"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:7048c338b6c86627afb27faecf418768acb6331fc24cfa56c93e8c9780f815fa"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, @@ -2067,7 +2065,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3fcc54cb0c8b811ff66082de1680b4b14cf8a81dce0d4fbf665c2265a81e07a1"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, @@ -2075,7 +2073,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:665f58bfd29b167039f714c6998178d27ccd83984084c286110ef26b230f259f"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, @@ -2083,7 +2081,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9eb5dee2772b0f704ca2e45b1713e4e5198c18f515b52743576d196348f374d3"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, @@ -2094,13 +2092,13 @@ files = [ [[package]] name = "setuptools" -version = "69.0.2" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, - {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] @@ -2557,13 +2555,13 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6. [[package]] name = "typing-extensions" -version = "4.8.0" +version = "4.9.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, ] [[package]] @@ -2652,13 +2650,13 @@ files = [ [[package]] name = "xarray" -version = "2023.11.0" +version = "2023.12.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.9" files = [ - {file = "xarray-2023.11.0-py3-none-any.whl", hash = "sha256:933b5101e965120ed58e29525667ab34aafcea1886c236ade72a34d7bb465d9c"}, - {file = "xarray-2023.11.0.tar.gz", hash = "sha256:9a45e10741844b5f948d8e1e768b460df7e90696d18e2eff2c1d47f5d9d50252"}, + {file = "xarray-2023.12.0-py3-none-any.whl", hash = "sha256:3c22b6824681762b6c3fcad86dfd18960a617bccbc7f456ce21b43a20e455fb9"}, + {file = "xarray-2023.12.0.tar.gz", hash = "sha256:4565dbc890de47e278346c44d6b33bb07d3427383e077a7ca8ab6606196fd433"}, ] [package.dependencies] @@ -2697,4 +2695,4 @@ xarray = ["xarray"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "781700cf044b82b6b8f87a5ef23d52616769544227a988ac9eff254d47802e93" +content-hash = "d5be6ceef0a2525bbc779fe5809b7f395ee33a4628abb5e43e8564fba7b7c651" diff --git a/pyproject.toml b/pyproject.toml index 7dda499..af0aa8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ attrs = "^23.1.0" typing-extensions = "^4.4.0" tqdm = "^4.64.1" psutil = "^5.9.5" -deker-local-adapters = "1.0.1" +deker-local-adapters = "^1.0.1" deker-server-adapters = {version = "^1.0.0", optional = true} deker-shell = { version = "^1.0.0", optional = true } xarray = {version = "^2023.5.0", optional = true} From 3e61df8dc27d97b1a49f04c639ca49d89a46954f Mon Sep 17 00:00:00 2001 From: matveyvarg Date: Fri, 29 Dec 2023 11:12:50 +0100 Subject: [PATCH 21/22] logger --- deker/client.py | 4 +++- deker/log.py | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/deker/client.py b/deker/client.py index 06c6897..6924f38 100644 --- a/deker/client.py +++ b/deker/client.py @@ -28,6 +28,7 @@ from deker_tools.data import convert_size_to_human from deker_tools.path import is_path_valid +from deker_tools.log import set_logger from psutil import swap_memory, virtual_memory from tqdm import tqdm @@ -42,7 +43,7 @@ ) from deker.integrity import IntegrityChecker from deker.locks import META_DIVIDER -from deker.log import SelfLoggerMixin, set_logging_level +from deker.log import SelfLoggerMixin, set_logging_level, format_string from deker.schemas import ArraySchema, VArraySchema from deker.tools import convert_human_memory_to_bytes from deker.types import ArrayLockMeta, CollectionLockMeta, LocksExtensions, LocksTypes, StorageSize @@ -212,6 +213,7 @@ def __init__( :param kwargs: a wildcard, reserved for any extra parameters """ try: + set_logger(format_string) set_logging_level(loglevel.upper()) self.__get_plugins() total_available_mem = virtual_memory().total + swap_memory().total diff --git a/deker/log.py b/deker/log.py index 5c00469..bd18745 100644 --- a/deker/log.py +++ b/deker/log.py @@ -19,13 +19,15 @@ from logging import Logger - _ROOT_DEKER_LOGGER_NAME = "Deker" _level = os.getenv("DEKER_LOGLEVEL", "WARNING") -_format = "%(name)s %(levelname)-4s [%(asctime)s] %(message)s" + +format_string = "%(levelname)s | %(asctime)s | %(name)s | %(message)s" +fmter = logging.Formatter(fmt=format_string) + _logger = logging.getLogger(_ROOT_DEKER_LOGGER_NAME) _handler = logging.StreamHandler() -_handler.setFormatter(logging.Formatter(fmt=_format)) +_handler.setFormatter(fmter) _logger.addHandler(_handler) From dc6b551baf85f684e478f21a91c12ab9f3b5cf91 Mon Sep 17 00:00:00 2001 From: Sergey Rybakov Date: Fri, 29 Dec 2023 16:40:16 +0200 Subject: [PATCH 22/22] trademark --- README.md | 26 +++++++-------- docs/deker/api/modules.rst | 4 +-- docs/deker/collection_schema.rst | 50 ++++++++++++++--------------- docs/deker/connecting_to_server.rst | 15 +++++---- docs/deker/data_access.rst | 8 ++--- docs/deker/fine_tuning.rst | 43 +++++++++++++------------ docs/deker/installation.rst | 44 ++++++++++++------------- docs/deker/shell.rst | 10 +++--- docs/deker/tools.rst | 14 ++++---- docs/index.rst | 33 ++++++++++--------- 10 files changed, 125 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 48abfa6..5df2f4e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Deker +# DEKER™ ![image](docs/deker/images/logo_50.png) @@ -8,22 +8,22 @@ [![codecov](https://codecov.io/gh/openweathermap/deker/branch/main/graph/badge.svg?token=Z040BQWIOR)](https://codecov.io/gh/openweathermap/deker) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -Deker is pure Python implementation of petabyte-scale highly parallel data storage engine for +DEKER™ is pure Python implementation of petabyte-scale highly parallel data storage engine for multidimensional arrays. -Deker name comes from term *dekeract*, the [10-cube](https://en.wikipedia.org/wiki/10-cube). +DEKER™ name comes from term *dekeract*, the [10-cube](https://en.wikipedia.org/wiki/10-cube). -Deker was made with the following major goals in mind: +DEKER™ was made with the following major goals in mind: * provide intuitive interface for storing and accessing **huge data arrays** * support **arbitrary number of data dimensions** * be **thread and process safe** and as **lean on RAM** use as possible -Deker empowers users to store and access a wide range of data types, virtually anything that can be +DEKER™ empowers users to store and access a wide range of data types, virtually anything that can be represented as arrays, like **geospacial data**, **satellite images**, **machine learning models**, **sensors data**, graphs, key-value pairs, tabular data, and more. -Deker does not limit your data complexity and size: it supports virtually unlimited number of data +DEKER™ does not limit your data complexity and size: it supports virtually unlimited number of data dimensions and provides under the hood mechanisms to **partition** huge amounts of data for **scalability**. @@ -40,7 +40,7 @@ dimensions and provides under the hood mechanisms to **partition** huge amounts ## Code and Documentation -Open source implementation of Deker storage engine is published at +Open source implementation of DEKER™ storage engine is published at * https://github.com/openweathermap/deker @@ -52,9 +52,9 @@ API documentation and tutorials for the current release could be found at ### Dependencies -Minimal Python version for Deker is 3.9. +Minimal Python version for DEKER™ is 3.9. -Deker depends on the following third-party packages: +DEKER™ depends on the following third-party packages: * `numpy` >= 1.18 * `attrs` >= 23.1.0 @@ -63,7 +63,7 @@ Deker depends on the following third-party packages: * `h5py` >= 3.8.0 * `hdf5plugin` >= 4.0.1 -Also please not that for flexibility few internal Deker components are published as separate +Also please not that for flexibility few internal DEKER™ components are published as separate packages: * [`deker-local-adapters`](https://github.com/openweathermap/deker-local-adapters) @@ -72,17 +72,17 @@ packages: ### Install -To install Deker run: +To install DEKER™ run: ```bash pip install deker ``` Please refer to documentation for advanced topics such as running on Apple silicone or using Xarray -with Deker API. +with DEKER™ API. ### First Steps -Now you can write simple script to jump into Deker development: +Now you can write simple script to jump into DEKER™ development: ```python from deker import Client, ArraySchema, DimensionSchema, TimeDimensionSchema diff --git a/docs/deker/api/modules.rst b/docs/deker/api/modules.rst index b9c5fa8..d1594bf 100755 --- a/docs/deker/api/modules.rst +++ b/docs/deker/api/modules.rst @@ -1,5 +1,5 @@ -Deker public API -================= +DEKER™ public API +================== .. toctree:: :maxdepth: 4 diff --git a/docs/deker/collection_schema.rst b/docs/deker/collection_schema.rst index 6bf96db..18a1f4f 100755 --- a/docs/deker/collection_schema.rst +++ b/docs/deker/collection_schema.rst @@ -6,10 +6,10 @@ Collection Schema Introduction ============ -In some aspects Deker is similar to other database management systems. It has *collections* which +In some aspects DEKER™ is similar to other database management systems. It has *collections* which are equivalent to tables in relational databases or collections in MongoDB. -Collection stores one of two flavors of *arrays* supported by Deker. We would look into difference +Collection stores one of two flavors of *arrays* supported by DEKER™. We would look into difference between them later in this tutorial, but for now it is important to understand that *array* is defined by the *schema* associated with the *collection* where it is stored. @@ -31,8 +31,8 @@ Collection *schema* consists from several components: Understanding Array Flavors =========================== -Two flavor of *arrays* supported by Deker are ``Array`` and ``VArray``. Those objects represent -core concept of Deker storage. Hereafter we will describe their structure, differences and +Two flavor of *arrays* supported by DEKER™ are ``Array`` and ``VArray``. Those objects represent +core concept of DEKER™ storage. Hereafter we will describe their structure, differences and commonalities and give overview of when either of them should be used. @@ -61,8 +61,8 @@ layers with particular weather characteristic values, as shown in the legend. In the illustration above single ``Array`` has 4 cells in each dimension, in other words its *shape* is ``(4, 4, 4)``. -Deker will store each ``Array`` data in a separate file, and when we retrieve this ``Array`` object -from ``Collection`` and access its data, all operations will affect this file only. +DEKER™ will store each ``Array`` data in a separate file, and when we retrieve this ``Array`` +object from ``Collection`` and access its data, all operations will affect this file only. VArray @@ -80,7 +80,7 @@ something really huge like whole Earth surface satellite image. Let's say that s would be 300000x200000 px. If stored in single file it will produce large filesystem objects that will impose limitations on concurrent read-write access thus impending storage scalability. -To optimize this type of data storage, Deker uses tiling, i.e. it splits large ``VArray`` objects +To optimize this type of data storage, DEKER™ uses tiling, i.e. it splits large ``VArray`` objects into series of smaller ``Array`` objects and transparently join them into for user access as virtual array. It probably would still be impossible to access this huge array as a whole, but it enables efficient access to digestible parts of it piece by piece. @@ -92,7 +92,7 @@ enables efficient access to digestible parts of it piece by piece. into separate *tiles* (``Array`` objects) with regular *grid*. If ``Collection`` is defined to contain ``VArray`` objects, you don't have to worry about tiling, -Deker would transparently manage this for you under the hood. +DEKER™ would transparently manage this for you under the hood. When some slice of data is queried from the ``VArray``, it automatically calculates which files need to be opened to retrieve it and what part of requested slice data bounds belong to each of @@ -111,8 +111,8 @@ Let's query the following slice of it: ``[1:3, :, :]`` Here you can see, that all 4 tile files will be affected, but only the highlighted pieces of them will be actually read or written. All different files reads or writes could be done in parallel. -In case you are retrieving data, Deker will transparently combine each read piece into subset with -requested shape and return it to you. If you use these bounds to write data, Deker will +In case you are retrieving data, DEKER™ will transparently combine each read piece into subset with +requested shape and return it to you. If you use these bounds to write data, DEKER™ will automatically split the slice you have provided into pieces and write them in parallel to corresponding files. @@ -234,7 +234,7 @@ If a dimension has a real regular scale, we may indicate it:: ), ] -As you can see, regular scale can be defined either with Python ``dict`` or with Deker ``Scale`` +As you can see, regular scale can be defined either with Python ``dict`` or with DEKER™ ``Scale`` named tuple. The keyword ``name`` is optional. Scale values shall be always defined as ``floats``. The parameters ``step`` and ``start_value`` may be negative as well. For example, ``era5`` weather @@ -242,7 +242,7 @@ model has a geo grid shaped ``(ys=721, xs=1440)`` with step ``0.25`` degrees per zero-point of the ``map`` is north-west or left-upper corner. In other words ``era5`` grid point ``(0, 0)`` is set to coordinates ``(lat=90.0, lon=-180.0)``. -Here is an example of how this grid can be bound to real geographical coordinates in Deker:: +Here is an example of how this grid can be bound to real geographical coordinates in DEKER™:: dimensions = [ DimensionSchema( @@ -348,7 +348,7 @@ let you set an individual start point for each new ``Array`` or ``VArray`` at it .. attention:: For ``start_value`` you can pass a datetime value with any timezone (e.g. your local timezone), - but you should remember that Deker converts and stores it in the UTC timezone. + but you should remember that DEKER™ converts and stores it in the UTC timezone. Before querying some data from ``TimeDimension``, you should convert your local time to UTC to be sure that you get a pack of correct data. You can do it with ``get_utc()`` function from @@ -381,7 +381,7 @@ All databases provide some additional obligatory and/or optional information con example, in SQL there are primary keys which indicate that data cannot be inserted without passing them. -For this purpose Deker provides **primary** and **custom attributes** which shall be defined as a +For this purpose DEKER™ provides **primary** and **custom attributes** which shall be defined as a list (or a tuple) of ``AttributeSchema``:: from deker import AttributeSchema @@ -428,7 +428,7 @@ Primary Attributes It is highly recommended to define at least one **primary** attribute in every schema. Primary attributes are a strictly ordered sequence. They are used for ``Array`` or ``VArray`` -filtering. When Deker is building its file system, it creates symlinks for main data files using +filtering. When DEKER™ is building its file system, it creates symlinks for main data files using primary attributes in the symlink path. If you need to get a certain ``Array`` or ``VArray`` from a ``Collection``, you have two options how to do it: @@ -483,8 +483,8 @@ dimensions schemas and ``dtype``. You may optionally pass a list of attributes s Data Type --------- -Deker has a strong data typing. All the values of all the ``Array`` or ``VArray`` objects in one -``Collection`` shall be of the same data type. Deker accepts numeric data of the following Python +DEKER™ has a strong data typing. All the values of all the ``Array`` or ``VArray`` objects in one +``Collection`` shall be of the same data type. DEKER™ accepts numeric data of the following Python and NumPy data types: .. list-table:: Integers @@ -649,7 +649,7 @@ That's why we need something that will fill them in. Rules are the following: 1. ``fill_value`` **shall not be significant** for your data. -2. ``fill_value`` **is optional** - you may not provide it. In this case Deker will choose it +2. ``fill_value`` **is optional** - you may not provide it. In this case DEKER™ will choose it automatically basing on the provided ``dtype``. For ``integer`` and ``unsigned integer`` data types it will be the lowest value for the correspondent data type bit capacity. For example, it will be ``-128`` for ``numpy.int8``. For ``float`` and ``complex`` data types it will be @@ -658,8 +658,8 @@ Rules are the following: passed to the ``dtype`` parameter. If all the values of the correspondent ``dtype`` are significant for you, you shall choose a data type of a greater bit capacity. For example, if all the values in the range ``[-128; 128]`` are valid for your dataset, you'd better choose - ``numpy.int16`` instead of ``numpy.int8`` and set ``-129`` as ``fill_value`` or let Deker to set - it automatically. The other workaround is to choose any floating data type, e.g. + ``numpy.int16`` instead of ``numpy.int8`` and set ``-129`` as ``fill_value`` or let DEKER™ to + set it automatically. The other workaround is to choose any floating data type, e.g. ``numpy.float16``, and have ``numpy.nan`` as a ``fill_value``. Now, let's create once again some simple dimensions and attributes for both types of schemas:: @@ -797,7 +797,7 @@ Creating Collection ``Client`` is responsible for creating connections and its internal context. -As far as Deker is a file-based database, you need to provide some path to the storage, where your +As far as DEKER™ is a file-based database, you need to provide some path to the storage, where your collections will be kept. @@ -806,9 +806,9 @@ URI There is a universal way to provide paths and connection options: an URI. -The scheme of URI string for embedded Deker databases, stored on your local drive, is ``file://``. +The scheme of URI string for embedded DEKER™ databases, stored on your local drive, is ``file://``. It shall be followed by a path to the directory where the storage will be located. If this -directory (or even full path to it) does not exist, Deker will create it at ``Client`` +directory (or even full path to it) does not exist, DEKER™ will create it at ``Client`` initialization. .. note:: @@ -824,7 +824,7 @@ In this documentation we will use a reference to a temporary directory ``/tmp/de Client ------ -Now open the ``Client`` for interacting with Deker:: +Now open the ``Client`` for interacting with DEKER™:: from deker import Client @@ -918,7 +918,7 @@ some world-wide weather data:: **We did it!** -Now there is a new path ``/tmp/deker/collections/weather`` on your local drive where Deker will +Now there is a new path ``/tmp/deker/collections/weather`` on your local drive where DEKER™ will store the data relative to the ``Collection`` named ``weather``. Each ``Array`` will contain a pack of daily 24-hours weather data for each entire latitude and longitude degree: ``temperature``, ``humidity``, ``pressure`` and ``wind_speed``. diff --git a/docs/deker/connecting_to_server.rst b/docs/deker/connecting_to_server.rst index d56f7d0..68f4fb0 100644 --- a/docs/deker/connecting_to_server.rst +++ b/docs/deker/connecting_to_server.rst @@ -5,14 +5,15 @@ Connecting to Server .. _OpenWeather: https://openweathermap.org .. _Installation page: installation.html -To access remotely the data stored on OpenWeather_ managed Deker server infrastructure, you need +To access remotely the data stored on OpenWeather_ managed DEKER™ server infrastructure, you need to use server adapters. It is an original OpenWeather plugin, based on `httpx `_ with HTTP 2.0 support, that allows your local client to communicate with remote OpenWeather -public server instances of Deker. +public server instances of DEKER™. -Deker will automatically find and initialize this plugin if it is installed in current environment. +DEKER™ will automatically find and initialize this plugin if it is installed in current +environment. .. attention:: You must install ``deker-server-adapters`` package , for details refer to the `Installation page`_ @@ -20,7 +21,7 @@ Deker will automatically find and initialize this plugin if it is installed in c Usage ========= -To use server version, you have to initialize Deker's Client with an uri which contains +To use server version, you have to initialize DEKER™ Client with an uri which contains ``http/https`` scheme. .. code-block:: python @@ -28,9 +29,9 @@ To use server version, you have to initialize Deker's Client with an uri which c from deker import Client client = Client("http://{url-to-deker-server}") # As simple as that -And now the client will communicate with Deker server. +And now the client will communicate with DEKER™ server. -If authentication is enabled on the Deker server, you can provide credentials by adding it +If authentication is enabled on the DEKER™ server, you can provide credentials by adding it to the url like this: .. code-block:: python @@ -41,7 +42,7 @@ to the url like this: Configuration ============= Server adapters use ``httpx client`` under the hood. You can configure its behaviour by passing -keyword arguments to the ``httpx_conf`` parameter of the Deker's Client: +keyword arguments to the ``httpx_conf`` parameter of the DEKER™ Client: .. code-block:: python diff --git a/docs/deker/data_access.rst b/docs/deker/data_access.rst index 09e2774..e90d3fd 100755 --- a/docs/deker/data_access.rst +++ b/docs/deker/data_access.rst @@ -286,7 +286,7 @@ slicing parameters:: .. _`official documentation`: https://numpy.org/doc/stable/user/basics.indexing.html -Deker allows you to index and slice its ``Array`` and ``VArray`` not only with integers, but with +DEKER™ allows you to index and slice its ``Array`` and ``VArray`` not only with integers, but with the ``types`` by which the dimensions are described. But let's start with a **constraint**. @@ -561,7 +561,7 @@ Read Xarray ----------- .. warning:: - ``xarray`` package is not in the list of the Deker default dependencies. Please, refer to the + ``xarray`` package is not in the list of the DEKER™ default dependencies. Please, refer to the Installation_ chapter for more details Xarray_ is a wonderful project, which provides special objects for working with multidimensional @@ -601,8 +601,8 @@ It provides even more opportunities. Refer to ``xarray.DataArray`` API_ for deta Locks ====== -Deker is thread and process safe. It uses its own locks for the majority of operations. -Deker locks can be divided into two groups: **read** and **write** locks +DEKER™ is thread and process safe. It uses its own locks for the majority of operations. +DEKER™ locks can be divided into two groups: **read** and **write** locks **Read locks** can be shared between threads and processes with no risk of data corruption. diff --git a/docs/deker/fine_tuning.rst b/docs/deker/fine_tuning.rst index 31f1c64..7f5acd9 100755 --- a/docs/deker/fine_tuning.rst +++ b/docs/deker/fine_tuning.rst @@ -2,7 +2,7 @@ Fine Tuning *********** -This chapter is dedicated to advanced settings and features provided by Deker. +This chapter is dedicated to advanced settings and features provided by DEKER™. Client @@ -15,9 +15,9 @@ tune. All of them shall be explicitly passed as keyword parameters, none of them ``executor`` ------------ -Deker creates its own ``ThreadPoolExecutor`` instance for working with ``VArray``. By default, this -parameter is ``None``. You may want to use your own ``ThreadPoolExecutor`` (or some custom -executor, based on ``ThreadPoolExecutor``) instance. In this case Deker will use the passed one:: +DEKER™ creates its own ``ThreadPoolExecutor`` instance for working with ``VArray``. By default, +this parameter is ``None``. You may want to use your own ``ThreadPoolExecutor`` (or some custom +executor, based on ``ThreadPoolExecutor``) instance. In this case DEKER™ will use the passed one:: from deker import Client @@ -34,9 +34,9 @@ executor, based on ``ThreadPoolExecutor``) instance. In this case Deker will use ``workers`` ----------- -This is a parameter for the native Deker executor mentioned above. +This is a parameter for the native DEKER™ executor mentioned above. -By default, it is ``None`` and in this case Deker uses the maximum number of threads from the +By default, it is ``None`` and in this case DEKER™ uses the maximum number of threads from the formula, provided by `Python 3.9 documentation`_ : ``cpu_count() + 4``. You may increase or reduce it, if you need:: @@ -51,7 +51,7 @@ You may increase or reduce it, if you need:: ``write_lock_timeout`` ---------------------- -Deker uses its own file locking mechanisms for different operations, one of which is for writing. +DEKER™ uses its own file locking mechanisms for different operations, one of which is for writing. With ``write_lock_timeout`` you can modify an amount of seconds during which a parallel writing process waits for the release of the locked file:: @@ -78,8 +78,9 @@ The default is ``1`` second. The units are immutable and only ``int`` is accepte ``loglevel`` ------------ -All the Deker objects (including private ones) have their own loggers. They are bound by the common -logging level, which defaults to ``"ERROR"``. If you need, you may change it at ``Client`` init:: +All the DEKER™ objects (including private ones) have their own loggers. They are bound by the +common logging level, which defaults to ``"ERROR"``. If you need, you may change +it at ``Client`` init:: from deker import Client @@ -89,7 +90,7 @@ If you need to change it on the fly, you may use the following function:: from deker.log import set_logging_level - set_logging_level("INFO") # now Deker logs starting from "INFO" level + set_logging_level("INFO") # now DEKER™ logs starting from "INFO" level ``memory_limit`` @@ -97,7 +98,7 @@ If you need to change it on the fly, you may use the following function:: This parameter is used for the early run time break in case of potential memory overflow. -Deker operates big amounts of data, and you may be unaware that your machine will probably run out +DEKER™ operates big amounts of data, and you may be unaware that your machine will probably run out of memory. For example, NumPy shall raise ``_ArrayMemoryError`` if you do something like this:: >>> import numpy as np @@ -106,19 +107,19 @@ of memory. For example, NumPy shall raise ``_ArrayMemoryError`` if you do someth # numpy.core._exceptions._ArrayMemoryError: Unable to allocate 74.5 GiB # for an array with shape (100000, 100000) and data type float64 -As Deker is lazy, you shall be warned about such problems beforehand. For that purpose, Deker +As DEKER™ is lazy, you shall be warned about such problems beforehand. For that purpose, DEKER™ checks the memory limits when it is creating: * ``Collection`` * ``Subset`` or ``VSubset`` * ``xarray.DataArray`` from a ``Subset`` or a ``VSubset`` -By default Deker is limited to your **total virtual memory size** (i.e. total amount of RAM plus -swap size). For example, you have 16 GB of RAM and 2 GB of swap. Thus, Deker is limited to 18 GB of -memory by default. But usually a machine is already using some parts of these memory for other +By default DEKER™ is limited to your **total virtual memory size** (i.e. total amount of RAM plus +swap size). For example, you have 16 GB of RAM and 2 GB of swap. Thus, DEKER™ is limited to 18 GB +of memory by default. But usually a machine is already using some parts of these memory for other processes. So your current available free memory is always lower than the total one. -Deker compares its limits with your current available free memory (RAM + swap) and chooses the +DEKER™ compares its limits with your current available free memory (RAM + swap) and chooses the minimal one of them. Than it compares the result with the requested shape size. In case your request requires too much memory or you are trying to create a ``Collection`` with a schema, which may cause a memory overflow in future, ``DekerMemoryError`` will be immediately raised. @@ -138,7 +139,7 @@ suffix is ignored: ``"1024k"``, ``"512m"``, ``"8g"``, ``"1t"`` will work. .. note:: You definitely may want to use it in **Docker**. - If you set a memory limit to your container, you'd better limit Deker to the same value. + If you set a memory limit to your container, you'd better limit DEKER™ to the same value. Otherwise your container may be killed because of memory overflow. HDF5 Options @@ -154,15 +155,15 @@ supports an unlimited variety of data types, and is designed for flexible and ef high volume and complex data. This format offers a big number of special tuning options. We will talk about ``chunks`` and data ``compression``. -Deker ``deker-local-adapters`` plugin has its default implementation of working with this format. +DEKER™ ``deker-local-adapters`` plugin has its default implementation of working with this format. It depends on two packages: ``h5py_`` and ``hdf5plugin_`` which provide a Python interface for HDF5 binaries and a pack of compression filters. .. _h5py: https://docs.h5py.org/en/stable/ .. _hdf5plugin: http://www.silx.org/doc/hdf5plugin/latest/ -Deker applies chunks and compression options to all of the files within one collection. As long as -you do not interact directly with the files and low-level interfaces, Deker provides special types +DEKER™ applies chunks and compression options to all of the files within one collection. As long as +you do not interact directly with the files and low-level interfaces, DEKER™ provides special types for these options usage. Your settings are stored in the collection metadata. When you invoke a ``Collection``, they are recovered and ready to be applied to your data. But they have to make a trip from the collection metadata to the final data, that's why we need ``HDF5Options`` and @@ -238,7 +239,7 @@ A HDF5-file may have *no chunks* options or be chunked either *manually* or *aut .. _HDF5 chunking manual: https://portal.hdfgroup.org/display/HDF5/Chunking+in+HDF5 -Deker allows you to use all the 3 options. +DEKER™ allows you to use all the 3 options. Chunks options are set to ``None`` by default. diff --git a/docs/deker/installation.rst b/docs/deker/installation.rst index 91dcd22..4153fc3 100755 --- a/docs/deker/installation.rst +++ b/docs/deker/installation.rst @@ -3,22 +3,22 @@ Installation ************ -Deker -===== +DEKER™ +======= -Deker was developed and tested on x86_64 Linux and both x86_64 and Apple silicon macOS, and known +DEKER™ was developed and tested on x86_64 Linux and both x86_64 and Apple silicon macOS, and known to be running in production environments on x86_64 Linux servers. .. note:: - Minimal Python version for Deker is ``3.9``. + Minimal Python version for DEKER™ is ``3.9``. .. attention:: - Deker uses NumPy, and some NumPy types are unsupported on current NumPy arm64 version. So if you - want to use Deker library on Apple silicon (M series CPU), you have to install x86_64 version of + DEKER™ uses NumPy, and some NumPy types are unsupported on current NumPy arm64 version. So if you + want to use DEKER™ library on Apple silicon (M series CPU), you have to install x86_64 version of Python using Rosetta_ x86_64 to arm64 dynamic binary translator. You may use the following guide_ to install x86_64 version of Python an then switch to that - version in your Deker project using ``pyenv`` and install Deker package as usual. + version in your DEKER™ project using ``pyenv`` and install DEKER™ package as usual. .. _Rosetta: https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment .. _guide: https://sixty-north.com/blog/pyenv-apple-silicon.html @@ -27,7 +27,7 @@ to be running in production environments on x86_64 Linux servers. Dependencies ------------ -Deker depends on the following third-party packages: +DEKER™ depends on the following third-party packages: * ``numpy`` >= 1.18 * ``attrs`` >= 23.1.0 @@ -36,14 +36,14 @@ Deker depends on the following third-party packages: * ``h5py`` >= 3.8.0 * ``hdf5plugin`` >= 4.0.1 -Also please note that for flexibility few internal Deker components are published as separate +Also please note that for flexibility few internal DEKER™ components are published as separate packages: * ``deker-local-adapters`` * ``deker-server-adapters`` * ``deker-tools`` -To install Deker run: +To install DEKER™ run: .. code-block:: bash @@ -53,7 +53,7 @@ To install Deker run: Optional Packages ----------------- -Deker also supports output of its data as Xarray_ via the following package: +DEKER™ also supports output of its data as Xarray_ via the following package: * ``xarray`` >= 2023.5.0 @@ -65,14 +65,14 @@ To install it with ``xarray`` optional dependency: .. _Xarray: https://docs.xarray.dev/en/stable/getting-started-guide/installing.html -Deker Tools -=========== +DEKER™ Tools +============= ``deker-tools`` is an out-of-box battery which provides several useful tools and utilities to work -with Deker data. You may find this package useful in your projects, even if they are not related to -Deker. +with DEKER™ data. You may find this package useful in your projects, even if they are not related +to DEKER™. -To install Deker tools package, run: +To install DEKER™ tools package, run: .. code-block:: bash @@ -82,7 +82,7 @@ To install Deker tools package, run: Interactive Shell ================= -``deker-shell`` is an interactive environment that enables you to manage and access Deker storage +``deker-shell`` is an interactive environment that enables you to manage and access DEKER™ storage in a convenient way. It requires ``deker`` package to be installed **manually** before use as described above. @@ -92,7 +92,7 @@ To install interactive shell package, run: pip install deker deker-shell -Or you can install it alongside with Deker by: +Or you can install it alongside with DEKER™ by: .. code-block:: bash @@ -105,15 +105,15 @@ Server Adapters It is an original OpenWeather plugin_, based on `httpx `_ with HTTP 2.0 support, that allows your local client to communicate with remote OpenWeather -public server instances of Deker. +public server instances of DEKER™. -If you don't have Deker yet, run +If you don't have DEKER™ yet, run .. code-block:: bash pip install deker[server-adapters] -If you have already installed Deker, you can simply install plugin to use it by: +If you have already installed DEKER™, you can simply install plugin to use it by: .. code-block:: bash @@ -121,7 +121,7 @@ If you have already installed Deker, you can simply install plugin to use it by: Install All at Once -================================= +==================== You can install all the above mentioned options at once by: .. code-block:: bash diff --git a/docs/deker/shell.rst b/docs/deker/shell.rst index bf2822d..b0319d8 100644 --- a/docs/deker/shell.rst +++ b/docs/deker/shell.rst @@ -3,9 +3,9 @@ Interactive Shell ***************** Interactive shell is a convenient Python REPL interface that allows you to manage, query and modify -data in your Deker storage. +data in your DEKER™ storage. -.. note:: Deker shell is based on amazing ptpython_ - a better Python REPL +.. note:: DEKER™ shell is based on amazing ptpython_ - a better Python REPL .. _ptpython: https://github.com/prompt-toolkit/ptpython @@ -24,7 +24,7 @@ Features Start ===== -Once installed, open your terminal and run the shell providing path to Deker storage via command +Once installed, open your terminal and run the shell providing path to DEKER™ storage via command line parameter (in this case it would be ``/tmp/deker-data``):: deker file:///tmp/deker-data @@ -48,8 +48,8 @@ REPL menu (called with ``F2``): Interface ========= -Imported Deker Classes ----------------------- +Imported DEKER™ Classes +------------------------ Basic storage access and management classes: diff --git a/docs/deker/tools.rst b/docs/deker/tools.rst index 42866b9..2a57f8a 100644 --- a/docs/deker/tools.rst +++ b/docs/deker/tools.rst @@ -1,17 +1,17 @@ -*********** -Deker Tools -*********** +************* +DEKER™ Tools +************* -Deker Tools is a collection of utility functions and classes designed to assist in common data +DEKER™ Tools is a collection of utility functions and classes designed to assist in common data processing tasks. It consists of modules that handle data conversion, path validation, and slice manipulation. -.. attention:: This package is not considered to be part of Deker public API and can be significantly +.. attention:: This package is not considered to be part of DEKER™ public API and can be significantly changed in future versions. -For details please refer to the `Deker Tools`_ API documentation. +For details please refer to the `DEKER™ Tools`_ API documentation. -.. _Deker Tools: api/deker_tools/modules.html +.. _DEKER™ Tools: api/deker_tools/modules.html ``data`` diff --git a/docs/index.rst b/docs/index.rst index 6161289..86874c7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ Data Access Fine Tuning Interactive Shell - Deker Tools + DEKER™ Tools Connecting to Server @@ -15,8 +15,8 @@ :hidden: :caption: API Reference - Deker API - Deker Tools + DEKER™ API + DEKER™ Tools .. toctree:: :hidden: @@ -26,32 +26,33 @@ GitHub Projects -************** -What is Deker? -************** +**************** +What is DEKER™? +**************** .. image:: deker/images/logo.png :align: right :scale: 50% -Deker is pure Python implementation of petabyte-scale highly parallel data storage engine for +DEKER™ is pure Python implementation of petabyte-scale highly parallel data storage engine for multidimensional arrays. -Deker name comes from term *dekeract*, the 10-cube_. +DEKER™ name comes from term *dekeract*, the 10-cube_. -Deker was made with the following major goals in mind: +DEKER™ was made with the following major goals in mind: * provide intuitive interface for storing and accessing **huge data arrays** * support **arbitrary number of data dimensions** * be **thread and process safe** and as **lean on RAM** use as possible -Deker empowers users to store and access a wide range of data types, virtually anything that can be -represented as arrays, like **geospacial data**, **satellite images**, **machine learning models**, -**sensors data**, graphs, key-value pairs, tabular data, and more. +DEKER™ empowers users to store and access a wide range of data types, virtually anything that +can be represented as arrays, like **geospacial data**, **satellite images**, +**machine learning models**, **sensors data**, graphs, key-value pairs, tabular data, +and more. -Deker does not limit your data complexity and size: it supports virtually unlimited number of data -dimensions and provides under the hood mechanisms to **partition** huge amounts of data for -**scalability**. +DEKER™ does not limit your data complexity and size: it supports virtually unlimited number +of data dimensions and provides under the hood mechanisms to **partition** huge amounts of data +for **scalability**. .. _10-cube: https://en.wikipedia.org/wiki/10-cube @@ -75,7 +76,7 @@ Features Code and Documentation ====================== -Open source implementation of Deker storage engine is published at +Open source implementation of DEKER™ storage engine is published at * https://github.com/openweathermap/deker