diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d289509f5d4..722e2525322 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,6 +112,7 @@ jobs: python -m pip install --upgrade pip python -m pip install poetry poetry install --all-extras + sudo apt-get update sudo apt-get install --no-install-recommends ffmpeg - name: Test @@ -157,6 +158,7 @@ jobs: python -m pip install poetry rm poetry.lock poetry install --all-extras + sudo apt-get update sudo apt-get install --no-install-recommends ffmpeg - name: Test @@ -187,6 +189,7 @@ jobs: python -m pip install poetry poetry install --all-extras poetry run pip install protobuf==3.19.0 # we check that we support 3.19 + sudo apt-get update sudo apt-get install --no-install-recommends ffmpeg - name: Test @@ -214,6 +217,7 @@ jobs: python -m pip install --upgrade pip python -m pip install poetry poetry install --all-extras + sudo apt-get update sudo apt-get install --no-install-recommends ffmpeg - name: Test @@ -242,6 +246,7 @@ jobs: poetry install --all-extras poetry run pip install protobuf==3.19.0 poetry run pip install tensorflow==2.11.0 + sudo apt-get update sudo apt-get install --no-install-recommends ffmpeg - name: Test diff --git a/docarray/array/array/io.py b/docarray/array/array/io.py index 676cf6a73a9..251afc65a4a 100644 --- a/docarray/array/array/io.py +++ b/docarray/array/array/io.py @@ -32,6 +32,7 @@ _dict_to_access_paths, ) from docarray.utils._internal.compress import _decompress_bytes, _get_compress_ctx +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: import pandas as pd @@ -500,7 +501,10 @@ def to_pandas(self) -> 'pd.DataFrame': :return: pandas.DataFrame """ - import pandas as pd + if TYPE_CHECKING: + import pandas as pd + else: + pd = import_library('pandas', raise_error=True) fields = self.document_type._get_access_paths() df = pd.DataFrame(columns=fields) diff --git a/docarray/array/array/sequence_indexing_mixin.py b/docarray/array/array/sequence_indexing_mixin.py index 01db74c0218..ac07359f3b0 100644 --- a/docarray/array/array/sequence_indexing_mixin.py +++ b/docarray/array/array/sequence_indexing_mixin.py @@ -1,5 +1,6 @@ import abc from typing import ( + TYPE_CHECKING, Any, Iterable, MutableSequence, @@ -14,7 +15,7 @@ import numpy as np -from docarray.utils._internal.misc import is_torch_available +from docarray.utils._internal.misc import import_library T_item = TypeVar('T_item') T = TypeVar('T', bound='IndexingSequenceMixin') @@ -85,11 +86,11 @@ def _normalize_index_item( return item.tolist() # torch index types - torch_available = is_torch_available() - if torch_available: + if TYPE_CHECKING: import torch else: - raise ValueError(f'Invalid index type {type(item)}') + torch = import_library('torch', raise_error=True) + allowed_torch_dtypes = [ torch.bool, torch.int64, diff --git a/docarray/base_doc/__init__.py b/docarray/base_doc/__init__.py index 5fdeed1a807..941e76c542b 100644 --- a/docarray/base_doc/__init__.py +++ b/docarray/base_doc/__init__.py @@ -1,6 +1,24 @@ from docarray.base_doc.any_doc import AnyDoc from docarray.base_doc.base_node import BaseNode from docarray.base_doc.doc import BaseDoc -from docarray.base_doc.doc_response import DocResponse +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) -__all__ = ['AnyDoc', 'BaseDoc', 'BaseNode', 'DocResponse'] +__all__ = ['AnyDoc', 'BaseDoc', 'BaseNode'] + + +def __getattr__(name: str): + if name == 'DocResponse': + import_library('fastapi', raise_error=True) + from docarray.base_doc.doc_response import DocResponse + + if name not in __all__: + __all__.append(name) + + return DocResponse + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) diff --git a/docarray/base_doc/doc_response.py b/docarray/base_doc/doc_response.py index cbc43bf4767..7d2b7b76ef6 100644 --- a/docarray/base_doc/doc_response.py +++ b/docarray/base_doc/doc_response.py @@ -1,14 +1,12 @@ -from typing import Any +from typing import TYPE_CHECKING, Any -try: - from fastapi.responses import JSONResponse, Response -except ImportError: +from docarray.utils._internal.misc import import_library - class NoImportResponse: - def __init__(self, *args, **kwargs): - ImportError('fastapi is not installed') - - Response = JSONResponse = NoImportResponse # type: ignore +if TYPE_CHECKING: + from fastapi.responses import JSONResponse +else: + fastapi = import_library('fastapi', raise_error=True) + JSONResponse = fastapi.responses.JSONResponse class DocResponse(JSONResponse): diff --git a/docarray/base_doc/mixins/io.py b/docarray/base_doc/mixins/io.py index e0fde4b5d4f..9654ae03d41 100644 --- a/docarray/base_doc/mixins/io.py +++ b/docarray/base_doc/mixins/io.py @@ -21,24 +21,23 @@ from docarray.typing import NdArray from docarray.typing.proto_register import _PROTO_TYPE_NAME_TO_CLASS from docarray.utils._internal.compress import _compress_bytes, _decompress_bytes -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -tf_available = is_tf_available() -if tf_available: +if TYPE_CHECKING: import tensorflow as tf # type: ignore - - from docarray.typing import TensorFlowTensor - -torch_available = is_torch_available() -if torch_available: import torch - - from docarray.typing import TorchTensor - -if TYPE_CHECKING: from pydantic.fields import ModelField from docarray.proto import DocumentProto, NodeProto + from docarray.typing import TensorFlowTensor, TorchTensor +else: + tf = import_library('tensorflow', raise_error=False) + if tf is not None: + from docarray.typing import TensorFlowTensor + + torch = import_library('torch', raise_error=False) + if torch is not None: + from docarray.typing import TorchTensor T = TypeVar('T', bound='IOMixin') @@ -68,12 +67,12 @@ def _type_to_protobuf(value: Any) -> 'NodeProto': return nested_item base_node_wrap: BaseNode - if torch_available: + if torch is not None: if isinstance(value, torch.Tensor): base_node_wrap = TorchTensor._docarray_from_native(value) return base_node_wrap._to_node_protobuf() - if tf_available: + if tf is not None: if isinstance(value, tf.Tensor): base_node_wrap = TensorFlowTensor._docarray_from_native(value) return base_node_wrap._to_node_protobuf() diff --git a/docarray/computation/tensorflow_backend.py b/docarray/computation/tensorflow_backend.py index f4fc9edaa51..fc963cdb48b 100644 --- a/docarray/computation/tensorflow_backend.py +++ b/docarray/computation/tensorflow_backend.py @@ -1,13 +1,19 @@ import typing -from typing import Callable, List, Optional, Tuple +from typing import TYPE_CHECKING, Callable, List, Optional, Tuple import numpy as np -import tensorflow as tf # type: ignore -import tensorflow._api.v2.experimental.numpy as tnp # type: ignore from docarray.computation import AbstractComputationalBackend from docarray.computation.abstract_numpy_based_backend import AbstractNumpyBasedBackend from docarray.typing import TensorFlowTensor +from docarray.utils._internal.misc import import_library + +if TYPE_CHECKING: + import tensorflow as tf # type: ignore + import tensorflow._api.v2.experimental.numpy as tnp # type: ignore +else: + tf = import_library('tensorflow', raise_error=True) + tnp = tf._api.v2.experimental.numpy def _unsqueeze_if_single_axis(*matrices: tf.Tensor) -> List[tf.Tensor]: diff --git a/docarray/computation/torch_backend.py b/docarray/computation/torch_backend.py index 9af155132cc..f64b993186a 100644 --- a/docarray/computation/torch_backend.py +++ b/docarray/computation/torch_backend.py @@ -1,9 +1,14 @@ -from typing import Any, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union import numpy as np -import torch from docarray.computation.abstract_comp_backend import AbstractComputationalBackend +from docarray.utils._internal.misc import import_library + +if TYPE_CHECKING: + import torch +else: + torch = import_library('torch', raise_error=True) def _unsqueeze_if_single_axis(*matrices: torch.Tensor) -> List[torch.Tensor]: diff --git a/docarray/documents/audio.py b/docarray/documents/audio.py index e27abcb5408..3103ab656c1 100644 --- a/docarray/documents/audio.py +++ b/docarray/documents/audio.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union import numpy as np @@ -7,15 +7,14 @@ from docarray.typing.bytes.audio_bytes import AudioBytes from docarray.typing.tensor.abstract_tensor import AbstractTensor from docarray.typing.tensor.audio.audio_tensor import AudioTensor -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -torch_available = is_torch_available() -if torch_available: - import torch - -tf_available = is_tf_available() -if tf_available: +if TYPE_CHECKING: import tensorflow as tf # type: ignore + import torch +else: + torch = import_library('torch', raise_error=False) + tf = import_library('tensorflow', raise_error=False) T = TypeVar('T', bound='AudioDoc') @@ -110,9 +109,9 @@ def validate( if isinstance(value, str): value = cls(url=value) elif isinstance(value, (AbstractTensor, np.ndarray)) or ( - torch_available + torch is not None and isinstance(value, torch.Tensor) - or (tf_available and isinstance(value, tf.Tensor)) + or (tf is not None and isinstance(value, tf.Tensor)) ): value = cls(tensor=value) diff --git a/docarray/documents/image.py b/docarray/documents/image.py index bf281f83d8f..47456c8cd29 100644 --- a/docarray/documents/image.py +++ b/docarray/documents/image.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union import numpy as np @@ -6,17 +6,16 @@ from docarray.typing import AnyEmbedding, ImageBytes, ImageUrl from docarray.typing.tensor.abstract_tensor import AbstractTensor from docarray.typing.tensor.image.image_tensor import ImageTensor -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -T = TypeVar('T', bound='ImageDoc') - -torch_available = is_torch_available() -if torch_available: +if TYPE_CHECKING: + import tensorflow as tf # type: ignore import torch +else: + tf = import_library('tensorflow', raise_error=False) + torch = import_library('torch', raise_error=False) -tf_available = is_tf_available() -if tf_available: - import tensorflow as tf # type: ignore +T = TypeVar('T', bound='ImageDoc') class ImageDoc(BaseDoc): @@ -99,8 +98,8 @@ def validate( value = cls(url=value) elif ( isinstance(value, (AbstractTensor, np.ndarray)) - or (torch_available and isinstance(value, torch.Tensor)) - or (tf_available and isinstance(value, tf.Tensor)) + or (torch is not None and isinstance(value, torch.Tensor)) + or (tf is not None and isinstance(value, tf.Tensor)) ): value = cls(tensor=value) elif isinstance(value, bytes): diff --git a/docarray/documents/mesh/vertices_and_faces.py b/docarray/documents/mesh/vertices_and_faces.py index 364ad3187f6..cc3dc6da795 100644 --- a/docarray/documents/mesh/vertices_and_faces.py +++ b/docarray/documents/mesh/vertices_and_faces.py @@ -1,7 +1,8 @@ -from typing import Any, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Type, TypeVar, Union from docarray.base_doc import BaseDoc from docarray.typing.tensor.tensor import AnyTensor +from docarray.utils._internal.misc import import_library T = TypeVar('T', bound='VerticesAndFaces') @@ -28,9 +29,12 @@ def validate( def display(self) -> None: """ Plot mesh consisting of vertices and faces. - To use this you need to install trimesh[easy]: `pip install 'trimesh[easy]'`. """ - import trimesh + if TYPE_CHECKING: + import trimesh + else: + trimesh = import_library('trimesh', raise_error=True) + from IPython.display import display if self.vertices is None or self.faces is None: diff --git a/docarray/documents/point_cloud/point_cloud_3d.py b/docarray/documents/point_cloud/point_cloud_3d.py index 25e0e6437d1..36e56a4c571 100644 --- a/docarray/documents/point_cloud/point_cloud_3d.py +++ b/docarray/documents/point_cloud/point_cloud_3d.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union import numpy as np @@ -6,15 +6,15 @@ from docarray.documents.point_cloud.points_and_colors import PointsAndColors from docarray.typing import AnyEmbedding, PointCloud3DUrl from docarray.typing.tensor.abstract_tensor import AbstractTensor -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -torch_available = is_torch_available() -if torch_available: +if TYPE_CHECKING: + import tensorflow as tf # type: ignore import torch +else: + tf = import_library('tensorflow', raise_error=False) + torch = import_library('torch', raise_error=False) -tf_available = is_tf_available() -if tf_available: - import tensorflow as tf # type: ignore T = TypeVar('T', bound='PointCloud3D') @@ -124,9 +124,9 @@ def validate( if isinstance(value, str): value = cls(url=value) elif isinstance(value, (AbstractTensor, np.ndarray)) or ( - torch_available + torch is not None and isinstance(value, torch.Tensor) - or (tf_available and isinstance(value, tf.Tensor)) + or (tf is not None and isinstance(value, tf.Tensor)) ): value = cls(tensors=PointsAndColors(points=value)) diff --git a/docarray/documents/point_cloud/points_and_colors.py b/docarray/documents/point_cloud/points_and_colors.py index 82ce82f9ba1..825744bda4f 100644 --- a/docarray/documents/point_cloud/points_and_colors.py +++ b/docarray/documents/point_cloud/points_and_colors.py @@ -1,19 +1,19 @@ -from typing import Any, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union import numpy as np from docarray.base_doc import BaseDoc from docarray.typing import AnyTensor from docarray.typing.tensor.abstract_tensor import AbstractTensor -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -torch_available = is_torch_available() -if torch_available: +if TYPE_CHECKING: + import tensorflow as tf # type: ignore import torch +else: + torch = import_library('torch', raise_error=False) + tf = import_library('tensorflow', raise_error=False) -tf_available = is_tf_available() -if tf_available: - import tensorflow as tf # type: ignore T = TypeVar('T', bound='PointsAndColors') @@ -36,9 +36,9 @@ def validate( value: Union[str, AbstractTensor, Any], ) -> T: if isinstance(value, (AbstractTensor, np.ndarray)) or ( - torch_available + torch is not None and isinstance(value, torch.Tensor) - or (tf_available and isinstance(value, tf.Tensor)) + or (tf is not None and isinstance(value, tf.Tensor)) ): value = cls(points=value) @@ -47,9 +47,11 @@ def validate( def display(self) -> None: """ Plot point cloud consisting of points in 3D space and optionally colors. - To use this you need to install trimesh[easy]: `pip install 'trimesh[easy]'`. """ - import trimesh + if TYPE_CHECKING: + import trimesh + else: + trimesh = import_library('trimesh', raise_error=True) from IPython.display import display colors = ( diff --git a/docarray/documents/video.py b/docarray/documents/video.py index 679f10ea8ba..1035beac277 100644 --- a/docarray/documents/video.py +++ b/docarray/documents/video.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union import numpy as np @@ -8,16 +8,14 @@ from docarray.typing.tensor.abstract_tensor import AbstractTensor from docarray.typing.tensor.video.video_tensor import VideoTensor from docarray.typing.url.video_url import VideoUrl -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library -torch_available = is_torch_available() -if torch_available: - import torch - - -tf_available = is_tf_available() -if tf_available: +if TYPE_CHECKING: import tensorflow as tf # type: ignore + import torch +else: + tf = import_library('tensorflow', raise_error=False) + torch = import_library('torch', raise_error=False) T = TypeVar('T', bound='VideoDoc') @@ -112,9 +110,9 @@ def validate( if isinstance(value, str): value = cls(url=value) elif isinstance(value, (AbstractTensor, np.ndarray)) or ( - torch_available + torch is not None and isinstance(value, torch.Tensor) - or (tf_available and isinstance(value, tf.Tensor)) + or (tf is not None and isinstance(value, tf.Tensor)) ): value = cls(tensor=value) diff --git a/docarray/index/__init__.py b/docarray/index/__init__.py index 4a9986e1a97..37ef5e6f611 100644 --- a/docarray/index/__init__.py +++ b/docarray/index/__init__.py @@ -1,4 +1,34 @@ -from docarray.index.backends.elastic import ElasticV7DocIndex -from docarray.index.backends.hnswlib import HnswDocumentIndex +import types +from typing import TYPE_CHECKING -__all__ = ['HnswDocumentIndex', 'ElasticV7DocIndex'] +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) + +if TYPE_CHECKING: + from docarray.index.backends.elastic import ElasticV7DocIndex # noqa: F401 + from docarray.index.backends.hnswlib import HnswDocumentIndex # noqa: F401 + +__all__ = [] + + +def __getattr__(name: str): + lib: types.ModuleType + if name == 'HnswDocumentIndex': + import_library('hnswlib', raise_error=True) + import docarray.index.backends.hnswlib as lib + elif name == 'ElasticV7DocIndex': + import_library('elasticsearch', raise_error=True) + import docarray.index.backends.elastic as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + + index_cls = getattr(lib, name) + + if name not in __all__: + __all__.append(name) + + return index_cls diff --git a/docarray/index/abstract.py b/docarray/index/abstract.py index a037b070527..11c130086b4 100644 --- a/docarray/index/abstract.py +++ b/docarray/index/abstract.py @@ -29,19 +29,20 @@ from docarray.typing import AnyTensor from docarray.typing.tensor.abstract_tensor import AbstractTensor from docarray.utils._internal._typing import is_tensor_union -from docarray.utils._internal.misc import is_tf_available, torch_imported +from docarray.utils._internal.misc import import_library from docarray.utils.find import FindResult, _FindResult if TYPE_CHECKING: - from pydantic.fields import ModelField - -if torch_imported: - import torch - -if is_tf_available(): import tensorflow as tf # type: ignore + import torch + from pydantic.fields import ModelField from docarray.typing import TensorFlowTensor +else: + tf = import_library('tensorflow', raise_error=False) + if tf is not None: + from docarray.typing import TensorFlowTensor + torch = import_library('torch', raise_error=False) TSchema = TypeVar('TSchema', bound=BaseDoc) @@ -826,12 +827,12 @@ def _to_numpy(self, val: Any, allow_passthrough=False) -> Any: """ if isinstance(val, np.ndarray): return val - if is_tf_available() and isinstance(val, TensorFlowTensor): + if tf is not None and isinstance(val, TensorFlowTensor): return val.unwrap().numpy() if isinstance(val, (list, tuple)): return np.array(val) - if (torch_imported and isinstance(val, torch.Tensor)) or ( - is_tf_available() and isinstance(val, tf.Tensor) + if (torch is not None and isinstance(val, torch.Tensor)) or ( + tf is not None and isinstance(val, tf.Tensor) ): return val.numpy() if allow_passthrough: diff --git a/docarray/index/backends/hnswlib.py b/docarray/index/backends/hnswlib.py index 851fdcda3ef..b7555012db8 100644 --- a/docarray/index/backends/hnswlib.py +++ b/docarray/index/backends/hnswlib.py @@ -4,6 +4,7 @@ from dataclasses import dataclass, field from pathlib import Path from typing import ( + TYPE_CHECKING, Any, Dict, Generic, @@ -17,7 +18,6 @@ cast, ) -import hnswlib import numpy as np from docarray import BaseDoc, DocArray @@ -30,28 +30,37 @@ ) from docarray.proto import DocumentProto from docarray.typing.tensor.abstract_tensor import AbstractTensor -from docarray.utils._internal.misc import is_np_int, is_tf_available, is_torch_available +from docarray.utils._internal.misc import import_library, is_np_int from docarray.utils.filter import filter_docs from docarray.utils.find import _FindResult -TSchema = TypeVar('TSchema', bound=BaseDoc) -T = TypeVar('T', bound='HnswDocumentIndex') - -HNSWLIB_PY_VEC_TYPES = [list, tuple, np.ndarray, AbstractTensor] -if is_torch_available(): +if TYPE_CHECKING: + import hnswlib + import tensorflow as tf # type: ignore import torch - HNSWLIB_PY_VEC_TYPES.append(torch.Tensor) + from docarray.typing import TensorFlowTensor +else: + hnswlib = import_library('hnswlib', raise_error=False) + torch = import_library('torch', raise_error=False) + tf = import_library('tensorflow', raise_error=False) + if tf is not None: + from docarray.typing import TensorFlowTensor -if is_tf_available(): - import tensorflow as tf # type: ignore +HNSWLIB_PY_VEC_TYPES = [list, tuple, np.ndarray, AbstractTensor] - from docarray.typing import TensorFlowTensor +if torch is not None: + HNSWLIB_PY_VEC_TYPES.append(torch.Tensor) +if tf is not None: HNSWLIB_PY_VEC_TYPES.append(tf.Tensor) HNSWLIB_PY_VEC_TYPES.append(TensorFlowTensor) +TSchema = TypeVar('TSchema', bound=BaseDoc) +T = TypeVar('T', bound='HnswDocumentIndex') + + def _collect_query_args(method_name: str): # TODO: use partialmethod instead def inner(self, *args, **kwargs): if args: diff --git a/docarray/proto/__init__.py b/docarray/proto/__init__.py index 20c5f56b020..1b04df23fe6 100644 --- a/docarray/proto/__init__.py +++ b/docarray/proto/__init__.py @@ -1,4 +1,13 @@ -from google.protobuf import __version__ as __pb__version__ +from typing import TYPE_CHECKING + +from docarray.utils._internal.misc import import_library + +if TYPE_CHECKING: + from google.protobuf import __version__ as __pb__version__ +else: + protobuf = import_library('google.protobuf', raise_error=True) + __pb__version__ = protobuf.__version__ + if __pb__version__.startswith('4'): from docarray.proto.pb.docarray_pb2 import ( diff --git a/docarray/proto/pb/docarray_pb2.py b/docarray/proto/pb/docarray_pb2.py index 15127469ab0..a830f17ddc4 100644 --- a/docarray/proto/pb/docarray_pb2.py +++ b/docarray/proto/pb/docarray_pb2.py @@ -6,6 +6,7 @@ from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() diff --git a/docarray/proto/pb2/docarray_pb2.py b/docarray/proto/pb2/docarray_pb2.py index bf1e687bac1..0ea41987658 100644 --- a/docarray/proto/pb2/docarray_pb2.py +++ b/docarray/proto/pb2/docarray_pb2.py @@ -12,7 +12,6 @@ _sym_db = _symbol_database.Default() - from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( diff --git a/docarray/store/__init__.py b/docarray/store/__init__.py index 20eb3af1a51..9547db27c3e 100644 --- a/docarray/store/__init__.py +++ b/docarray/store/__init__.py @@ -1,5 +1,37 @@ +import types +from typing import TYPE_CHECKING + from docarray.store.file import FileDocStore -from docarray.store.jac import JACDocStore -from docarray.store.s3 import S3DocStore +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) + +if TYPE_CHECKING: + from docarray.store.jac import JACDocStore # noqa: F401 + from docarray.store.s3 import S3DocStore # noqa: F401 + +__all__ = ['FileDocStore'] + + +def __getattr__(name: str): + lib: types.ModuleType + if name == 'JACDocStore': + import_library('hubble', raise_error=True) + import docarray.store.jac as lib + elif name == 'S3DocStore': + import_library('smart_open', raise_error=True) + import_library('botocore', raise_error=True) + import_library('boto3', raise_error=True) + import docarray.store.s3 as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + + store_cls = getattr(lib, name) + + if name not in __all__: + __all__.append(name) -__all__ = ['JACDocStore', 'FileDocStore', 'S3DocStore'] + return store_cls diff --git a/docarray/store/jac.py b/docarray/store/jac.py index c9350fae18a..b2b2564a91e 100644 --- a/docarray/store/jac.py +++ b/docarray/store/jac.py @@ -14,10 +14,6 @@ Union, ) -import hubble -from hubble import Client as HubbleClient -from hubble.client.endpoints import EndpointsV2 - from docarray.store.abstract_doc_store import AbstractDocStore from docarray.store.helpers import ( _BufferedCachingRequestReader, @@ -25,12 +21,22 @@ raise_req_error, ) from docarray.utils._internal.cache import _get_cache_path +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: # pragma: no cover import io from docarray import BaseDoc, DocArray +if TYPE_CHECKING: + import hubble + from hubble import Client as HubbleClient + from hubble.client.endpoints import EndpointsV2 +else: + hubble = import_library('hubble', raise_error=True) + HubbleClient = hubble.Client + EndpointsV2 = hubble.client.endpoints.EndpointsV2 + def _get_length_from_summary(summary: List[Dict]) -> Optional[int]: """Get the length from summary.""" diff --git a/docarray/store/s3.py b/docarray/store/s3.py index 7711432900c..23534d556fd 100644 --- a/docarray/store/s3.py +++ b/docarray/store/s3.py @@ -1,19 +1,22 @@ import io import logging from pathlib import Path -from typing import Dict, Iterator, List, Optional, Type, TypeVar - -import boto3 -import botocore -from smart_open import open -from typing_extensions import TYPE_CHECKING +from typing import TYPE_CHECKING, Dict, Iterator, List, Optional, Type, TypeVar from docarray.store.abstract_doc_store import AbstractDocStore from docarray.store.helpers import _from_binary_stream, _to_binary_stream from docarray.utils._internal.cache import _get_cache_path +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: # pragma: no cover from docarray import BaseDoc, DocArray + import boto3 + import botocore + from smart_open import open +else: + open = import_library('smart_open', raise_error=True).open + boto3 = import_library('boto3', raise_error=True) + botocore = import_library('botocore', raise_error=True) SelfS3DocStore = TypeVar('SelfS3DocStore', bound='S3DocStore') diff --git a/docarray/typing/__init__.py b/docarray/typing/__init__.py index c9dceb600c9..f729b985456 100644 --- a/docarray/typing/__init__.py +++ b/docarray/typing/__init__.py @@ -1,3 +1,5 @@ +from typing_extensions import TYPE_CHECKING + from docarray.typing.bytes import AudioBytes, ImageBytes, VideoBytes from docarray.typing.id import ID from docarray.typing.tensor import ImageNdArray, ImageTensor @@ -15,6 +17,22 @@ TextUrl, VideoUrl, ) +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) + +if TYPE_CHECKING: + from docarray.typing.tensor import TensorFlowTensor # noqa: F401 + from docarray.typing.tensor import TorchEmbedding, TorchTensor # noqa: F401 + from docarray.typing.tensor.audio import AudioTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.audio import AudioTorchTensor # noqa: F401 + from docarray.typing.tensor.embedding import TensorFlowEmbedding # noqa: F401 + from docarray.typing.tensor.image import ImageTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.image import ImageTorchTensor # noqa: F401 + from docarray.typing.tensor.video import VideoTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.video import VideoTorchTensor # noqa: F401 + __all__ = [ 'NdArray', @@ -31,8 +49,6 @@ 'AnyUrl', 'ID', 'AnyTensor', - 'NdArrayEmbedding', - 'ImageBytes', 'ImageTensor', 'ImageNdArray', 'ImageBytes', @@ -40,39 +56,38 @@ 'AudioBytes', ] -from docarray.utils._internal.misc import is_tf_available, is_torch_available -torch_available = is_torch_available() -if torch_available: - from docarray.typing.tensor import TorchEmbedding, TorchTensor # noqa: F401 - from docarray.typing.tensor.audio.audio_torch_tensor import AudioTorchTensor # noqa - from docarray.typing.tensor.image import ImageTorchTensor # noqa: F401 - from docarray.typing.tensor.video.video_torch_tensor import VideoTorchTensor # noqa +_torch_tensors = [ + 'TorchTensor', + 'TorchEmbedding', + 'ImageTorchTensor', + 'AudioTorchTensor', + 'VideoTorchTensor', +] +_tf_tensors = [ + 'TensorFlowTensor', + 'TensorFlowEmbedding', + 'ImageTensorFlowTensor', + 'AudioTensorFlowTensor', + 'VideoTensorFlowTensor', +] - __all__.extend( - [ - 'AudioTorchTensor', - 'TorchEmbedding', - 'TorchTensor', - 'VideoTorchTensor', - 'ImageTorchTensor', - ] - ) -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor import TensorFlowTensor # noqa: F401 - from docarray.typing.tensor.audio import AudioTensorFlowTensor # noqa: F401 - from docarray.typing.tensor.embedding import TensorFlowEmbedding # noqa: F401 - from docarray.typing.tensor.image import ImageTensorFlowTensor # noqa: F401 - from docarray.typing.tensor.video import VideoTensorFlowTensor # noqa +def __getattr__(name: str): + if name in _torch_tensors: + import_library('torch', raise_error=True) + elif name in _tf_tensors: + import_library('tensorflow', raise_error=True) + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + + import docarray.typing.tensor + + tensor_cls = getattr(docarray.typing.tensor, name) + + if name not in __all__: + __all__.append(name) - __all__.extend( - [ - 'TensorFlowTensor', - 'TensorFlowEmbedding', - 'AudioTensorFlowTensor', - 'ImageTensorFlowTensor', - 'VideoTensorFlowTensor', - ] - ) + return tensor_cls diff --git a/docarray/typing/bytes/audio_bytes.py b/docarray/typing/bytes/audio_bytes.py index 649d06bac03..4a0283c8761 100644 --- a/docarray/typing/bytes/audio_bytes.py +++ b/docarray/typing/bytes/audio_bytes.py @@ -7,6 +7,7 @@ from docarray.typing.abstract_type import AbstractType from docarray.typing.proto_register import _register_proto +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: from pydantic.fields import BaseConfig, ModelField @@ -77,10 +78,12 @@ class MyAudio(BaseDoc): --- :return: np.ndarray representing the Audio as RGB values """ + if TYPE_CHECKING: + import pydub + else: + pydub = import_library('pydub', raise_error=True) - from pydub import AudioSegment # type: ignore - - segment = AudioSegment.from_file(io.BytesIO(self)) + segment = pydub.AudioSegment.from_file(io.BytesIO(self)) # Convert to float32 using NumPy samples = np.array(segment.get_array_of_samples()) diff --git a/docarray/typing/bytes/image_bytes.py b/docarray/typing/bytes/image_bytes.py index f8e68ba03f0..f8aaf3c6caf 100644 --- a/docarray/typing/bytes/image_bytes.py +++ b/docarray/typing/bytes/image_bytes.py @@ -7,6 +7,7 @@ from docarray.typing.abstract_type import AbstractType from docarray.typing.proto_register import _register_proto +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: from pydantic.fields import BaseConfig, ModelField @@ -88,7 +89,11 @@ class MyDoc(BaseDoc): :return: np.ndarray representing the image as RGB values """ - from PIL import Image as PILImage + if TYPE_CHECKING: + from PIL import Image as PILImage + else: + PIL = import_library('PIL', raise_error=True) # noqa: F841 + from PIL import Image as PILImage raw_img = PILImage.open(BytesIO(self)) if width or height: diff --git a/docarray/typing/bytes/video_bytes.py b/docarray/typing/bytes/video_bytes.py index a48face2b6b..bac2733b8db 100644 --- a/docarray/typing/bytes/video_bytes.py +++ b/docarray/typing/bytes/video_bytes.py @@ -8,6 +8,7 @@ from docarray.typing.abstract_type import AbstractType from docarray.typing.proto_register import _register_proto from docarray.typing.tensor import AudioNdArray, NdArray, VideoNdArray +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: from pydantic.fields import BaseConfig, ModelField @@ -84,7 +85,10 @@ class MyDoc(BaseDoc): av.open() as described [here](https://pyav.org/docs/stable/api/_globals.html?highlight=open#av.open) :return: a VideoLoadResult instance with video, audio and keyframe indices """ - import av + if TYPE_CHECKING: + import av + else: + av = import_library('av') with av.open(BytesIO(self), **kwargs) as container: audio_frames = [] diff --git a/docarray/typing/tensor/__init__.py b/docarray/typing/tensor/__init__.py index 4185f23c22d..4c4077f3cdb 100644 --- a/docarray/typing/tensor/__init__.py +++ b/docarray/typing/tensor/__init__.py @@ -1,9 +1,29 @@ +import types + +from typing_extensions import TYPE_CHECKING + from docarray.typing.tensor.audio import AudioNdArray from docarray.typing.tensor.embedding import AnyEmbedding, NdArrayEmbedding from docarray.typing.tensor.image import ImageNdArray, ImageTensor from docarray.typing.tensor.ndarray import NdArray from docarray.typing.tensor.tensor import AnyTensor from docarray.typing.tensor.video import VideoNdArray +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) + +if TYPE_CHECKING: + from docarray.typing.tensor.audio import AudioTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.audio import AudioTorchTensor # noqa: F401 + from docarray.typing.tensor.embedding import TensorFlowEmbedding # noqa: F401 + from docarray.typing.tensor.embedding import TorchEmbedding # noqa: F401 + from docarray.typing.tensor.image import ImageTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.image import ImageTorchTensor # noqa: F401 + from docarray.typing.tensor.tensorflow_tensor import TensorFlowTensor # noqa: F401 + from docarray.typing.tensor.torch_tensor import TorchTensor # noqa: F401 + from docarray.typing.tensor.video import VideoTensorFlowTensor # noqa: F401 + from docarray.typing.tensor.video import VideoTorchTensor # noqa: F401 __all__ = [ 'NdArray', @@ -16,43 +36,34 @@ 'VideoNdArray', ] -from docarray.utils._internal.misc import is_tf_available, is_torch_available - -torch_available = is_torch_available() -if torch_available: - from docarray.typing.tensor.audio import AudioTorchTensor # noqa: F401 - from docarray.typing.tensor.embedding import TorchEmbedding # noqa: F401 - from docarray.typing.tensor.image import ImageTorchTensor # noqa: F401 - from docarray.typing.tensor.torch_tensor import TorchTensor # noqa: F401 - from docarray.typing.tensor.video import VideoTorchTensor # noqa: F401 - __all__.extend( - [ - 'TorchEmbedding', - 'TorchTensor', - 'ImageTorchTensor', - 'AudioTorchTensor', - 'VideoTorchTensor', - ] - ) +def __getattr__(name: str): + if 'Torch' in name: + import_library('torch', raise_error=True) + elif 'TensorFlow' in name: + import_library('tensorflow', raise_error=True) - torch_available = is_torch_available() + lib: types.ModuleType + if name == 'TorchTensor': + import docarray.typing.tensor.torch_tensor as lib + elif name == 'TensorFlowTensor': + import docarray.typing.tensor.tensorflow_tensor as lib + elif name in ['TorchEmbedding', 'TensorFlowEmbedding']: + import docarray.typing.tensor.embedding as lib + elif name in ['ImageTorchTensor', 'ImageTensorFlowTensor']: + import docarray.typing.tensor.image as lib + elif name in ['AudioTorchTensor', 'AudioTensorFlowTensor']: + import docarray.typing.tensor.audio as lib + elif name in ['VideoTorchTensor', 'VideoTensorFlowTensor']: + import docarray.typing.tensor.video as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + tensor_cls = getattr(lib, name) -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor.audio import AudioTensorFlowTensor # noqa: F401 - from docarray.typing.tensor.embedding import TensorFlowEmbedding # noqa: F401 - from docarray.typing.tensor.image import ImageTensorFlowTensor # noqa: F401 - from docarray.typing.tensor.tensorflow_tensor import TensorFlowTensor # noqa: F401 - from docarray.typing.tensor.video import VideoTensorFlowTensor # noqa: F401 + if name not in __all__: + __all__.append(name) - __all__.extend( - [ - 'TensorFlowEmbedding', - 'TensorFlowTensor', - 'ImageTensorFlowTensor', - 'AudioTensorFlowTensor', - 'VideoTensorFlowTensor', - ] - ) + return tensor_cls diff --git a/docarray/typing/tensor/audio/__init__.py b/docarray/typing/tensor/audio/__init__.py index 4f730451603..a505ab05720 100644 --- a/docarray/typing/tensor/audio/__init__.py +++ b/docarray/typing/tensor/audio/__init__.py @@ -1,20 +1,38 @@ +import types +from typing import TYPE_CHECKING + from docarray.typing.tensor.audio.audio_ndarray import AudioNdArray +from docarray.typing.tensor.audio.audio_tensor import AudioTensor +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) -__all__ = ['AudioNdArray'] +if TYPE_CHECKING: + from docarray.typing.tensor.audio.audio_tensorflow_tensor import ( # noqa + AudioTensorFlowTensor, + ) + from docarray.typing.tensor.audio.audio_torch_tensor import AudioTorchTensor # noqa -from docarray.utils._internal.misc import is_tf_available, is_torch_available +__all__ = ['AudioNdArray', 'AudioTensor'] -torch_available = is_torch_available() -if torch_available: - from docarray.typing.tensor.audio.audio_torch_tensor import AudioTorchTensor # noqa - __all__.extend(['AudioTorchTensor']) +def __getattr__(name: str): + lib: types.ModuleType + if name == 'AudioTorchTensor': + import_library('torch', raise_error=True) + import docarray.typing.tensor.audio.audio_torch_tensor as lib + elif name == 'AudioTensorFlowTensor': + import_library('tensorflow', raise_error=True) + import docarray.typing.tensor.audio.audio_tensorflow_tensor as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + tensor_cls = getattr(lib, name) -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor.audio.audio_tensorflow_tensor import ( # noqa - AudioTensorFlowTensor, - ) + if name not in __all__: + __all__.append(name) - __all__.extend(['AudioTensorFlowTensor']) + return tensor_cls diff --git a/docarray/typing/tensor/audio/abstract_audio_tensor.py b/docarray/typing/tensor/audio/abstract_audio_tensor.py index e84b4ebc13e..05a455e2c6c 100644 --- a/docarray/typing/tensor/audio/abstract_audio_tensor.py +++ b/docarray/typing/tensor/audio/abstract_audio_tensor.py @@ -1,9 +1,9 @@ import warnings from abc import ABC -from typing import Any, BinaryIO, Dict, TypeVar, Union +from typing import TYPE_CHECKING, Any, BinaryIO, Dict, TypeVar, Union from docarray.typing.tensor.abstract_tensor import AbstractTensor -from docarray.utils._internal.misc import is_notebook +from docarray.utils._internal.misc import import_library, is_notebook T = TypeVar('T', bound='AbstractAudioTensor') @@ -37,12 +37,15 @@ def save( :param sample_width: sample width in bytes :param pydub_args: dictionary of additional arguments for pydub.AudioSegment.export function """ - from pydub import AudioSegment # type: ignore + if TYPE_CHECKING: + import pydub + else: + pydub = import_library('pydub', raise_error=True) comp_backend = self.get_comp_backend() channels = 2 if comp_backend.n_dim(array=self) > 1 else 1 # type: ignore - segment = AudioSegment( + segment = pydub.AudioSegment( self.to_bytes(), frame_rate=frame_rate, sample_width=sample_width, diff --git a/docarray/typing/tensor/embedding/__init__.py b/docarray/typing/tensor/embedding/__init__.py index f844b7abaa9..c32048b21c6 100644 --- a/docarray/typing/tensor/embedding/__init__.py +++ b/docarray/typing/tensor/embedding/__init__.py @@ -1,21 +1,37 @@ +import types + +from typing_extensions import TYPE_CHECKING + from docarray.typing.tensor.embedding.embedding import AnyEmbedding from docarray.typing.tensor.embedding.ndarray import NdArrayEmbedding +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) -__all__ = ['NdArrayEmbedding', 'AnyEmbedding'] +if TYPE_CHECKING: + from docarray.typing.tensor.embedding.tensorflow import TensorFlowEmbedding # noqa + from docarray.typing.tensor.embedding.torch import TorchEmbedding # noqa -from docarray.utils._internal.misc import is_tf_available, is_torch_available +__all__ = ['NdArrayEmbedding', 'AnyEmbedding'] -torch_available = is_torch_available() -if torch_available: - from docarray.typing.tensor.embedding.torch import TorchEmbedding # noqa F401 - __all__.append('TorchEmbedding') +def __getattr__(name: str): + lib: types.ModuleType + if name == 'TorchEmbedding': + import_library('torch', raise_error=True) + import docarray.typing.tensor.embedding.torch as lib + elif name == 'TensorFlowEmbedding': + import_library('tensorflow', raise_error=True) + import docarray.typing.tensor.embedding.tensorflow as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + tensor_cls = getattr(lib, name) -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor.embedding.tensorflow import ( # noqa F401 - TensorFlowEmbedding, - ) + if name not in __all__: + __all__.append(name) - __all__.append('TensorFlowEmbedding') + return tensor_cls diff --git a/docarray/typing/tensor/image/__init__.py b/docarray/typing/tensor/image/__init__.py index 2fb32d452ab..7af4b852206 100644 --- a/docarray/typing/tensor/image/__init__.py +++ b/docarray/typing/tensor/image/__init__.py @@ -1,21 +1,39 @@ +import types + +from typing_extensions import TYPE_CHECKING + from docarray.typing.tensor.image.image_ndarray import ImageNdArray from docarray.typing.tensor.image.image_tensor import ImageTensor +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) -__all__ = ['ImageNdArray', 'ImageTensor'] +if TYPE_CHECKING: + from docarray.typing.tensor.image.image_tensorflow_tensor import ( # noqa + ImageTensorFlowTensor, + ) + from docarray.typing.tensor.image.image_torch_tensor import ImageTorchTensor # noqa -from docarray.utils._internal.misc import is_tf_available, is_torch_available +__all__ = ['ImageNdArray', 'ImageTensor'] -torch_available = is_torch_available() -if torch_available: - from docarray.typing.tensor.image.image_torch_tensor import ImageTorchTensor # noqa - __all__.extend(['ImageTorchTensor']) +def __getattr__(name: str): + lib: types.ModuleType + if name == 'ImageTorchTensor': + import_library('torch', raise_error=True) + import docarray.typing.tensor.image.image_torch_tensor as lib + elif name == 'ImageTensorFlowTensor': + import_library('tensorflow', raise_error=True) + import docarray.typing.tensor.image.image_tensorflow_tensor as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + tensor_cls = getattr(lib, name) -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor.image.image_tensorflow_tensor import ( # noqa - ImageTensorFlowTensor, - ) + if name not in __all__: + __all__.append(name) - __all__.extend(['ImageTensorFlowTensor']) + return tensor_cls diff --git a/docarray/typing/tensor/image/abstract_image_tensor.py b/docarray/typing/tensor/image/abstract_image_tensor.py index b02d1452f63..7b033a4ee33 100644 --- a/docarray/typing/tensor/image/abstract_image_tensor.py +++ b/docarray/typing/tensor/image/abstract_image_tensor.py @@ -1,9 +1,10 @@ import io import warnings from abc import ABC +from typing import TYPE_CHECKING from docarray.typing.tensor.abstract_tensor import AbstractTensor -from docarray.utils._internal.misc import is_notebook +from docarray.utils._internal.misc import import_library, is_notebook class AbstractImageTensor(AbstractTensor, ABC): @@ -14,7 +15,11 @@ def to_bytes(self, format: str = 'PNG') -> bytes: :param format: the image format use to store the image, can be 'PNG' , 'JPG' ... :return: bytes """ - from PIL import Image + if TYPE_CHECKING: + from PIL import Image as PILImage + else: + PIL = import_library('PIL', raise_error=True) # noqa: F841 + from PIL import Image as PILImage if format == 'jpg': format = 'jpeg' # unify it to ISO standard @@ -22,7 +27,7 @@ def to_bytes(self, format: str = 'PNG') -> bytes: tensor = self.get_comp_backend().to_numpy(self) mode = 'RGB' if tensor.ndim == 3 else 'L' - pil_image = Image.fromarray(tensor, mode=mode) + pil_image = PILImage.fromarray(tensor, mode=mode) with io.BytesIO() as buffer: pil_image.save(buffer, format=format) @@ -35,10 +40,14 @@ def display(self) -> None: Display image data from tensor in notebook. """ if is_notebook(): - from PIL import Image + if TYPE_CHECKING: + from PIL import Image as PILImage + else: + PIL = import_library('PIL', raise_error=True) # noqa: F841 + from PIL import Image as PILImage np_array = self.get_comp_backend().to_numpy(self) - img = Image.fromarray(np_array) + img = PILImage.fromarray(np_array) from IPython.display import display diff --git a/docarray/typing/tensor/tensorflow_tensor.py b/docarray/typing/tensor/tensorflow_tensor.py index 4f28ab78a47..f0d79aa0b30 100644 --- a/docarray/typing/tensor/tensorflow_tensor.py +++ b/docarray/typing/tensor/tensorflow_tensor.py @@ -1,18 +1,22 @@ from typing import TYPE_CHECKING, Any, Dict, Generic, Type, TypeVar, Union, cast import numpy as np -import tensorflow as tf # type: ignore +from docarray.base_doc.base_node import BaseNode from docarray.typing.proto_register import _register_proto from docarray.typing.tensor.abstract_tensor import AbstractTensor +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: - from pydantic.fields import ModelField + import tensorflow as tf # type: ignore from pydantic import BaseConfig - from docarray.proto import NdArrayProto + from pydantic.fields import ModelField + from docarray.computation.tensorflow_backend import TensorFlowCompBackend + from docarray.proto import NdArrayProto +else: + tf = import_library('tensorflow', raise_error=True) -from docarray.base_doc.base_node import BaseNode T = TypeVar('T', bound='TensorFlowTensor') ShapeT = TypeVar('ShapeT') diff --git a/docarray/typing/tensor/torch_tensor.py b/docarray/typing/tensor/torch_tensor.py index 011208b02bc..1ec05df0086 100644 --- a/docarray/typing/tensor/torch_tensor.py +++ b/docarray/typing/tensor/torch_tensor.py @@ -2,18 +2,22 @@ from typing import TYPE_CHECKING, Any, Dict, Generic, Type, TypeVar, Union, cast import numpy as np -import torch # type: ignore +from docarray.base_doc.base_node import BaseNode from docarray.typing.proto_register import _register_proto from docarray.typing.tensor.abstract_tensor import AbstractTensor +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: - from pydantic.fields import ModelField + import torch from pydantic import BaseConfig - from docarray.proto import NdArrayProto + from pydantic.fields import ModelField + from docarray.computation.torch_backend import TorchCompBackend + from docarray.proto import NdArrayProto +else: + torch = import_library('torch', raise_error=True) -from docarray.base_doc.base_node import BaseNode T = TypeVar('T', bound='TorchTensor') ShapeT = TypeVar('ShapeT') @@ -34,7 +38,10 @@ class metaTorchAndNode( @_register_proto(proto_type_name='torch_tensor') class TorchTensor( - torch.Tensor, AbstractTensor, Generic[ShapeT], metaclass=metaTorchAndNode + torch.Tensor, + AbstractTensor, + Generic[ShapeT], + metaclass=metaTorchAndNode, ): # Subclassing torch.Tensor following the advice from here: # https://pytorch.org/docs/stable/notes/extending.html#subclassing-torch-tensor diff --git a/docarray/typing/tensor/video/__init__.py b/docarray/typing/tensor/video/__init__.py index 424758cfc91..a575e7b6201 100644 --- a/docarray/typing/tensor/video/__init__.py +++ b/docarray/typing/tensor/video/__init__.py @@ -1,20 +1,39 @@ -from docarray.typing.tensor.video.video_ndarray import VideoNdArray +import types -__all__ = ['VideoNdArray'] +from typing_extensions import TYPE_CHECKING -from docarray.utils._internal.misc import is_tf_available, is_torch_available +from docarray.typing.tensor.video.video_ndarray import VideoNdArray +from docarray.typing.tensor.video.video_tensor import VideoTensor +from docarray.utils._internal.misc import ( + _get_path_from_docarray_root_level, + import_library, +) -torch_available = is_torch_available() -if torch_available: +if TYPE_CHECKING: + from docarray.typing.tensor.video.video_tensorflow_tensor import ( # noqa + VideoTensorFlowTensor, + ) from docarray.typing.tensor.video.video_torch_tensor import VideoTorchTensor # noqa - __all__.extend(['VideoTorchTensor']) +__all__ = ['VideoNdArray', 'VideoTensor'] -tf_available = is_tf_available() -if tf_available: - from docarray.typing.tensor.video.video_tensorflow_tensor import ( # noqa: F401 - VideoTensorFlowTensor, - ) +def __getattr__(name: str): + lib: types.ModuleType + if name == 'VideoTorchTensor': + import_library('torch', raise_error=True) + import docarray.typing.tensor.video.video_torch_tensor as lib + elif name == 'VideoTensorFlowTensor': + import_library('tensorflow', raise_error=True) + import docarray.typing.tensor.video.video_tensorflow_tensor as lib + else: + raise ImportError( + f'cannot import name \'{name}\' from \'{_get_path_from_docarray_root_level(__file__)}\'' + ) + + tensor_cls = getattr(lib, name) + + if name not in __all__: + __all__.append(name) - __all__.extend(['VideoTensorFlowTensor']) + return tensor_cls diff --git a/docarray/typing/tensor/video/video_tensor_mixin.py b/docarray/typing/tensor/video/video_tensor_mixin.py index 3d19e499bf4..4ce6a1b7260 100644 --- a/docarray/typing/tensor/video/video_tensor_mixin.py +++ b/docarray/typing/tensor/video/video_tensor_mixin.py @@ -1,13 +1,13 @@ import abc import warnings from io import BytesIO -from typing import Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Optional, Type, TypeVar, Union import numpy as np from docarray.typing.tensor.abstract_tensor import AbstractTensor from docarray.typing.tensor.audio.audio_tensor import AudioTensor -from docarray.utils._internal.misc import is_notebook +from docarray.utils._internal.misc import import_library, is_notebook T = TypeVar('T', bound='VideoTensorMixin') @@ -76,7 +76,10 @@ class MyDoc(BaseDoc): :param audio_format: the name of one of the audio formats supported by PyAV, such as 'flt', 'fltp', 's16' or 's16p'. """ - import av + if TYPE_CHECKING: + import av + else: + av = import_library('av', raise_error=True) np_tensor = self.get_comp_backend().to_numpy(array=self) video_tensor = np_tensor.astype('uint8') diff --git a/docarray/typing/url/url_3d/mesh_url.py b/docarray/typing/url/url_3d/mesh_url.py index 073f4a006a1..2f235b6fb01 100644 --- a/docarray/typing/url/url_3d/mesh_url.py +++ b/docarray/typing/url/url_3d/mesh_url.py @@ -72,7 +72,6 @@ def display(self) -> None: """ Plot mesh from url. This loads the Trimesh instance of the 3D mesh, and then displays it. - To use this you need to install trimesh[easy]: `pip install 'trimesh[easy]'`. """ from IPython.display import display diff --git a/docarray/typing/url/url_3d/point_cloud_url.py b/docarray/typing/url/url_3d/point_cloud_url.py index eba73f5da6f..ac077795a4b 100644 --- a/docarray/typing/url/url_3d/point_cloud_url.py +++ b/docarray/typing/url/url_3d/point_cloud_url.py @@ -92,7 +92,6 @@ def display( ) -> None: """ Plot point cloud from url. - To use this you need to install trimesh[easy]: `pip install 'trimesh[easy]'`. First, it loads the point cloud into a :class:`PointsAndColors` object, and then calls display on it. The following is therefore equivalent: diff --git a/docarray/typing/url/url_3d/url_3d.py b/docarray/typing/url/url_3d/url_3d.py index 31228ccb124..b6d77b60829 100644 --- a/docarray/typing/url/url_3d/url_3d.py +++ b/docarray/typing/url/url_3d/url_3d.py @@ -3,6 +3,7 @@ from docarray.typing.proto_register import _register_proto from docarray.typing.url.any_url import AnyUrl +from docarray.utils._internal.misc import import_library if TYPE_CHECKING: import trimesh @@ -55,7 +56,10 @@ def _load_trimesh_instance( """ import urllib.parse - import trimesh + if TYPE_CHECKING: + import trimesh + else: + trimesh = import_library('trimesh', raise_error=True) if not trimesh_args: trimesh_args = {} diff --git a/docarray/utils/_internal/compress.py b/docarray/utils/_internal/compress.py index 0ff00f8eecd..51b4860fe4a 100644 --- a/docarray/utils/_internal/compress.py +++ b/docarray/utils/_internal/compress.py @@ -1,11 +1,17 @@ -from typing import IO, Callable, Optional +from typing import IO, TYPE_CHECKING, Callable, Optional + +from docarray.utils._internal.misc import import_library def _compress_bytes(data: bytes, algorithm: Optional[str] = None) -> bytes: if algorithm == 'lz4': - import lz4.frame # type: ignore + if TYPE_CHECKING: + from lz4 import frame + else: + lz4 = import_library('lz4', raise_error=True) # noqa: F841 + from lz4 import frame - data = lz4.frame.compress(data) + data = frame.compress(data) elif algorithm == 'bz2': import bz2 @@ -27,9 +33,13 @@ def _compress_bytes(data: bytes, algorithm: Optional[str] = None) -> bytes: def _decompress_bytes(data: bytes, algorithm: Optional[str] = None) -> bytes: if algorithm == 'lz4': - import lz4.frame # type: ignore + if TYPE_CHECKING: + from lz4 import frame + else: + lz4 = import_library('lz4', raise_error=True) # noqa: F841 + from lz4 import frame - data = lz4.frame.decompress(data) + data = frame.decompress(data) elif algorithm == 'bz2': import bz2 @@ -51,10 +61,14 @@ def _decompress_bytes(data: bytes, algorithm: Optional[str] = None) -> bytes: def _get_compress_ctx(algorithm: Optional[str] = None) -> Optional[Callable]: if algorithm == 'lz4': - import lz4.frame # type: ignore + if TYPE_CHECKING: + from lz4 import frame + else: + lz4 = import_library('lz4', raise_error=True) # noqa: F841 + from lz4 import frame def _fun(x: IO[bytes]): - return lz4.frame.LZ4FrameFile(x, 'wb') + return frame.LZ4FrameFile(x, 'wb') compress_ctx = _fun elif algorithm == 'gzip': diff --git a/docarray/utils/_internal/misc.py b/docarray/utils/_internal/misc.py index 99ed9b6696a..9f97ad88ea6 100644 --- a/docarray/utils/_internal/misc.py +++ b/docarray/utils/_internal/misc.py @@ -1,4 +1,8 @@ -from typing import Any +import importlib +import os +import re +import types +from typing import Any, Optional import numpy as np @@ -18,10 +22,58 @@ tf_imported = True +INSTALL_INSTRUCTIONS = { + 'google.protobuf': '"docarray[common]"', + 'lz4': '"docarray[common]"', + 'pandas': '"docarray[pandas]"', + 'PIL': '"docarray[image]"', + 'pydub': '"docarray[audio]"', + 'av': '"docarray[video]"', + 'trimesh': '"docarray[mesh]"', + 'hnswlib': '"docarray[hnswlib]"', + 'elasticsearch': '"docarray[elasticsearch]"', + 'fastapi': '"docarray[web]"', + 'torch': '"docarray[torch]"', + 'tensorflow': 'protobuf==3.19.0 tensorflow', + 'hubble': '"docarray[jac]"', + 'smart_open': '"docarray[aws]"', + 'boto3': '"docarray[aws]"', + 'botocore': '"docarray[aws]"', +} + + +def import_library( + package: str, raise_error: bool = True +) -> Optional[types.ModuleType]: + lib: Optional[types.ModuleType] + try: + lib = importlib.import_module(package) + except (ModuleNotFoundError, ImportError): + lib = None + + if lib is None and raise_error: + raise ImportError( + f'The following required library is not installed: {package} \n' + f'To install all necessary libraries, run: `pip install {INSTALL_INSTRUCTIONS[package]}`.' + ) + else: + return lib + + +def _get_path_from_docarray_root_level(file_path: str) -> str: + path = os.path.dirname(file_path) + rel_path = re.sub('(?s:.*)docarray', 'docarray', path).replace('/', '.') + return rel_path + + def is_torch_available(): return torch_imported +def is_tf_available(): + return tf_imported + + def is_np_int(item: Any) -> bool: dtype = getattr(item, 'dtype', None) ndim = getattr(item, 'ndim', None) @@ -33,10 +85,6 @@ def is_np_int(item: Any) -> bool: return False # this is unreachable, but mypy wants it -def is_tf_available(): - return tf_imported - - def is_notebook() -> bool: """ Check if we're running in a Jupyter notebook, using magic command diff --git a/docs/how_to/add_doc_index.md b/docs/how_to/add_doc_index.md index 4f0125428e1..3d4cfb9b8bc 100644 --- a/docs/how_to/add_doc_index.md +++ b/docs/how_to/add_doc_index.md @@ -9,10 +9,11 @@ This document shows how to add a new Document Index to DocArray. That process can be broken down into a number of basic steps: -1. Create a new class that inherits from `BaseDocIndex` -2. Declare default configurations for your Document Index -3. Implement abstract methods for indexing, searching, and deleting -4. Implement a Query Builder for your Document Index +1. Installation and user instructions +2. Create a new class that inherits from `BaseDocIndex`Create a new class that inherits from `BaseDocIndex` +3. Declare default configurations for your Document Index +4. Implement abstract methods for indexing, searching, and deleting +5. Implement a Query Builder for your Document Index In general, the steps above can be followed in roughly that order. @@ -25,6 +26,46 @@ For an end-to-end example of this process, you can check out the [existing HNSWL For example, HNSWLib can only index vectors, so it uses SQLite to store the rest of the Documents alongside it. This is _not_ how you should store Documents in your implementation! You can find guidance on how you _should_ do it below. + +## Installation and user instructions +Add the library required for your Index via poetry: `poetry add {my_index_lib}`. +In the `pyproject.toml` file, it will look like this: +``` +[tool.poetry.dependencies] +my_index_lib = ">=123.456.789" +``` +Mark it as optional and manually create an extra for it: +``` +[tool.poetry.dependencies] +my_index_lib = {version = ">=0.6.2", optional = true } + +[tool.poetry.extras] +my_index_extra = ["my_index_lib"] +``` + +In case the user tries to use your Index without the correct installs, we want to throw an error with corresponding instructions. + +To enable this, first, add instructions to the `INSTALL_INSTRUCTIONS` dictionary in `docarray/utils/misc.py`, such as +```python +{'my_index_lib': '"docarray[my_index_extra]"'} +``` +Next, ensure to add a case to the `__getattr__()` for your new Index to `docarray/index/__init__.py`. By doing so, the user will be given the instructions, when trying to import `MyIndex` without the correct libraries installed. + +```python +if TYPE_CHECKING: + from docarray.index.backends.my_index import MyIndex # noqa: F401 + + +def __getattr__(name: str): + if name == 'HnswDocumentIndex': + import_library('hnswlib', raise_error=True) + from docarray.index.backends.my_index import MyIndex # noqa + + __all__.append('MyIndex') + return MyIndex +``` +Additionally, wrap the required imports in the file where the `MyIndex` class will be located, such as it was done in `docarray/index/backends/hnswlib.py`. + ## Create a new Document Index class To get started, create a new class that inherits from `BaseDocIndex` and `typing.Generic`: diff --git a/poetry.lock b/poetry.lock index 93569cb83c4..a9bc680af7f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "aiohttp" @@ -610,6 +610,18 @@ files = [ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] +[[package]] +name = "chardet" +version = "5.1.0" +description = "Universal encoding detector for Python 3" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, + {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, +] + [[package]] name = "charset-normalizer" version = "2.0.12" @@ -645,7 +657,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -653,6 +665,24 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "colorlog" +version = "6.7.0" +description = "Add colours to the output of Python's logging module." +category = "main" +optional = true +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.7.0-py2.py3-none-any.whl", hash = "sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662"}, + {file = "colorlog-6.7.0.tar.gz", hash = "sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + [[package]] name = "commonmark" version = "0.9.1" @@ -1123,7 +1153,7 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "importlib-resources" version = "5.10.0" description = "Read resources from Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1340,7 +1370,7 @@ dev = ["hypothesis"] name = "jsonschema" version = "4.17.0" description = "An implementation of JSON Schema validation for Python" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1504,6 +1534,99 @@ docs = ["autodoc-traits", "docutils (<0.19)", "jinja2 (<3.1.0)", "mistune (<1)", openapi = ["openapi-core (>=0.14.2)", "ruamel-yaml"] test = ["codecov", "ipykernel", "jupyter-server[test]", "openapi-core (>=0.14.2,<0.15.0)", "openapi-spec-validator (<0.5)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "requests-mock", "ruamel-yaml", "strict-rfc3339"] +[[package]] +name = "lxml" +version = "4.9.2" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" +files = [ + {file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"}, + {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"}, + {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"}, + {file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"}, + {file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"}, + {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"}, + {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"}, + {file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"}, + {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"}, + {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"}, + {file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"}, + {file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"}, + {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"}, + {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"}, + {file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"}, + {file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"}, + {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"}, + {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"}, + {file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"}, + {file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"}, + {file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"}, + {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"}, + {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"}, + {file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"}, + {file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"}, + {file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"}, + {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"}, + {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"}, + {file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"}, + {file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"}, + {file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"}, + {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"}, + {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"}, + {file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"}, + {file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"}, + {file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"}, + {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"}, + {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"}, + {file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"}, + {file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"}, + {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"}, + {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"}, + {file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] +source = ["Cython (>=0.29.7)"] + [[package]] name = "lz4" version = "4.3.2" @@ -1554,6 +1677,81 @@ docs = ["sphinx (>=1.6.0)", "sphinx-bootstrap-theme"] flake8 = ["flake8"] tests = ["psutil", "pytest (!=3.3.0)", "pytest-cov"] +[[package]] +name = "mapbox-earcut" +version = "1.0.1" +description = "Python bindings for the mapbox earcut C++ polygon triangulation library." +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "mapbox_earcut-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:60f8299b724b5ad1f171c2666a12591845536b0e9318ddc9649f75805096686c"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4af0911ed9d1920c36c54b500ea69fbcc948f409c66f632c75b15fee04c7544e"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:584fd2f7de878f14b3268257ec3c55bac146f1adc1887a64f0ecbf91ee39489f"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20929541c1c9f5fefde45c6c33e8ed3138c7bdd1034ced998877913878f3457c"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:48e8d8ebadd4e4d0dfd87374d43ca3caf8c8e692f1b6897588594d12527d5020"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:352f92997fd39024919a258db29df1642dd98632807ca96e737242adf64b5e96"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-win32.whl", hash = "sha256:5cf359c5ae1a5dcdd6d9c150ec43a820a289c28596ae7c52de09075543cc19ae"}, + {file = "mapbox_earcut-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f5cd49d6e13b3627c6cd6d3a945285e1ce7e9b193f3ce5ca53f0b7b86acd41e"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1e02d61d01aa1239ffbe1b8384cdc224d7c67db604eb7bfc34dd39fb1dc515c2"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d170d0a79b4ef3c9591ec6727a0ab35bae9e267b389122365343d6f55f9027a0"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78945356229992d7aa6da750059f401f329651adc76c000505a0e9e4f93be5df"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66cf29a2434d3366889c69fc50e6d2f9f1abf3a8a4154c7e03ef8f180d3bea40"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a73f6f422932b2758b03f78e92aa5c4d5b5f7ce6456483f5993f4677b0bbde23"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9af9369266bf0ca32f4d401152217c46c699392513f22639c6b1be32bde9c1cc"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-win32.whl", hash = "sha256:ff9a13be4364625697b0e0e04ba6a0f77300148b871bba0a85bfa67e972e85c4"}, + {file = "mapbox_earcut-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e736557539c74fa969e866889c2b0149fc12668f35e3ae33667d837ff2880d3"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:aa6111a18efacb79c081f3d3cdd7d25d0585bb0e9f28896b207ebe1d56efa40e"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2911829d1e6e5e1282fbe2840fadf578f606580f02ed436346c2d51c92f810b"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01ff909a7b8405a923abedd701b53633c997cc2b5dc9d5b78462f51c25ec2c33"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:b7e73477b4ef3951ef5c32848126f047ac7fd2dd04dc033444a85261a346ed08"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:dae325af3553afa4d0ca0caa5afe57dc3d2e3a90a51dfbabc49a5ce1ea1009f7"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-win32.whl", hash = "sha256:29f8f746a9c68f1509084b0c78227d4e142241a2e30aab6def872e53a46f7281"}, + {file = "mapbox_earcut-1.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3c487b93b0e1059b404be4daea62c22cfc8054ffd88591377848c8e399d4abeb"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f85f8d95503dba4612a2dd5c076ed18845a46cea4ba38660e4929efccb5a594a"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8ade6c4822be1680c933bda32af0bb23a73e63e951db348ac1adef8de137239"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04431a498a836c62aba5d807572daf3c8b064b25ab83e79994498455524ce517"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:714d33603c59d7306650615d7b05d51da273f1aa5b41c3b462207271a2283fa7"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:065faa6b4a7525faa48e46e692176cbcf9587ade7a1abdb2c96cb6477ab0004d"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-win32.whl", hash = "sha256:9f433276f54e302aa0c3ef0f8edb7a4092cdd677aafc623fab2b81e1db9f2729"}, + {file = "mapbox_earcut-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2ac93a18a19acffaa7dc42646534f3850b545d6ad31469f3b7157efc9da113db"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b23d0b41d5d7e72fa197e981c3e317f234336b4594bb64252837a0558c9c505d"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:57337d9cf95a97b926eab57845525501df61abb0334ed59502a6485cf9216f64"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5447f35b1dda5f89a6d5c95e9a1831f1c5aaf1eeac853f0b2f3df97ec81c2c75"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dffb3e2a0253e3e2e1b7638df80a029d4d80f38db42a7736f92a8e8d4d1a3209"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:202761e67b0974b1618e638b83a1bb24d0a421a0c773435833a368b9b4f0ee2b"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9c37424997c46f45f16a8ec42fc892a011f9528257f207e2aae4bd14cfcd7c3d"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-win32.whl", hash = "sha256:ed5ec84c85a6e6cbfa294bdcbf567d3fa0abec9191acc8f362552946b8b7b398"}, + {file = "mapbox_earcut-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:da5eeb66f50b01e77340b00f29867fa89df4b9e28646f9a0b8f6b5c8827515fd"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb4aa9a7d1c5f92458d73f460d1f063fbcb38c50ff1f0b7e3485b8dc0f1f6635"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7f779084b11bd74be374be69054803ac36095a68d1a0da1d499a47d3c7f7ccc"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5190425932e82e22e3e35dfb892f5eb441aef155c45fa055da027c72c124b3d1"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68b47dc4ab2aaa9ec163c18bc6133c74739990b5013d17e13bac2d1b5c9afea"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e1b737d4b7b1c52c3915b898714e036990149a422343ec1481ac66b35df17f24"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b77f444324a3b0e91ba2b4b2d533a66503f8fb7103e4901d0064ec2413bff8c"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-win32.whl", hash = "sha256:db61cec2374ff063e314c40b3a868237d2af1b0d98f3ec1217bc0f881e7cc40a"}, + {file = "mapbox_earcut-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:86b8c3732fb93f4e8ed8b1cc8388b93a72d0e9755a00f324e780b15a00fe5bc0"}, + {file = "mapbox_earcut-1.0.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0b5ad819f3fd57fc8a18c7b61a244e63b2a24475195f57e826a066e007a7a877"}, + {file = "mapbox_earcut-1.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:732e5c86037692f6c635dc4e139520be8366cde0fd39dbe122480f657b2cca90"}, + {file = "mapbox_earcut-1.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cf7c0d0d862addc99fe0b33150c8f5c06baafa320b6dd6f67d17309512d1e9a"}, + {file = "mapbox_earcut-1.0.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8416071bd3af616afab4513347b064274899f73e0ffe309c2a1be66600736c98"}, + {file = "mapbox_earcut-1.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1310c3e208e0bfd6da090ae65226ee49adba4078fe1ed2d95197c3b97ad513b9"}, + {file = "mapbox_earcut-1.0.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b657a30f677de4005f497c79ab3bb2827ba01e2642cb58ac30242f7cff48e40b"}, + {file = "mapbox_earcut-1.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34e3476d9af878887fd0d9cce759d6951fe0cc6c240e13afed1ff38fc23fc9d5"}, + {file = "mapbox_earcut-1.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e480ce4794b0c391f0b829362c78ec74b690104ef36866160a7e14232b2d3779"}, + {file = "mapbox_earcut-1.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c21271dd89263d037af5caeac425e54a8fba727ea30d1b42e3ce94cc675df15a"}, + {file = "mapbox_earcut-1.0.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11c784ba52c981dcf709bcc8de99d75a214a476f7c16369d219ca4751c7f6f6f"}, + {file = "mapbox_earcut-1.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be37a75c94017a2efaffc8763475867d4860fc4cb3262b6839d635690403d28f"}, + {file = "mapbox_earcut-1.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ad50f947d44c8c1c0900c3e1869a4a550509450117b87b0368b06014f66590b"}, + {file = "mapbox_earcut-1.0.1.tar.gz", hash = "sha256:9f155e429a22e27387cfd7a6372c3a3865aafa609ad725e2c4465257f154a438"}, +] + +[package.dependencies] +numpy = "*" + +[package.extras] +test = ["pytest"] + [[package]] name = "markdown" version = "3.3.7" @@ -1816,6 +2014,24 @@ files = [ [package.extras] test = ["pytest (>=4.0.2)"] +[[package]] +name = "mpmath" +version = "1.3.0" +description = "Python library for arbitrary-precision floating-point arithmetic" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] + +[package.extras] +develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] +tests = ["pytest (>=4.6)"] + [[package]] name = "multidict" version = "6.0.4" @@ -2107,6 +2323,25 @@ files = [ {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, ] +[[package]] +name = "networkx" +version = "2.6.3" +description = "Python package for creating and manipulating graphs and networks" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "networkx-2.6.3-py3-none-any.whl", hash = "sha256:80b6b89c77d1dfb64a4c7854981b60aeea6360ac02c6d4e4913319e0a313abef"}, + {file = "networkx-2.6.3.tar.gz", hash = "sha256:c0946ed31d71f1b732b5aaa6da5a0388a345019af232ce2f49c766e2d6795c51"}, +] + +[package.extras] +default = ["matplotlib (>=3.3)", "numpy (>=1.19)", "pandas (>=1.1)", "scipy (>=1.5,!=1.6.1)"] +developer = ["black (==21.5b1)", "pre-commit (>=2.12)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.1)", "pillow (>=8.2)", "pydata-sphinx-theme (>=0.6,<1.0)", "sphinx (>=4.0,<5.0)", "sphinx-gallery (>=0.9,<1.0)", "texext (>=0.6.6)"] +extra = ["lxml (>=4.5)", "pydot (>=1.4.1)", "pygraphviz (>=1.7)"] +test = ["codecov (>=2.1)", "pytest (>=6.2)", "pytest-cov (>=2.12)"] + [[package]] name = "nodeenv" version = "1.7.0" @@ -2532,7 +2767,7 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." -category = "dev" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2712,6 +2947,24 @@ files = [ {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, ] +[[package]] +name = "pycollada" +version = "0.7.2" +description = "python library for reading and writing collada documents" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "pycollada-0.7.2.tar.gz", hash = "sha256:70a2630ed499bdab718c0e61a3e6ae3698130d7e4654e89cdecde51bfdaea56f"}, +] + +[package.dependencies] +python-dateutil = ">=2.2" + +[package.extras] +prettyprint = ["lxml"] +validation = ["lxml"] + [[package]] name = "pycparser" version = "2.21" @@ -2839,7 +3092,7 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pyrsistent" version = "0.19.2" description = "Persistent/Functional/Immutable data structures" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3326,6 +3579,64 @@ files = [ [package.dependencies] pyasn1 = ">=0.1.3" +[[package]] +name = "rtree" +version = "1.0.1" +description = "R-Tree spatial index for Python GIS" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "Rtree-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9855b8f11cdad99c56eb361b7b632a4fbd3d8cbe3f2081426b445f0cfb7fdca9"}, + {file = "Rtree-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:18ce7e4d04b85c48f2d364835620b3b20e38e199639746e7b12f07a2303e18ff"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:784efa6b7be9e99b33613ae8495931032689441eabb6120c9b3eb91188c33794"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:157207191aebdacbbdbb369e698cfbfebce53bc97114e96c8af5bed3126475f1"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5fb3671a8d440c24b1dd29ec621d4345ced7185e26f02abe98e85a6629fcb50"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:11d16f51cf9205cd6995af36e24efe8f184270f667fb49bb69b09fc46b97e7d4"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6db6a0a93e41594ffc14b053f386dd414ab5a82535bbd9aedafa6ac8dc0650d8"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6e29e5eb3083ad12ac5c1ce6e37465ea3428d894d3466cc9c9e2ee4bf768e53"}, + {file = "Rtree-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:656b148589c0b5bab4a7db4d033634329f42a5feaac10ca40aceeca109d83c1f"}, + {file = "Rtree-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b2c15f9373ba314c83a8df5cb6d99b4e3af23c376c6b1317add995432dd0970"}, + {file = "Rtree-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93c5e0bf31e76b4f92a6eec3d2891e938408774c75a8ed6ac3d2c8db04a2be33"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6792de0e3c2fd3ad7e069445027603bec7a47000432f49c80246886311f4f152"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:004e131b570dc360a49e7f3b60e7bc6517943a54df056587964d1cb903889e7e"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:becd711fe97c2e09b1b7969e83080a3c8012bce2d30f6db879aade255fcba5c1"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:015df09e1bc55ddf7c88799bf1515d058cd0ee78eacf4cd443a32876d3b3a863"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c2973b76f61669a85e160b4ad09879c4089fc0e3f20fd99adf161ca298fe8374"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e4335e131a58952635560a003458011d97f9ea6f3c010dc24906050b42ee2c03"}, + {file = "Rtree-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:e7ca5d743f6a1dc62653dfac8ee7ce2e1ba91be7cf97916a7f60b7cbe48fb48d"}, + {file = "Rtree-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2ee7165e9872a026ccb868c021711eba39cedf7d1820763c9de52d5324691a92"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8de99f28af0f1783eefb80918959903b4b18112f6a12b48f296ecb162804e69d"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a94e2f4bf74bd202ea8b67ea3d7c71e763ad41f79be1d6b72aa2c8d5a8e92c4"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5120da3a1b96f3a7a17dd6af0afdd4e6f3cc9baa87e9ee0a272882f01f980bb"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7e3d5f0e7b28250afbb290ab88b49aa0f121c9714d0da2080581783690347507"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:296203e933b6ec0dd07f6a7456c4f1492def95b6993f20cc61c92b0fee0aecc5"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:77908cd7acdd519a731979ebf5baff8afd102109c2f52864c1e6ee75d3ea2d87"}, + {file = "Rtree-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1a213e5d385278ca7668bc5b27083f8d6e39996a9bd59b6528f3a30009dae4ed"}, + {file = "Rtree-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cfa8cffec5cb9fed494c4bb335ebdb69b3c26178b0b685f67f79296c6b3d800c"}, + {file = "Rtree-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b31fd22d214160859d038da7cb2aaa27acb71efc24a7bcc75c84b5e502721549"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d68a81ad419d5c2ea5fecc677e6c178666c057e2c7b24100a6c48392196f1e9"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62f38020af47b765adc6b0bc7c4e810c6c3d1eab44ba339b592ff25a4c0dc0a7"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50b658a6707f215a0056d52e9f83a97148c0af62dea07cf29b3789a2c429e78a"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3573cbb0de872f54d0a0c29596a84e8ac3939c47ca3bece4a82e92775730a0d0"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5abe5a19d943a88bea14901970e4c53e4579fc2662404cdea6163bf4c04d49a"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1e894112cef4de6c518bdea0b43eada65f12888c3645cc437c3a677aa023039f"}, + {file = "Rtree-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:582854252b8fd5c8472478af060635434931fb55edd269bac128cbf2eef43620"}, + {file = "Rtree-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b54057e8a8ad92c1d8e9eaa5cf32aad70dde454abbf9b638e9d6024520a52c02"}, + {file = "Rtree-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:698de8ce6c62e159d93b35bacf64bcf3619077b5367bc88cd2cff5e0bc36169b"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:273ee61783de3a1664e5f868feebf5eea4629447137751bfa4087b0f82093082"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16900ee02cf5c198a42b03635268a80f606aa102f3f7618b89f75023d406da1c"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ce4a6fdb63254a4c1efebe7a4f7a59b1c333c703bde4ae715d9ad88c833e10b"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5b20f69e040a05503b22297af223f336fe7047909b57e4b207b98292f33a229f"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:57128293dd625cb1f07726f32208097953e8854d70ab1fc55d6858733618b9ed"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e898d7409ab645c25e06d4e058f99271182601d70b2887aba3351bf08e09a0c6"}, + {file = "Rtree-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ad9912faeddb1ddcec5e26b33089166d58a107af6862d8b7f1bb2b7c0002ab39"}, + {file = "Rtree-1.0.1.tar.gz", hash = "sha256:222121699c303a64065d849bf7038b1ecabc37b65c7fa340bedb38ef0e805429"}, +] + +[package.dependencies] +typing-extensions = {version = ">=3.7", markers = "python_version < \"3.8\""} + [[package]] name = "ruff" version = "0.0.243" @@ -3370,6 +3681,38 @@ botocore = ">=1.12.36,<2.0a.0" [package.extras] crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] +[[package]] +name = "scipy" +version = "1.6.1" +description = "SciPy: Scientific Library for Python" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "scipy-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76"}, + {file = "scipy-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092"}, + {file = "scipy-1.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261"}, + {file = "scipy-1.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced"}, + {file = "scipy-1.6.1-cp37-cp37m-win32.whl", hash = "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78"}, + {file = "scipy-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c"}, + {file = "scipy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519"}, + {file = "scipy-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345"}, + {file = "scipy-1.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d"}, + {file = "scipy-1.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d"}, + {file = "scipy-1.6.1-cp38-cp38-win32.whl", hash = "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4"}, + {file = "scipy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf"}, + {file = "scipy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67"}, + {file = "scipy-1.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627"}, + {file = "scipy-1.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0"}, + {file = "scipy-1.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07"}, + {file = "scipy-1.6.1-cp39-cp39-win32.whl", hash = "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4"}, + {file = "scipy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f"}, + {file = "scipy-1.6.1.tar.gz", hash = "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11"}, +] + +[package.dependencies] +numpy = ">=1.16.5" + [[package]] name = "send2trash" version = "1.8.0" @@ -3404,6 +3747,61 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-g testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "shapely" +version = "2.0.1" +description = "Manipulation and analysis of geometric objects" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "shapely-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b06d031bc64149e340448fea25eee01360a58936c89985cf584134171e05863f"}, + {file = "shapely-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9a6ac34c16f4d5d3c174c76c9d7614ec8fe735f8f82b6cc97a46b54f386a86bf"}, + {file = "shapely-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:865bc3d7cc0ea63189d11a0b1120d1307ed7a64720a8bfa5be2fde5fc6d0d33f"}, + {file = "shapely-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45b4833235b90bc87ee26c6537438fa77559d994d2d3be5190dd2e54d31b2820"}, + {file = "shapely-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce88ec79df55430e37178a191ad8df45cae90b0f6972d46d867bf6ebbb58cc4d"}, + {file = "shapely-2.0.1-cp310-cp310-win32.whl", hash = "sha256:01224899ff692a62929ef1a3f5fe389043e262698a708ab7569f43a99a48ae82"}, + {file = "shapely-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:da71de5bf552d83dcc21b78cc0020e86f8d0feea43e202110973987ffa781c21"}, + {file = "shapely-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:502e0a607f1dcc6dee0125aeee886379be5242c854500ea5fd2e7ac076b9ce6d"}, + {file = "shapely-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7d3bbeefd8a6a1a1017265d2d36f8ff2d79d0162d8c141aa0d37a87063525656"}, + {file = "shapely-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f470a130d6ddb05b810fc1776d918659407f8d025b7f56d2742a596b6dffa6c7"}, + {file = "shapely-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4641325e065fd3e07d55677849c9ddfd0cf3ee98f96475126942e746d55b17c8"}, + {file = "shapely-2.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90cfa4144ff189a3c3de62e2f3669283c98fb760cfa2e82ff70df40f11cadb39"}, + {file = "shapely-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70a18fc7d6418e5aea76ac55dce33f98e75bd413c6eb39cfed6a1ba36469d7d4"}, + {file = "shapely-2.0.1-cp311-cp311-win32.whl", hash = "sha256:09d6c7763b1bee0d0a2b84bb32a4c25c6359ad1ac582a62d8b211e89de986154"}, + {file = "shapely-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d8f55f355be7821dade839df785a49dc9f16d1af363134d07eb11e9207e0b189"}, + {file = "shapely-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:83a8ec0ee0192b6e3feee9f6a499d1377e9c295af74d7f81ecba5a42a6b195b7"}, + {file = "shapely-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a529218e72a3dbdc83676198e610485fdfa31178f4be5b519a8ae12ea688db14"}, + {file = "shapely-2.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91575d97fd67391b85686573d758896ed2fc7476321c9d2e2b0c398b628b961c"}, + {file = "shapely-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8b0d834b11be97d5ab2b4dceada20ae8e07bcccbc0f55d71df6729965f406ad"}, + {file = "shapely-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:b4f0711cc83734c6fad94fc8d4ec30f3d52c1787b17d9dca261dc841d4731c64"}, + {file = "shapely-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:05c51a29336e604c084fb43ae5dbbfa2c0ef9bd6fedeae0a0d02c7b57a56ba46"}, + {file = "shapely-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b519cf3726ddb6c67f6a951d1bb1d29691111eaa67ea19ddca4d454fbe35949c"}, + {file = "shapely-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:193a398d81c97a62fc3634a1a33798a58fd1dcf4aead254d080b273efbb7e3ff"}, + {file = "shapely-2.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e55698e0ed95a70fe9ff9a23c763acfe0bf335b02df12142f74e4543095e9a9b"}, + {file = "shapely-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f32a748703e7bf6e92dfa3d2936b2fbfe76f8ce5f756e24f49ef72d17d26ad02"}, + {file = "shapely-2.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a34a23d6266ca162499e4a22b79159dc0052f4973d16f16f990baa4d29e58b6"}, + {file = "shapely-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d173d24e85e51510e658fb108513d5bc11e3fd2820db6b1bd0522266ddd11f51"}, + {file = "shapely-2.0.1-cp38-cp38-win32.whl", hash = "sha256:3cb256ae0c01b17f7bc68ee2ffdd45aebf42af8992484ea55c29a6151abe4386"}, + {file = "shapely-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:c7eed1fb3008a8a4a56425334b7eb82651a51f9e9a9c2f72844a2fb394f38a6c"}, + {file = "shapely-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ac1dfc397475d1de485e76de0c3c91cc9d79bd39012a84bb0f5e8a199fc17bef"}, + {file = "shapely-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33403b8896e1d98aaa3a52110d828b18985d740cc9f34f198922018b1e0f8afe"}, + {file = "shapely-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2569a4b91caeef54dd5ae9091ae6f63526d8ca0b376b5bb9fd1a3195d047d7d4"}, + {file = "shapely-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a70a614791ff65f5e283feed747e1cc3d9e6c6ba91556e640636bbb0a1e32a71"}, + {file = "shapely-2.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c43755d2c46b75a7b74ac6226d2cc9fa2a76c3263c5ae70c195c6fb4e7b08e79"}, + {file = "shapely-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad81f292fffbd568ae71828e6c387da7eb5384a79db9b4fde14dd9fdeffca9a"}, + {file = "shapely-2.0.1-cp39-cp39-win32.whl", hash = "sha256:b50c401b64883e61556a90b89948297f1714dbac29243d17ed9284a47e6dd731"}, + {file = "shapely-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:bca57b683e3d94d0919e2f31e4d70fdfbb7059650ef1b431d9f4e045690edcd5"}, + {file = "shapely-2.0.1.tar.gz", hash = "sha256:66a6b1a3e72ece97fc85536a281476f9b7794de2e646ca8a4517e2e3c1446893"}, +] + +[package.dependencies] +numpy = ">=1.14" + +[package.extras] +docs = ["matplotlib", "numpydoc (>=1.1.0,<1.2.0)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov"] + [[package]] name = "six" version = "1.16.0" @@ -3484,6 +3882,36 @@ typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\"" [package.extras] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +[[package]] +name = "svg-path" +version = "6.2" +description = "SVG path objects and parser" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "svg.path-6.2-py2.py3-none-any.whl", hash = "sha256:c3b12e6d372771b466078837252eb13b655ea2658437c426cc67fc6262433dc8"}, + {file = "svg.path-6.2.tar.gz", hash = "sha256:1a2159f9db898df93c4637cfd3ccaf7da1fd073f59fa9a5950c73e46d4aa1aca"}, +] + +[package.extras] +test = ["Pillow", "pytest", "pytest-cov"] + +[[package]] +name = "sympy" +version = "1.10.1" +description = "Computer algebra system (CAS) in Python" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "sympy-1.10.1-py3-none-any.whl", hash = "sha256:df75d738930f6fe9ebe7034e59d56698f29e85f443f743e51e47df0caccc2130"}, + {file = "sympy-1.10.1.tar.gz", hash = "sha256:5939eeffdf9e152172601463626c022a2c27e75cf6278de8d401d50c9d58787b"}, +] + +[package.dependencies] +mpmath = ">=0.19" + [[package]] name = "terminado" version = "0.17.0" @@ -3628,23 +4056,39 @@ test = ["pre-commit", "pytest"] [[package]] name = "trimesh" -version = "3.17.1" +version = "3.21.2" description = "Import, export, process, analyze and view triangular meshes." category = "main" optional = true python-versions = "*" files = [ - {file = "trimesh-3.17.1-py3-none-any.whl", hash = "sha256:a09460ee4e11c32bf9f0643b86241b3e3e2aa86296c4912a0738b76da3034c00"}, - {file = "trimesh-3.17.1.tar.gz", hash = "sha256:025bb2fa3a2e87bdd6873f11db45a7ca19216f2f8b6aed29140fca57e32c298e"}, + {file = "trimesh-3.21.2-py3-none-any.whl", hash = "sha256:8a575f2ee4dc77fc680aa1545c3503619027c75d09bcc4878d29d5f32e0476ee"}, + {file = "trimesh-3.21.2.tar.gz", hash = "sha256:5513c4fb540b286cb95bdf626b906e3cdb661ff7a85ee940a52f27f1275049a4"}, ] [package.dependencies] +chardet = {version = "*", optional = true, markers = "extra == \"easy\""} +colorlog = {version = "*", optional = true, markers = "extra == \"easy\""} +jsonschema = {version = "*", optional = true, markers = "extra == \"easy\""} +lxml = {version = "*", optional = true, markers = "extra == \"easy\""} +mapbox-earcut = {version = "*", optional = true, markers = "extra == \"easy\""} +networkx = {version = "*", optional = true, markers = "extra == \"easy\""} numpy = "*" +pillow = {version = "*", optional = true, markers = "extra == \"easy\""} +pycollada = {version = "*", optional = true, markers = "extra == \"easy\""} +requests = {version = "*", optional = true, markers = "extra == \"easy\""} +rtree = {version = "*", optional = true, markers = "extra == \"easy\""} +scipy = {version = "*", optional = true, markers = "extra == \"easy\""} +setuptools = {version = "*", optional = true, markers = "extra == \"easy\""} +shapely = {version = "*", optional = true, markers = "extra == \"easy\""} +"svg.path" = {version = "*", optional = true, markers = "extra == \"easy\""} +sympy = {version = "*", optional = true, markers = "extra == \"easy\""} +xxhash = {version = "*", optional = true, markers = "extra == \"easy\""} [package.extras] -all = ["chardet", "colorlog", "glooey", "jsonschema", "lxml", "mapbox-earcut", "meshio", "msgpack", "networkx", "pillow", "psutil", "pycollada", "pyglet (<2)", "python-fcl", "requests", "rtree", "scikit-image", "scipy", "setuptools", "shapely", "svg.path", "sympy", "xatlas", "xxhash"] -easy = ["chardet", "colorlog", "jsonschema", "lxml", "mapbox-earcut", "msgpack", "networkx", "pillow", "pycollada", "pyglet (<2)", "requests", "rtree", "scipy", "setuptools", "shapely", "svg.path", "sympy", "xxhash"] -test = ["coveralls", "ezdxf", "pyinstrument", "pytest", "pytest-cov"] +all = ["chardet", "colorlog", "glooey", "jsonschema", "lxml", "mapbox-earcut", "meshio", "networkx", "pillow", "psutil", "pycollada", "pyglet (<2)", "python-fcl", "requests", "rtree", "scikit-image", "scipy", "setuptools", "shapely", "svg.path", "sympy", "xatlas", "xxhash"] +easy = ["chardet", "colorlog", "jsonschema", "lxml", "mapbox-earcut", "networkx", "pillow", "pycollada", "requests", "rtree", "scipy", "setuptools", "shapely", "svg.path", "sympy", "xxhash"] +test = ["autopep8", "coveralls", "ezdxf", "pyinstrument", "pytest", "pytest-cov", "ruff"] [[package]] name = "typed-ast" @@ -3930,6 +4374,114 @@ files = [ [package.extras] test = ["pytest (>=3.0.0)"] +[[package]] +name = "xxhash" +version = "3.2.0" +description = "Python binding for xxHash" +category = "main" +optional = true +python-versions = ">=3.6" +files = [ + {file = "xxhash-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:af44b9e59c4b2926a4e3c7f9d29949ff42fcea28637ff6b8182e654461932be8"}, + {file = "xxhash-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1bdd57973e2b802ef32553d7bebf9402dac1557874dbe5c908b499ea917662cd"}, + {file = "xxhash-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b7c9aa77bbce61a5e681bd39cb6a804338474dcc90abe3c543592aa5d6c9a9b"}, + {file = "xxhash-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11bf87dc7bb8c3b0b5e24b7b941a9a19d8c1f88120b6a03a17264086bc8bb023"}, + {file = "xxhash-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2783d41487ce6d379fdfaa7332fca5187bf7010b9bddcf20cafba923bc1dc665"}, + {file = "xxhash-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:561076ca0dcef2fbc20b2bc2765bff099e002e96041ae9dbe910a863ca6ee3ea"}, + {file = "xxhash-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a26eeb4625a6e61cedc8c1b39b89327c9c7e1a8c2c4d786fe3f178eb839ede6"}, + {file = "xxhash-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d93a44d0104d1b9b10de4e7aadf747f6efc1d7ec5ed0aa3f233a720725dd31bd"}, + {file = "xxhash-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:89585adc73395a10306d2e2036e50d6c4ac0cf8dd47edf914c25488871b64f6d"}, + {file = "xxhash-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a892b4b139126a86bfdcb97cd912a2f8c4e8623869c3ef7b50871451dd7afeb0"}, + {file = "xxhash-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e998efb190653f70e0f30d92b39fc645145369a4823bee46af8ddfc244aa969d"}, + {file = "xxhash-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e8ed3bd2b8bb3277710843ca63e4f5c3ee6f8f80b083be5b19a7a9905420d11e"}, + {file = "xxhash-3.2.0-cp310-cp310-win32.whl", hash = "sha256:20181cbaed033c72cb881b2a1d13c629cd1228f113046133469c9a48cfcbcd36"}, + {file = "xxhash-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:a0f7a16138279d707db778a63264d1d6016ac13ffd3f1e99f54b2855d6c0d8e1"}, + {file = "xxhash-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5daff3fb5bfef30bc5a2cb143810d376d43461445aa17aece7210de52adbe151"}, + {file = "xxhash-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75bb5be3c5de702a547715f320ecf5c8014aeca750ed5147ca75389bd22e7343"}, + {file = "xxhash-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01f36b671ff55cb1d5c2f6058b799b697fd0ae4b4582bba6ed0999678068172a"}, + {file = "xxhash-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4d4519123aac73c93159eb8f61db9682393862dd669e7eae034ecd0a35eadac"}, + {file = "xxhash-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:994e4741d5ed70fc2a335a91ef79343c6b1089d7dfe6e955dd06f8ffe82bede6"}, + {file = "xxhash-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919bc1b010aa6ff0eb918838ff73a435aed9e9a19c3202b91acecd296bf75607"}, + {file = "xxhash-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17b65454c5accbb079c45eca546c27c4782f5175aa320758fafac896b1549d27"}, + {file = "xxhash-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b0c094d5e65a46dbf3fe0928ff20873a747e6abfd2ed4b675beeb2750624bc2e"}, + {file = "xxhash-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f94163ebe2d5546e6a5977e96d83621f4689c1054053428cf8d4c28b10f92f69"}, + {file = "xxhash-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cead7c0307977a00b3f784cff676e72c147adbcada19a2e6fc2ddf54f37cf387"}, + {file = "xxhash-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a0e1bd0260c1da35c1883321ce2707ceea07127816ab625e1226ec95177b561a"}, + {file = "xxhash-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc8878935671490efe9275fb4190a6062b73277bd273237179b9b5a2aa436153"}, + {file = "xxhash-3.2.0-cp311-cp311-win32.whl", hash = "sha256:a433f6162b18d52f7068175d00bd5b1563b7405f926a48d888a97b90a160c40d"}, + {file = "xxhash-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:a32d546a1752e4ee7805d6db57944f7224afa7428d22867006b6486e4195c1f3"}, + {file = "xxhash-3.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:82daaab720866bf690b20b49de5640b0c27e3b8eea2d08aa75bdca2b0f0cfb63"}, + {file = "xxhash-3.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3126df6520cbdbaddd87ce74794b2b6c45dd2cf6ac2b600a374b8cdb76a2548c"}, + {file = "xxhash-3.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e172c1ee40507ae3b8d220f4048aaca204f203e1e4197e8e652f5c814f61d1aa"}, + {file = "xxhash-3.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5384f1d9f30876f5d5b618464fb19ff7ce6c0fe4c690fbaafd1c52adc3aae807"}, + {file = "xxhash-3.2.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26cb52174a7e96a17acad27a3ca65b24713610ac479c99ac9640843822d3bebf"}, + {file = "xxhash-3.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbcd613a5e76b1495fc24db9c37a6b7ee5f214fd85979187ec4e032abfc12ded"}, + {file = "xxhash-3.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f988daf25f31726d5b9d0be6af636ca9000898f9ea43a57eac594daea25b0948"}, + {file = "xxhash-3.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:bbc30c98ab006ab9fc47e5ed439c00f706bc9d4441ff52693b8b6fea335163e0"}, + {file = "xxhash-3.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:2408d49260b0a4a7cc6ba445aebf38e073aeaf482f8e32767ca477e32ccbbf9e"}, + {file = "xxhash-3.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:3f4152fd0bf8b03b79f2f900fd6087a66866537e94b5a11fd0fd99ef7efe5c42"}, + {file = "xxhash-3.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0eea848758e4823a01abdbcccb021a03c1ee4100411cbeeb7a5c36a202a0c13c"}, + {file = "xxhash-3.2.0-cp36-cp36m-win32.whl", hash = "sha256:77709139af5123c578ab06cf999429cdb9ab211047acd0c787e098dcb3f1cb4d"}, + {file = "xxhash-3.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:91687671fd9d484a4e201ad266d366b695a45a1f2b41be93d116ba60f1b8f3b3"}, + {file = "xxhash-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e4af8bc5c3fcc2192c266421c6aa2daab1a18e002cb8e66ef672030e46ae25cf"}, + {file = "xxhash-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8be562e2ce3e481d9209b6f254c3d7c5ff920eb256aba2380d2fb5ba75d4f87"}, + {file = "xxhash-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9eba0c7c12126b12f7fcbea5513f28c950d28f33d2a227f74b50b77789e478e8"}, + {file = "xxhash-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2198c4901a0223c48f6ec0a978b60bca4f4f7229a11ca4dc96ca325dd6a29115"}, + {file = "xxhash-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50ce82a71b22a3069c02e914bf842118a53065e2ec1c6fb54786e03608ab89cc"}, + {file = "xxhash-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5019fb33711c30e54e4e57ae0ca70af9d35b589d385ac04acd6954452fa73bb"}, + {file = "xxhash-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0d54ac023eef7e3ac9f0b8841ae8a376b933043bc2ad428121346c6fa61c491c"}, + {file = "xxhash-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c55fa832fc3fe64e0d29da5dc9b50ba66ca93312107cec2709300ea3d3bab5c7"}, + {file = "xxhash-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4ce006215497993ae77c612c1883ca4f3973899573ce0c52fee91f0d39c4561"}, + {file = "xxhash-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1afb9b9d27fd675b436cb110c15979976d92d761ad6e66799b83756402f3a974"}, + {file = "xxhash-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:baa99cebf95c1885db21e119395f222a706a2bb75a545f0672880a442137725e"}, + {file = "xxhash-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:75aa692936942ccb2e8fd6a386c81c61630ac1b6d6e921698122db8a930579c3"}, + {file = "xxhash-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0a2cdfb5cae9fafb9f7b65fd52ecd60cf7d72c13bb2591ea59aaefa03d5a8827"}, + {file = "xxhash-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a68d1e8a390b660d94b9360ae5baa8c21a101bd9c4790a8b30781bada9f1fc6"}, + {file = "xxhash-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ce7c3ce28f94302df95eaea7c9c1e2c974b6d15d78a0c82142a97939d7b6c082"}, + {file = "xxhash-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dcb419bf7b0bc77d366e5005c25682249c5521a63fd36c51f584bd91bb13bd5"}, + {file = "xxhash-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae521ed9287f86aac979eeac43af762f03d9d9797b2272185fb9ddd810391216"}, + {file = "xxhash-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0d16775094423088ffa357d09fbbb9ab48d2fb721d42c0856b801c86f616eec"}, + {file = "xxhash-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe454aeab348c42f56d6f7434ff758a3ef90787ac81b9ad5a363cd61b90a1b0b"}, + {file = "xxhash-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052fd0efdd5525c2dbc61bebb423d92aa619c4905bba605afbf1e985a562a231"}, + {file = "xxhash-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:02badf3754e2133de254a4688798c4d80f0060635087abcb461415cb3eb82115"}, + {file = "xxhash-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:66b8a90b28c13c2aae7a71b32638ceb14cefc2a1c8cf23d8d50dfb64dfac7aaf"}, + {file = "xxhash-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:649cdf19df175925ad87289ead6f760cd840730ee85abc5eb43be326a0a24d97"}, + {file = "xxhash-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4b948a03f89f5c72d69d40975af8af241111f0643228796558dc1cae8f5560b0"}, + {file = "xxhash-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49f51fab7b762da7c2cee0a3d575184d3b9be5e2f64f26cae2dd286258ac9b3c"}, + {file = "xxhash-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1a42994f0d42b55514785356722d9031f064fd34e495b3a589e96db68ee0179d"}, + {file = "xxhash-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0a6d58ba5865475e53d6c2c4fa6a62e2721e7875e146e2681e5337a6948f12e7"}, + {file = "xxhash-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:aabdbc082030f8df613e2d2ea1f974e7ad36a539bdfc40d36f34e55c7e4b8e94"}, + {file = "xxhash-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:498843b66b9ca416e9d03037e5875c8d0c0ab9037527e22df3b39aa5163214cd"}, + {file = "xxhash-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a910b1193cd90af17228f5d6069816646df0148f14f53eefa6b2b11a1dedfcd0"}, + {file = "xxhash-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb6d8ce31dc25faf4da92991320e211fa7f42de010ef51937b1dc565a4926501"}, + {file = "xxhash-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:883dc3d3942620f4c7dbc3fd6162f50a67f050b714e47da77444e3bcea7d91cc"}, + {file = "xxhash-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dc8bfacf89b8f5be54d55bc3b4bd6d74d0c5320c8a63d2538ac7df5b96f1d5"}, + {file = "xxhash-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61e6aa1d30c2af692aa88c4dd48709426e8b37bff6a574ee2de677579c34a3d6"}, + {file = "xxhash-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:314ec0bd21f0ee8d30f2bd82ed3759314bd317ddbbd8555668f3d20ab7a8899a"}, + {file = "xxhash-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dad638cde3a5357ad3163b80b3127df61fb5b5e34e9e05a87697144400ba03c7"}, + {file = "xxhash-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:eaa3ea15025b56076d806b248948612289b093e8dcda8d013776b3848dffff15"}, + {file = "xxhash-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7deae3a312feb5c17c97cbf18129f83cbd3f1f9ec25b0f50e2bd9697befb22e7"}, + {file = "xxhash-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:add774341c09853b1612c64a526032d95ab1683053325403e1afbe3ad2f374c5"}, + {file = "xxhash-3.2.0-cp39-cp39-win32.whl", hash = "sha256:9b94749130ef3119375c599bfce82142c2500ef9ed3280089157ee37662a7137"}, + {file = "xxhash-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:e57d94a1552af67f67b27db5dba0b03783ea69d5ca2af2f40e098f0ba3ce3f5f"}, + {file = "xxhash-3.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92fd765591c83e5c5f409b33eac1d3266c03d3d11c71a7dbade36d5cdee4fbc0"}, + {file = "xxhash-3.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8970f6a411a9839a02b23b7e90bbbba4a6de52ace009274998566dc43f36ca18"}, + {file = "xxhash-3.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5f3e33fe6cbab481727f9aeb136a213aed7e33cd1ca27bd75e916ffacc18411"}, + {file = "xxhash-3.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:368265392cb696dd53907e2328b5a8c1bee81cf2142d0cc743caf1c1047abb36"}, + {file = "xxhash-3.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3b1f3c6d67fa9f49c4ff6b25ce0e7143bab88a5bc0f4116dd290c92337d0ecc7"}, + {file = "xxhash-3.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c5e8db6e1ee7267b7c412ad0afd5863bf7a95286b8333a5958c8097c69f94cf5"}, + {file = "xxhash-3.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:761df3c7e2c5270088b691c5a8121004f84318177da1ca1db64222ec83c44871"}, + {file = "xxhash-3.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2d15a707e7f689531eb4134eccb0f8bf3844bb8255ad50823aa39708d9e6755"}, + {file = "xxhash-3.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6b2ba4ff53dd5f57d728095e3def7375eb19c90621ce3b41b256de84ec61cfd"}, + {file = "xxhash-3.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:61b0bcf946fdfd8ab5f09179dc2b5c74d1ef47cedfc6ed0ec01fdf0ee8682dd3"}, + {file = "xxhash-3.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f7b79f0f302396d8e0d444826ceb3d07b61977793886ebae04e82796c02e42dc"}, + {file = "xxhash-3.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0773cd5c438ffcd5dbff91cdd503574f88a4b960e70cedeb67736583a17a918"}, + {file = "xxhash-3.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ec1f57127879b419a2c8d2db9d9978eb26c61ae17e5972197830430ae78d25b"}, + {file = "xxhash-3.2.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d4b15c00e807b1d3d0b612338c814739dec310b80fb069bd732b98ddc709ad7"}, + {file = "xxhash-3.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:9d3f686e3d1c8900c5459eee02b60c7399e20ec5c6402364068a343c83a61d90"}, + {file = "xxhash-3.2.0.tar.gz", hash = "sha256:1afd47af8955c5db730f630ad53ae798cf7fae0acb64cebb3cf94d35c47dd088"}, +] + [[package]] name = "yarl" version = "1.8.2" @@ -4038,9 +4590,9 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [extras] audio = ["pydub"] aws = ["smart-open"] -common = ["lz4", "protobuf"] +common = ["protobuf", "lz4"] elasticsearch = ["elasticsearch"] -full = ["av", "lz4", "pillow", "protobuf", "pydub", "trimesh", "types-pillow"] +full = ["protobuf", "lz4", "pandas", "pillow", "types-pillow", "av", "pydub", "trimesh"] hnswlib = ["hnswlib"] image = ["pillow", "types-pillow"] jac = ["jina-hubble-sdk"] @@ -4053,4 +4605,4 @@ web = ["fastapi"] [metadata] lock-version = "2.0" python-versions = ">=3.7,<4.0" -content-hash = "3388af41b53300637299b44bd9ea94a18a44368bb1006ee16e04d35c99a238b6" +content-hash = "821f6cd00f78c456f6146f39c14f0704e4f2d113c35db00c58462d8cfbe3a538" diff --git a/pyproject.toml b/pyproject.toml index 78930d3d464..3114ff8dc61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ torch = { version = ">=1.0.0", optional = true } orjson = ">=3.8.2" pillow = {version = ">=9.3.0", optional = true } types-pillow = {version = ">=9.3.0.1", optional = true } -trimesh = {version = ">=3.17.1", optional = true} +trimesh = {version = ">=3.17.1", extras = ["easy"], optional = true } typing-inspect = ">=0.8.0" types-requests = ">=2.28.11.6" av = {version = ">=10.0.0", optional = true} @@ -30,20 +30,20 @@ jina-hubble-sdk = {version = ">=0.34.0", optional = true} [tool.poetry.extras] common = ["protobuf", "lz4"] -torch = ["torch"] +pandas = ["pandas"] image = ["pillow", "types-pillow"] video = ["av"] audio = ["pydub"] mesh = ["trimesh"] -web = ["fastapi"] hnswlib = ["hnswlib"] -pandas = ["pandas"] elasticsearch = ["elasticsearch"] jac = ["jina-hubble-sdk"] aws = ["smart-open"] +torch = ["torch"] +web = ["fastapi"] # all -full = ["protobuf", "lz4", "pillow", "types-pillow", "av", "pydub", "trimesh"] +full = ["protobuf", "lz4", "pandas", "pillow", "types-pillow", "av", "pydub", "trimesh"] [tool.poetry.dev-dependencies] pytest = ">=7.0" @@ -77,43 +77,20 @@ plugins = "pydantic.mypy" check_untyped_defs = true [[tool.mypy.overrides]] -module = "av" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "pandas" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "trimesh" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "hnswlib" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "typing_inspect" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "IPython.display" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "hubble.*" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "smart_open" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "boto3" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "botocore" +module = [ + "botocore", + "pydub", + "boto3", + "lz4", + "smart_open", + "hubble.*", + "IPython.display", + "typing_inspect", + "hnswlib", + "trimesh", + "pandas", + "av", +] ignore_missing_imports = true [tool.black]