14
14
15
15
import re
16
16
import time
17
- import traceback
18
17
import warnings
19
18
from abc import ABC , abstractmethod
20
19
from 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
22
21
23
22
import wrapt
24
23
25
24
from testcontainers .core .config import testcontainers_config as config
26
25
from testcontainers .core .utils import setup_logger
27
26
28
- if TYPE_CHECKING :
29
- from testcontainers .core .container import DockerContainer
30
-
31
27
logger = setup_logger (__name__ )
32
28
33
29
# Get a tuple of transient exceptions for which we'll retry. Other exceptions will be raised.
36
32
# Type variables for generic functions
37
33
F = TypeVar ("F" , bound = Callable [..., Any ])
38
34
35
+
39
36
class WaitStrategyTarget (Protocol ):
40
37
"""
41
38
Protocol defining the interface that containers must implement for wait strategies.
@@ -163,7 +160,7 @@ def wait_until_ready(self, container: WaitStrategyTarget) -> Any:
163
160
logger .debug (f"Connection attempt failed: { e !s} " )
164
161
time .sleep (self ._poll_interval )
165
162
166
- @wrapt .decorator
163
+ @wrapt .decorator # type: ignore[misc]
167
164
def wrapper (wrapped : Callable [..., Any ], instance : Any , args : list [Any ], kwargs : dict [str , Any ]) -> Any :
168
165
# Use the LegacyWaitStrategy to handle retries with proper timeout
169
166
strategy = LegacyWaitStrategy (wrapped , instance , args , kwargs )
@@ -177,6 +174,7 @@ def wrapper(wrapped: Callable[..., Any], instance: Any, args: list[Any], kwargs:
177
174
178
175
return cast ("Callable[[F], F]" , wrapper )
179
176
177
+
180
178
@wait_container_is_ready ()
181
179
def wait_for (condition : Callable [..., bool ]) -> bool :
182
180
warnings .warn (
@@ -244,8 +242,13 @@ def wait_for_logs(
244
242
# For more complex scenarios, use structured wait strategies directly:
245
243
container.waiting_for(LogMessageWaitStrategy("ready"))
246
244
"""
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)
249
252
warnings .warn (
250
253
"The wait_for_logs function with string or callable predicates is deprecated and will be removed in a future version. "
251
254
"Use structured wait strategies instead: "
@@ -254,11 +257,6 @@ def wait_for_logs(
254
257
DeprecationWarning ,
255
258
stacklevel = 2 ,
256
259
)
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
262
260
263
261
# Original implementation for backwards compatibility
264
262
re_predicate : Optional [Callable [[str ], Any ]] = None
0 commit comments