Skip to content

Commit c4c85a7

Browse files
committed
feat: Add Weaviate module
1 parent 2e27225 commit c4c85a7

File tree

6 files changed

+748
-167
lines changed

6 files changed

+748
-167
lines changed

index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ testcontainers-python facilitates the use of Docker containers for functional an
3737
modules/redis/README
3838
modules/selenium/README
3939
modules/k3s/README
40+
modules/weaviate/README
4041

4142
Getting Started
4243
---------------

modules/weaviate/README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.. autoclass:: testcontainers.weaviate.WeaviateContainer
2+
.. title:: testcontainers.weaviate.WeaviateContainer
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
from typing import TYPE_CHECKING, Optional
14+
15+
from requests import ConnectionError, get
16+
17+
from testcontainers.core.generic import DbContainer
18+
from testcontainers.core.waiting_utils import wait_container_is_ready
19+
20+
if TYPE_CHECKING:
21+
from requests import Response
22+
23+
24+
class WeaviateContainer(DbContainer):
25+
"""
26+
Weaviate vector database container.
27+
28+
Arguments:
29+
`image`
30+
Docker image to use with Weaviate container.
31+
`env_vars`
32+
Additional environment variables to include with the container, e.g. ENABLE_MODULES list, QUERY_DEFAULTS_LIMIT setting.
33+
34+
Example:
35+
This example shows how to start Weaviate container with defualt settings.
36+
37+
.. doctest::
38+
39+
>>> from testcontainers.weaviate import WeaviateContainer
40+
41+
>>> with WeaviateContainer() as weaviate:
42+
... with container.get_client() as client:
43+
... client.is_live()
44+
45+
This example shows how to start Weaviate container with additinal settings.
46+
47+
.. doctest::
48+
49+
>>> from testcontainers.weaviate import WeaviateContainer
50+
51+
>>> with WeaviateContainer(
52+
>>> env_vars={
53+
>>> "ENABLE_MODULES": "backup-filesystem,text2vec-openai",
54+
>>> "BACKUP_FILESYSTEM_PATH": "/tmp/backups",
55+
>>> "QUERY_DEFAULTS_LIMIT": 100,
56+
>>> }
57+
>>> ) as container:
58+
>>> with container.get_client() as client:
59+
>>> client.is_live()
60+
"""
61+
62+
def __init__(
63+
self,
64+
image: str = "semitechnologies/weaviate:1.24.5",
65+
env_vars: Optional[dict[str, str]] = None,
66+
**kwargs,
67+
) -> None:
68+
super().__init__(image, **kwargs)
69+
self._http_port = 8080
70+
self._grpc_port = 50051
71+
72+
self.with_command(f"--host 0.0.0.0 --scheme http --port {self._http_port}")
73+
self.with_exposed_ports(self._http_port, self._grpc_port)
74+
75+
if env_vars is not None:
76+
for key, value in env_vars.items():
77+
self.with_env(key, value)
78+
79+
def _configure(self) -> None:
80+
self.with_env("AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED", "true")
81+
self.with_env("PERSISTENCE_DATA_PATH", "/var/lib/weaviate")
82+
83+
@wait_container_is_ready(ConnectionError)
84+
def _connect(self) -> None:
85+
url = f"http://{self.get_http_host()}:{self.get_http_port()}/v1/.well-known/ready"
86+
response: Response = get(url)
87+
response.raise_for_status()
88+
89+
def get_client(
90+
self,
91+
headers: Optional[dict[str, str]] = None,
92+
):
93+
"""
94+
Get a `weaviate.WeaviateClient` instance associated with the container.
95+
96+
Arguments:
97+
`headers`
98+
Additional headers to include in the requests, e.g. API keys for third-party Cloud vectorization.
99+
100+
Returns:
101+
WeaviateClient: An instance of the `weaviate.WeaviateClient` class.
102+
"""
103+
104+
try:
105+
import weaviate
106+
except ImportError as e:
107+
raise ImportError("To use the `get_client` method, you must install the `weaviate-client` package.") from e
108+
return weaviate.connect_to_custom(
109+
http_host=self.get_http_host(),
110+
http_port=self.get_http_port(),
111+
http_secure=self.get_http_secure(),
112+
grpc_host=self.get_http_host(),
113+
grpc_port=self.get_grpc_port(),
114+
grpc_secure=self.get_grpc_secure(),
115+
headers=headers,
116+
)
117+
118+
def get_http_host(self) -> str:
119+
"""
120+
Get the HTTP host of Weaviate container.
121+
122+
Returns:
123+
`str`
124+
The HTTP host of Weaviate container.
125+
"""
126+
return f"{self.get_container_host_ip()}"
127+
128+
def get_http_port(self) -> int:
129+
"""
130+
Get the HTTP port of Weaviate container.
131+
132+
Returns:
133+
`int`
134+
The HTTP port of Weaviate container.
135+
"""
136+
return self.get_exposed_port(self._http_port)
137+
138+
def get_http_secure(self) -> bool:
139+
"""
140+
Get the HTTP secured setting of Weaviate container.
141+
142+
Returns:
143+
`bool`
144+
True if it's https.
145+
"""
146+
return False
147+
148+
def get_grpc_host(self) -> str:
149+
"""
150+
Get the gRPC host of Weaviate container.
151+
152+
Returns:
153+
`str`
154+
The gRPC host of Weaviate container.
155+
"""
156+
return f"{self.get_container_host_ip()}"
157+
158+
def get_grpc_port(self) -> int:
159+
"""
160+
Get the gRPC port of Weaviate container.
161+
162+
Returns:
163+
`int`
164+
The gRPC port of Weaviate container.
165+
"""
166+
return self.get_exposed_port(self._grpc_port)
167+
168+
def get_grpc_secure(self) -> bool:
169+
"""
170+
Get the gRPC secured setting of Weaviate container.
171+
172+
Returns:
173+
`str`
174+
True if the conntection is secured with SSL.
175+
"""
176+
return False
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from testcontainers.weaviate import WeaviateContainer
2+
import weaviate
3+
4+
5+
def test_docker_run_weaviate():
6+
with WeaviateContainer() as container:
7+
client = weaviate.connect_to_custom(
8+
http_host=container.get_http_host(),
9+
http_port=container.get_http_port(),
10+
http_secure=container.get_http_secure(),
11+
grpc_host=container.get_grpc_host(),
12+
grpc_port=container.get_grpc_port(),
13+
grpc_secure=container.get_grpc_secure(),
14+
)
15+
16+
meta = client.get_meta()
17+
assert len(meta.get("version")) > 0
18+
19+
client.close()
20+
21+
22+
def test_docker_run_weaviate_with_client():
23+
with WeaviateContainer() as container:
24+
with container.get_client() as client:
25+
assert client.is_live()
26+
27+
meta = client.get_meta()
28+
assert len(meta.get("version")) > 0
29+
30+
31+
def test_docker_run_weaviate_with_modules():
32+
enable_modules = [
33+
"backup-filesystem",
34+
"text2vec-openai",
35+
"text2vec-cohere",
36+
"text2vec-huggingface",
37+
"generative-openai",
38+
]
39+
with WeaviateContainer(
40+
env_vars={
41+
"ENABLE_MODULES": ",".join(enable_modules),
42+
"BACKUP_FILESYSTEM_PATH": "/tmp/backups",
43+
}
44+
) as container:
45+
with container.get_client() as client:
46+
assert client.is_live()
47+
48+
meta = client.get_meta()
49+
assert len(meta.get("version")) > 0
50+
51+
modules = meta.get("modules")
52+
assert len(modules) == len(enable_modules)
53+
54+
for name in enable_modules:
55+
assert len(modules[name]) > 0

0 commit comments

Comments
 (0)