Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/testcontainers/core/waiting_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _poll(self, check: Callable[[], bool], transient_exceptions: Optional[list[t


# Keep existing wait_container_is_ready but make it use the new system internally
def wait_container_is_ready(*transient_exceptions: type[Exception]) -> Callable[[F], F]:
def wait_container_is_ready(*transient_exceptions: type[Exception]) -> Callable[[F], F]: # noqa: C901
"""
Legacy wait decorator that uses the new wait strategy system internally.
Maintains backwards compatibility with existing code.
Expand Down
6 changes: 3 additions & 3 deletions core/tests/test_socat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import httpx
import pytest
import requests

from testcontainers.core.container import DockerContainer
from testcontainers.core.network import Network
from testcontainers.socat.socat import SocatContainer
Expand All @@ -16,7 +16,7 @@ def test_socat_with_helloworld():
):
socat_url = f"http://{socat.get_container_host_ip()}:{socat.get_exposed_port(8080)}"

response = httpx.get(f"{socat_url}/ping")
response = requests.get(f"{socat_url}/ping") # noqa: S113

assert response.status_code == 200
assert response.content == b"PONG"
17 changes: 17 additions & 0 deletions doctests/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,20 @@
"sphinx.ext.doctest",
]
master_doc = "README"

doctest_global_setup = r"""
import sys
from importlib.metadata import version, PackageNotFoundError
from packaging.version import Version
try:
_cassandra_driver_version = Version(version("cassandra-driver"))
except PackageNotFoundError:
_cassandra_driver_version = None
SKIP_CASSANDRA_EXAMPLE = (
_cassandra_driver_version is not None
and _cassandra_driver_version <= Version("3.29.3")
and sys.version_info > (3, 14)
)
"""
14 changes: 4 additions & 10 deletions modules/cassandra/testcontainers/cassandra/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs
from testcontainers.core.wait_strategies import LogMessageWaitStrategy


class CassandraContainer(DockerContainer):
Expand All @@ -20,7 +20,8 @@ class CassandraContainer(DockerContainer):

Example:

.. doctest::
.. doctest:: cassandra_container
:skipif: SKIP_CASSANDRA_EXAMPLE

>>> from testcontainers.cassandra import CassandraContainer
>>> from cassandra.cluster import Cluster, DCAwareRoundRobinPolicy
Expand All @@ -46,14 +47,7 @@ def __init__(self, image: str = "cassandra:latest", **kwargs) -> None:
self.with_env("MAX_HEAP_SIZE", "1024M")
self.with_env("CASSANDRA_ENDPOINT_SNITCH", "GossipingPropertyFileSnitch")
self.with_env("CASSANDRA_DC", self.DEFAULT_LOCAL_DATACENTER)

def _connect(self):
wait_for_logs(self, "Startup complete")

def start(self) -> "CassandraContainer":
super().start()
self._connect()
return self
self.waiting_for(LogMessageWaitStrategy("Startup complete"))

def get_contact_points(self) -> list[tuple[str, int]]:
return [(self.get_container_host_ip(), int(self.get_exposed_port(self.CQL_PORT)))]
Expand Down
15 changes: 12 additions & 3 deletions modules/cassandra/tests/test_cassandra.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
from cassandra.cluster import Cluster, DCAwareRoundRobinPolicy

from testcontainers.cassandra import CassandraContainer
import sys

from importlib.metadata import version
import pytest
from packaging.version import Version


@pytest.mark.skipif(
Version(version("cassandra-driver")) <= Version("3.29.3") and sys.version_info > (3, 14),
reason="cassandra-driver <= 3.29.3 is incompatible with Python > 3.14",
)
def test_docker_run_cassandra() -> None:
from cassandra.cluster import Cluster, DCAwareRoundRobinPolicy

def test_docker_run_cassandra():
with CassandraContainer("cassandra:4.1.4") as cassandra:
cluster = Cluster(
cassandra.get_contact_points(),
Expand Down
13 changes: 8 additions & 5 deletions modules/kafka/testcontainers/kafka/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import tarfile
import time
from dataclasses import dataclass, field
Expand All @@ -10,7 +11,7 @@
from testcontainers.core.container import DockerContainer
from testcontainers.core.utils import raise_for_deprecated_parameter
from testcontainers.core.version import ComparableVersion
from testcontainers.core.waiting_utils import wait_for_logs
from testcontainers.core.wait_strategies import LogMessageWaitStrategy
from testcontainers.kafka._redpanda import RedpandaContainer

__all__ = [
Expand Down Expand Up @@ -59,7 +60,7 @@ def __init__(self, image: str = "confluentinc/cp-kafka:7.6.0", port: int = 9093,
super().__init__(image, **kwargs)
self.port = port
self.kraft_enabled = False
self.wait_for = r".*\[KafkaServer id=\d+\] started.*"
self.wait_for: re.Pattern[str] = re.compile(r".*\[KafkaServer id=\d+\] started.*")
self.boot_command = ""
self.cluster_id = "MkU3OEVBNTcwNTJENDM2Qk"
self.listeners = f"PLAINTEXT://0.0.0.0:{self.port},BROKER://0.0.0.0:9092"
Expand Down Expand Up @@ -102,7 +103,7 @@ def configure(self):
self._configure_zookeeper()

def _configure_kraft(self) -> None:
self.wait_for = r".*Kafka Server started.*"
self.wait_for = re.compile(r".*Kafka Server started.*")

self.with_env("CLUSTER_ID", self.cluster_id)
self.with_env("KAFKA_NODE_ID", 1)
Expand Down Expand Up @@ -172,14 +173,16 @@ def tc_start(self) -> None:
)
self.create_file(data, KafkaContainer.TC_START_SCRIPT)

def start(self, timeout=30) -> "KafkaContainer":
def start(self, timeout: int = 30) -> "KafkaContainer":
script = KafkaContainer.TC_START_SCRIPT
command = f'sh -c "while [ ! -f {script} ]; do sleep 0.1; done; sh {script}"'
self.configure()
self.with_command(command)
super().start()
self.tc_start()
wait_for_logs(self, self.wait_for, timeout=timeout)
wait_strategy = LogMessageWaitStrategy(self.wait_for)
wait_strategy.with_startup_timeout(timeout)
wait_strategy.wait_until_ready(self)
return self

def create_file(self, content: bytes, path: str) -> None:
Expand Down
8 changes: 4 additions & 4 deletions modules/mysql/testcontainers/mysql/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from testcontainers.core.generic import DbContainer
from testcontainers.core.utils import raise_for_deprecated_parameter
from testcontainers.core.waiting_utils import wait_for_logs
from testcontainers.core.wait_strategies import LogMessageWaitStrategy


class MySqlContainer(DbContainer):
Expand Down Expand Up @@ -106,10 +106,10 @@ def _configure(self) -> None:
self.with_env("MYSQL_PASSWORD", self.password)

def _connect(self) -> None:
wait_for_logs(
self,
re.compile(".*: ready for connections.*: ready for connections.*", flags=re.DOTALL | re.MULTILINE).search,
wait_strategy = LogMessageWaitStrategy(
re.compile(r".*: ready for connections.*: ready for connections.*", flags=re.DOTALL | re.MULTILINE),
)
wait_strategy.wait_until_ready(self)

def get_connection_url(self) -> str:
return super()._create_connection_url(
Expand Down
Loading