|  | 
|  | 1 | +from dataclasses import dataclass, field | 
| 1 | 2 | from os import environ | 
|  | 3 | +from os.path import exists | 
|  | 4 | +from pathlib import Path | 
| 2 | 5 | 
 | 
| 3 | 6 | MAX_TRIES = int(environ.get("TC_MAX_TRIES", 120)) | 
| 4 | 7 | SLEEP_TIME = int(environ.get("TC_POOLING_INTERVAL", 1)) | 
|  | 
| 9 | 12 | RYUK_DISABLED: bool = environ.get("TESTCONTAINERS_RYUK_DISABLED", "false") == "true" | 
| 10 | 13 | RYUK_DOCKER_SOCKET: str = environ.get("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "/var/run/docker.sock") | 
| 11 | 14 | RYUK_RECONNECTION_TIMEOUT: str = environ.get("RYUK_RECONNECTION_TIMEOUT", "10s") | 
|  | 15 | + | 
|  | 16 | +TC_FILE = ".testcontainers.properties" | 
|  | 17 | +TC_GLOBAL = Path.home() / TC_FILE | 
|  | 18 | + | 
|  | 19 | + | 
|  | 20 | +def read_tc_properties() -> dict[str, str]: | 
|  | 21 | +    """ | 
|  | 22 | +    Read the .testcontainers.properties for settings. (see the Java implementation for details) | 
|  | 23 | +    Currently we only support the ~/.testcontainers.properties but may extend to per-project variables later. | 
|  | 24 | +
 | 
|  | 25 | +    :return: the merged properties from the sources. | 
|  | 26 | +    """ | 
|  | 27 | +    tc_files = [item for item in [TC_GLOBAL] if exists(item)] | 
|  | 28 | +    if not tc_files: | 
|  | 29 | +        return {} | 
|  | 30 | +    settings = {} | 
|  | 31 | + | 
|  | 32 | +    for file in tc_files: | 
|  | 33 | +        with open(file) as contents: | 
|  | 34 | +            tuples = [line.split("=") for line in contents.readlines() if "=" in line] | 
|  | 35 | +            settings = {**settings, **{item[0].strip(): item[1].strip() for item in tuples}} | 
|  | 36 | +    return settings | 
|  | 37 | + | 
|  | 38 | + | 
|  | 39 | +@dataclass | 
|  | 40 | +class TestcontainersConfiguration: | 
|  | 41 | +    max_tries: int = MAX_TRIES | 
|  | 42 | +    sleep_time: int = SLEEP_TIME | 
|  | 43 | +    ryuk_image: str = RYUK_IMAGE | 
|  | 44 | +    ryuk_privileged: bool = RYUK_PRIVILEGED | 
|  | 45 | +    ryuk_disabled: bool = RYUK_DISABLED | 
|  | 46 | +    ryuk_docker_socket: str = RYUK_DOCKER_SOCKET | 
|  | 47 | +    ryuk_reconnection_timeout: str = RYUK_RECONNECTION_TIMEOUT | 
|  | 48 | +    tc_properties: dict[str, str] = field(default_factory=read_tc_properties) | 
|  | 49 | + | 
|  | 50 | +    def tc_properties_get_tc_host(self): | 
|  | 51 | +        return self.tc_properties.get("tc.host") | 
|  | 52 | + | 
|  | 53 | +    @property | 
|  | 54 | +    def timeout(self): | 
|  | 55 | +        return self.max_tries * self.sleep_time | 
|  | 56 | + | 
|  | 57 | + | 
|  | 58 | +testcontainers_config = TestcontainersConfiguration() | 
|  | 59 | + | 
|  | 60 | +__all__ = [ | 
|  | 61 | +    # the public API of this module | 
|  | 62 | +    "testcontainers_config", | 
|  | 63 | +    # and all the legacy things that are deprecated: | 
|  | 64 | +    "MAX_TRIES", | 
|  | 65 | +    "SLEEP_TIME", | 
|  | 66 | +    "TIMEOUT", | 
|  | 67 | +    "RYUK_IMAGE", | 
|  | 68 | +    "RYUK_PRIVILEGED", | 
|  | 69 | +    "RYUK_DISABLED", | 
|  | 70 | +    "RYUK_DOCKER_SOCKET", | 
|  | 71 | +    "RYUK_RECONNECTION_TIMEOUT", | 
|  | 72 | +] | 
0 commit comments