1414
1515import re
1616import time
17- import traceback
1817import warnings
1918from abc import ABC , abstractmethod
2019from datetime import timedelta
21- from typing import Any , Callable , Protocol , TypeVar , TYPE_CHECKING , Union , cast
20+ from typing import Any , Callable , Optional , Protocol , TypeVar , Union , cast
2221
2322import wrapt
2423
2524from testcontainers .core .config import testcontainers_config as config
2625from testcontainers .core .utils import setup_logger
2726
28- if TYPE_CHECKING :
29- from testcontainers .core .container import DockerContainer
30-
3127logger = setup_logger (__name__ )
3228
3329# Get a tuple of transient exceptions for which we'll retry. Other exceptions will be raised.
3632# Type variables for generic functions
3733F = TypeVar ("F" , bound = Callable [..., Any ])
3834
35+
3936class WaitStrategyTarget (Protocol ):
4037 """
4138 Protocol defining the interface that containers must implement for wait strategies.
@@ -163,7 +160,7 @@ def wait_until_ready(self, container: WaitStrategyTarget) -> Any:
163160 logger .debug (f"Connection attempt failed: { e !s} " )
164161 time .sleep (self ._poll_interval )
165162
166- @wrapt .decorator
163+ @wrapt .decorator # type: ignore[misc]
167164 def wrapper (wrapped : Callable [..., Any ], instance : Any , args : list [Any ], kwargs : dict [str , Any ]) -> Any :
168165 # Use the LegacyWaitStrategy to handle retries with proper timeout
169166 strategy = LegacyWaitStrategy (wrapped , instance , args , kwargs )
@@ -177,6 +174,7 @@ def wrapper(wrapped: Callable[..., Any], instance: Any, args: list[Any], kwargs:
177174
178175 return cast ("Callable[[F], F]" , wrapper )
179176
177+
180178@wait_container_is_ready ()
181179def wait_for (condition : Callable [..., bool ]) -> bool :
182180 warnings .warn (
@@ -244,8 +242,13 @@ def wait_for_logs(
244242 # For more complex scenarios, use structured wait strategies directly:
245243 container.waiting_for(LogMessageWaitStrategy("ready"))
246244 """
247- # Only warn for legacy usage (string or callable predicates, not WaitStrategy objects)
248- if not isinstance (predicate , WaitStrategy ):
245+ if isinstance (predicate , WaitStrategy ):
246+ start = time .time ()
247+ predicate .with_startup_timeout (int (timeout )).with_poll_interval (interval )
248+ predicate .wait_until_ready (container )
249+ return time .time () - start
250+ else :
251+ # Only warn for legacy usage (string or callable predicates, not WaitStrategy objects)
249252 warnings .warn (
250253 "The wait_for_logs function with string or callable predicates is deprecated and will be removed in a future version. "
251254 "Use structured wait strategies instead: "
@@ -254,11 +257,6 @@ def wait_for_logs(
254257 DeprecationWarning ,
255258 stacklevel = 2 ,
256259 )
257- if isinstance (predicate , WaitStrategy ):
258- start = time .time ()
259- predicate .with_startup_timeout (int (timeout )).with_poll_interval (interval )
260- predicate .wait_until_ready (container )
261- return time .time () - start
262260
263261 # Original implementation for backwards compatibility
264262 re_predicate : Optional [Callable [[str ], Any ]] = None
0 commit comments