Skip to content

Commit 0729bf4

Browse files
fix: add chroma container (#515)
based on #477 --------- Co-authored-by: Trayan Azarov <[email protected]>
1 parent 914f1e5 commit 0729bf4

File tree

6 files changed

+394
-1
lines changed

6 files changed

+394
-1
lines changed

index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ testcontainers-python facilitates the use of Docker containers for functional an
1717
core/README
1818
modules/arangodb/README
1919
modules/azurite/README
20+
modules/chroma/README
2021
modules/clickhouse/README
2122
modules/elasticsearch/README
2223
modules/google/README

modules/chroma/README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.. autoclass:: testcontainers.chroma.ChromaContainer
2+
.. title:: testcontainers.minio.ChromaContainer
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from typing import TYPE_CHECKING
2+
3+
from requests import ConnectionError, get
4+
5+
from testcontainers.core.container import DockerContainer
6+
from testcontainers.core.utils import raise_for_deprecated_parameter
7+
from testcontainers.core.waiting_utils import wait_container_is_ready
8+
9+
if TYPE_CHECKING:
10+
from requests import Response
11+
12+
13+
class ChromaContainer(DockerContainer):
14+
"""
15+
The example below spins up a ChromaDB container, performs a healthcheck and creates a collection.
16+
The method :code:`get_client` can be used to create a client for the Chroma Python Client.
17+
18+
Example:
19+
20+
.. doctest::
21+
22+
>>> import chromadb
23+
>>> from testcontainers.chroma import ChromaContainer
24+
25+
>>> with ChromaContainer() as chroma:
26+
... config = chroma.get_config()
27+
... client = chromadb.HttpClient(host=config["host"], port=config["port"])
28+
... col = client.get_or_create_collection("test")
29+
... col.name
30+
'test'
31+
"""
32+
33+
def __init__(
34+
self,
35+
image: str = "chromadb/chroma:latest",
36+
port: int = 8000,
37+
**kwargs,
38+
) -> None:
39+
"""
40+
Args:
41+
image: Docker image to use for the MinIO container.
42+
port: Port to expose on the container.
43+
access_key: Access key for client connections.
44+
secret_key: Secret key for client connections.
45+
"""
46+
raise_for_deprecated_parameter(kwargs, "port_to_expose", "port")
47+
super().__init__(image, **kwargs)
48+
self.port = port
49+
50+
self.with_exposed_ports(self.port)
51+
# self.with_command(f"server /data --address :{self.port}")
52+
53+
def get_config(self) -> dict:
54+
"""This method returns the configuration of the Chroma container,
55+
including the endpoint.
56+
57+
Returns:
58+
dict: {`endpoint`: str}
59+
"""
60+
host_ip = self.get_container_host_ip()
61+
exposed_port = self.get_exposed_port(self.port)
62+
return {
63+
"endpoint": f"{host_ip}:{exposed_port}",
64+
"host": host_ip,
65+
"port": exposed_port,
66+
}
67+
68+
@wait_container_is_ready(ConnectionError)
69+
def _healthcheck(self) -> None:
70+
"""This is an internal method used to check if the Chroma container
71+
is healthy and ready to receive requests."""
72+
url = f"http://{self.get_config()['endpoint']}/api/v1/heartbeat"
73+
response: Response = get(url)
74+
response.raise_for_status()
75+
76+
def start(self) -> "ChromaContainer":
77+
"""This method starts the Chroma container and runs the healthcheck
78+
to verify that the container is ready to use."""
79+
super().start()
80+
self._healthcheck()
81+
return self

modules/chroma/tests/test_chroma.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from testcontainers.chroma import ChromaContainer
2+
import chromadb
3+
4+
5+
def test_docker_run_chroma():
6+
with ChromaContainer(image="chromadb/chroma:0.4.24") as chroma:
7+
client = chromadb.HttpClient(host=chroma.get_config()["host"], port=chroma.get_config()["port"])
8+
col = client.get_or_create_collection("test")
9+
assert col.name == "test"

0 commit comments

Comments
 (0)