File size: 1,765 Bytes
6d5047c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""Config hydration: env vars, _target_ resolution, and recursive instantiation."""

import importlib
import os


def get_env_var(name: str, default=None):
    """Read env var by name and by lowercased name; return default if neither set."""
    return os.getenv(name, os.getenv(name.lower(), default))


def resolve_target(target: str):
    """Import module and return the attribute named by a dotted path (e.g. 'pkg.mod.Class')."""
    module_name, attr_name = target.rsplit(".", 1)
    module = importlib.import_module(module_name)
    return getattr(module, attr_name)


def materialize_value(value):
    """Recursively turn dicts with '_target_' into instances; lists/dicts traversed; leaves
    unchanged."""
    if isinstance(value, dict):
        if "_target_" in value:
            return instantiate_from_dict(value)
        return {k: materialize_value(v) for k, v in value.items()}
    if isinstance(value, list):
        return [materialize_value(v) for v in value]
    return value


def instantiate_from_dict(node, overrides=None):
    """Build an instance from a config dict: '_target_' gives the class, other keys are kwargs; overrides merged in."""
    if not isinstance(node, dict) or "_target_" not in node:
        raise ValueError("Config node must be a dict with a '_target_' key.")

    target = resolve_target(node["_target_"])
    kwargs = {}
    for key, value in node.items():
        if key == "_target_":
            continue
        kwargs[key] = materialize_value(value)

    if overrides:
        kwargs.update({k: v for k, v in overrides.items() if v is not None})

    return target(**kwargs)