1 2
import errno
2 2
import importlib
3 2
import inspect
4 2
import io
5 2
import types
6 2
from contextlib import suppress
7 2
from pathlib import Path
8

9 2
from dynaconf import default_settings
10 2
from dynaconf.utils import DynaconfDict
11 2
from dynaconf.utils import object_merge
12 2
from dynaconf.utils import upperfy
13 2
from dynaconf.utils.files import find_file
14

15

16 2
def load(obj, settings_module, identifier="py", silent=False, key=None):
17
    """Tries to import a python module"""
18 2
    mod, loaded_from = get_module(obj, settings_module, silent)
19 2
    if not (mod and loaded_from):
20 2
        return
21 2
    load_from_python_object(obj, mod, settings_module, key, identifier)
22

23

24 2
def load_from_python_object(
25
    obj, mod, settings_module, key=None, identifier=None
26
):
27 2
    file_merge = getattr(mod, "dynaconf_merge", False) or getattr(
28
        mod, "DYNACONF_MERGE", False
29
    )
30 2
    for setting in dir(mod):
31
        # at least 3 first chars should be upper to be considered a setting var
32 2
        if setting[:3].isupper():
33 2
            if key is None or key == setting:
34 2
                setting_value = getattr(mod, setting)
35 2
                obj.set(
36
                    setting,
37
                    setting_value,
38
                    loader_identifier=identifier,
39
                    merge=file_merge,
40
                )
41 2
    obj._loaded_files.append(mod.__file__)
42

43

44 2
def try_to_load_from_py_module_name(
45
    obj, name, key=None, identifier="py", silent=False
46
):
47
    """Try to load module by its string name.
48

49
    Arguments:
50
        obj {LAzySettings} -- Dynaconf settings instance
51
        name {str} -- Name of the module e.g: foo.bar.zaz
52

53
    Keyword Arguments:
54
        key {str} -- Single key to be loaded (default: {None})
55
        identifier {str} -- Name of identifier to store (default: 'py')
56
        silent {bool} -- Weather to raise or silence exceptions.
57
    """
58 2
    ctx = suppress(ImportError, TypeError) if silent else suppress()
59

60 2
    with ctx:
61 2
        mod = importlib.import_module(name)
62 2
        load_from_python_object(obj, mod, name, key, identifier)
63 2
        return True  # loaded ok!
64
    # if it reaches this point that means exception occurred, module not found.
65 2
    return False
66

67

68 2
def get_module(obj, filename, silent=False):
69 2
    try:
70 2
        mod = importlib.import_module(filename)
71 2
        loaded_from = "module"
72 2
    except (ImportError, TypeError):
73 2
        mod = import_from_filename(obj, filename, silent=silent)
74 2
        if mod and not mod._is_error:
75 2
            loaded_from = "filename"
76
        else:
77
            # it is important to return None in case of not loaded
78 2
            loaded_from = None
79 2
    return mod, loaded_from
80

81

82
def import_from_filename(obj, filename, silent=False):  # pragma: no cover
83
    """If settings_module is a filename path import it."""
84
    if filename in [item.filename for item in inspect.stack()]:
85
        raise ImportError(
86
            "Looks like you are loading dynaconf "
87
            f"from inside the {filename} file and then it is trying "
88
            "to load itself entering in a circular reference "
89
            "problem. To solve it you have to "
90
            "invoke your program from another root folder "
91
            "or rename your program file."
92
        )
93

94
    _find_file = getattr(obj, "find_file", find_file)
95
    if not filename.endswith(".py"):
96
        filename = f"{filename}.py"
97

98
    if filename in default_settings.SETTINGS_FILE_FOR_DYNACONF:
99
        silent = True
100
    mod = types.ModuleType(filename.rstrip(".py"))
101
    mod.__file__ = filename
102
    mod._is_error = False
103
    try:
104
        with io.open(
105
            _find_file(filename),
106
            encoding=default_settings.ENCODING_FOR_DYNACONF,
107
        ) as config_file:
108
            exec(compile(config_file.read(), filename, "exec"), mod.__dict__)
109
    except IOError as e:
110
        e.strerror = (
111
            f"py_loader: error loading file " f"({e.strerror} {filename})\n"
112
        )
113
        if silent and e.errno in (errno.ENOENT, errno.EISDIR):
114
            return
115
        mod._is_error = True
116
    return mod
117

118

119 2
def write(settings_path, settings_data, merge=True):
120
    """Write data to a settings file.
121

122
    :param settings_path: the filepath
123
    :param settings_data: a dictionary with data
124
    :param merge: boolean if existing file should be merged with new data
125
    """
126 2
    settings_path = Path(settings_path)
127
    if settings_path.exists() and merge:  # pragma: no cover
128
        existing = DynaconfDict()
129
        load(existing, str(settings_path))
130
        object_merge(existing, settings_data)
131 2
    with io.open(
132
        str(settings_path),
133
        "w",
134
        encoding=default_settings.ENCODING_FOR_DYNACONF,
135
    ) as f:
136 2
        f.writelines(
137
            [f"{upperfy(k)} = {repr(v)}\n" for k, v in settings_data.items()]
138
        )

Read our documentation on viewing source code .

Loading