Skip to content

API Reference

Source code in config_file/config_file.py
 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
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
class ConfigFile:
    def __init__(self, file_path: Union[str, Path]) -> None:
        """Stores the config file path and reads the file contents.

        Args:
            file_path: Path to the configuration file. Supports tilde
                (~) expansion for home directory.

        Raises:
            ValueError: If the specified file path does not have an extension
                        that is supported or it is a directory.
            FileNotFoundError: If the specified file path does not exist.
            ParsingError: If the file_path could not be parsed.
        """
        self.__path = ConfigFilePath(file_path).validate()
        self.__parser = self.__path.file_parser

    @property
    def path(self) -> Path:
        return Path(self.__path)

    @property
    def original_path(self) -> Path:
        return Path(self.__path.original_path)

    def __getitem__(self, key: str) -> Any:
        return self.__parser.parsed_content[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.__parser.parsed_content[key] = value

    def __delitem__(self, key: str) -> None:
        del self.__parser.parsed_content[key]

    def __contains__(self, key: str) -> bool:
        return self.has(key)

    def __str__(self) -> str:
        return str(self.__parser)

    def __repr__(self) -> str:
        return f"{self.path}\n\n{str(self.__parser)}"

    def get(
        self,
        key: str,
        parse_types: bool = False,
        return_type: Union[Callable[[Any], Any], None] = None,
        default: Any = Default(None),
    ) -> Any:
        """
        Retrieve the value of a key.

        Args:
            key: The key to retrieve.
            parse_types: Automatically parse ints, floats, booleans, dicts, and
                         lists. This recursively parses all types in whatever you're
                         retrieving, not just a single type. For example, if you are
                         retrieving a section, all values in that section will be
                         parsed.
            return_type: The type to coerce the return value to.
            default: The default value to return if the value of the key is empty.
                If not specified, a KeyError will be raised if the key does not exist.

        Returns:
            The value of the key.

        Raises:
            KeyError: If a key is attempted to be retrieved that does not exist.
            ValueError: If the value is not able to be coerced into return_type.
        """
        try:
            key_value = self.__parser.get(key)
        except KeyError as error:
            if isinstance(default, Default) and default.value is None:
                raise error
            else:
                key_value = default

        if parse_types:
            key_value = parse_value(key_value)

        return return_type(key_value) if return_type else key_value

    def set(self, key: str, value: Any) -> None:
        """Sets the value of a key.

        If the given key does not exist, it will be automatically
        created for you. That includes if there are multiple keys
        in a row that do not exist.
        e.g. set('exists.does_not.does_not.also_does_not', 5)

        The behavior of how this is done, however, depends on the
        file used. For example, with INI, subsections are not supported.
        So it would create a key in the section `exists` called `does_not`
        and set it to the value {'does_not': {'also_does_not': 5}}.

        Args:
            key: The section, sub-section, or key to delete.
            value: The value to set the key to.
        """
        self.__parser.set(key, value)

    def delete(self, key: str) -> None:
        """Deletes a section or key.

        Args:
            key: The section, sub-section, or key to delete.

        Raises:
            KeyError: If a key is attempted to be deleted that
            does not exist.
        """
        self.__parser.delete(key)

    def has(self, key: str, wild: bool = False) -> bool:
        """
        Check if a section, sub-section, or key exists.

        Some formats, like JSON, do not have sections and
        therefore, it would only be checking if a particular
        key exists.

        Args:
            key: The section, sub-section, or key to find.
            wild: Whether or not to search everywhere.

            Without `wild`, a single word `key` without a `.`
            will look at the outer most hierarchy of the file for it.

            With `wild`, that single word `key` will be searched
            for throughout the entire file.

        Returns:
            True if the key exists. False otherwise.
        """
        return self.__parser.has(key, wild=wild)

    def restore_original(self, original_path: Union[str, Path, None] = None) -> None:
        """Restores the original the configuration file.

        The current one is deleted and the original is copied back
        in its place. The internal contents are then reset to the
        new file.

        Args:
            original_path: The original file to reset to.

            Defaults to the original_path property if it is not
            provided.

        Raises:
            FileNotFoundError: If the original configuration file (whether
            calculated or passed in) does not exist or if the current
            configuration path is passed in as the original_path (since
            it is deleted before the original file is copied over).

            OSError: If the current configuration path is not writable.
        """
        original_path = ConfigFilePath(
            original_path if original_path else self.original_path
        ).validate()

        self.__path.unlink()
        copyfile(original_path, self.__path)
        self.__parser.reset_internal_contents(self.__path.contents)

    def save(self) -> None:
        """
        Save your configuration changes.

        This writes the file back out, including any changes
        you've made, to the specified path given from this
        object's constructor.
        """
        with open(str(self.__path), "w") as config_file:
            config_file.write(str(self))

__init__(file_path)

Stores the config file path and reads the file contents.

Parameters:

Name Type Description Default
file_path Union[str, Path]

Path to the configuration file. Supports tilde (~) expansion for home directory.

required

Raises:

Type Description
ValueError

If the specified file path does not have an extension that is supported or it is a directory.

FileNotFoundError

If the specified file path does not exist.

ParsingError

If the file_path could not be parsed.

Source code in config_file/config_file.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def __init__(self, file_path: Union[str, Path]) -> None:
    """Stores the config file path and reads the file contents.

    Args:
        file_path: Path to the configuration file. Supports tilde
            (~) expansion for home directory.

    Raises:
        ValueError: If the specified file path does not have an extension
                    that is supported or it is a directory.
        FileNotFoundError: If the specified file path does not exist.
        ParsingError: If the file_path could not be parsed.
    """
    self.__path = ConfigFilePath(file_path).validate()
    self.__parser = self.__path.file_parser

delete(key)

Deletes a section or key.

Parameters:

Name Type Description Default
key str

The section, sub-section, or key to delete.

required

Raises:

Type Description
KeyError

If a key is attempted to be deleted that

Source code in config_file/config_file.py
113
114
115
116
117
118
119
120
121
122
123
def delete(self, key: str) -> None:
    """Deletes a section or key.

    Args:
        key: The section, sub-section, or key to delete.

    Raises:
        KeyError: If a key is attempted to be deleted that
        does not exist.
    """
    self.__parser.delete(key)

get(key, parse_types=False, return_type=None, default=Default(None))

Retrieve the value of a key.

Parameters:

Name Type Description Default
key str

The key to retrieve.

required
parse_types bool

Automatically parse ints, floats, booleans, dicts, and lists. This recursively parses all types in whatever you're retrieving, not just a single type. For example, if you are retrieving a section, all values in that section will be parsed.

False
return_type Union[Callable[[Any], Any], None]

The type to coerce the return value to.

None
default Any

The default value to return if the value of the key is empty. If not specified, a KeyError will be raised if the key does not exist.

Default(None)

Returns:

Type Description
Any

The value of the key.

Raises:

Type Description
KeyError

If a key is attempted to be retrieved that does not exist.

ValueError

If the value is not able to be coerced into return_type.

Source code in config_file/config_file.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def get(
    self,
    key: str,
    parse_types: bool = False,
    return_type: Union[Callable[[Any], Any], None] = None,
    default: Any = Default(None),
) -> Any:
    """
    Retrieve the value of a key.

    Args:
        key: The key to retrieve.
        parse_types: Automatically parse ints, floats, booleans, dicts, and
                     lists. This recursively parses all types in whatever you're
                     retrieving, not just a single type. For example, if you are
                     retrieving a section, all values in that section will be
                     parsed.
        return_type: The type to coerce the return value to.
        default: The default value to return if the value of the key is empty.
            If not specified, a KeyError will be raised if the key does not exist.

    Returns:
        The value of the key.

    Raises:
        KeyError: If a key is attempted to be retrieved that does not exist.
        ValueError: If the value is not able to be coerced into return_type.
    """
    try:
        key_value = self.__parser.get(key)
    except KeyError as error:
        if isinstance(default, Default) and default.value is None:
            raise error
        else:
            key_value = default

    if parse_types:
        key_value = parse_value(key_value)

    return return_type(key_value) if return_type else key_value

has(key, wild=False)

Check if a section, sub-section, or key exists.

Some formats, like JSON, do not have sections and therefore, it would only be checking if a particular key exists.

Parameters:

Name Type Description Default
key str

The section, sub-section, or key to find.

required
wild bool

Whether or not to search everywhere.

False

Returns:

Type Description
bool

True if the key exists. False otherwise.

Source code in config_file/config_file.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def has(self, key: str, wild: bool = False) -> bool:
    """
    Check if a section, sub-section, or key exists.

    Some formats, like JSON, do not have sections and
    therefore, it would only be checking if a particular
    key exists.

    Args:
        key: The section, sub-section, or key to find.
        wild: Whether or not to search everywhere.

        Without `wild`, a single word `key` without a `.`
        will look at the outer most hierarchy of the file for it.

        With `wild`, that single word `key` will be searched
        for throughout the entire file.

    Returns:
        True if the key exists. False otherwise.
    """
    return self.__parser.has(key, wild=wild)

restore_original(original_path=None)

Restores the original the configuration file.

The current one is deleted and the original is copied back in its place. The internal contents are then reset to the new file.

Parameters:

Name Type Description Default
original_path Union[str, Path, None]

The original file to reset to.

None

Raises:

Type Description
FileNotFoundError

If the original configuration file (whether

OSError

If the current configuration path is not writable.

Source code in config_file/config_file.py
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
def restore_original(self, original_path: Union[str, Path, None] = None) -> None:
    """Restores the original the configuration file.

    The current one is deleted and the original is copied back
    in its place. The internal contents are then reset to the
    new file.

    Args:
        original_path: The original file to reset to.

        Defaults to the original_path property if it is not
        provided.

    Raises:
        FileNotFoundError: If the original configuration file (whether
        calculated or passed in) does not exist or if the current
        configuration path is passed in as the original_path (since
        it is deleted before the original file is copied over).

        OSError: If the current configuration path is not writable.
    """
    original_path = ConfigFilePath(
        original_path if original_path else self.original_path
    ).validate()

    self.__path.unlink()
    copyfile(original_path, self.__path)
    self.__parser.reset_internal_contents(self.__path.contents)

save()

Save your configuration changes.

This writes the file back out, including any changes you've made, to the specified path given from this object's constructor.

Source code in config_file/config_file.py
177
178
179
180
181
182
183
184
185
186
def save(self) -> None:
    """
    Save your configuration changes.

    This writes the file back out, including any changes
    you've made, to the specified path given from this
    object's constructor.
    """
    with open(str(self.__path), "w") as config_file:
        config_file.write(str(self))

set(key, value)

Sets the value of a key.

If the given key does not exist, it will be automatically created for you. That includes if there are multiple keys in a row that do not exist. e.g. set('exists.does_not.does_not.also_does_not', 5)

The behavior of how this is done, however, depends on the file used. For example, with INI, subsections are not supported. So it would create a key in the section exists called does_not and set it to the value {'does_not': {'also_does_not': 5}}.

Parameters:

Name Type Description Default
key str

The section, sub-section, or key to delete.

required
value Any

The value to set the key to.

required
Source code in config_file/config_file.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def set(self, key: str, value: Any) -> None:
    """Sets the value of a key.

    If the given key does not exist, it will be automatically
    created for you. That includes if there are multiple keys
    in a row that do not exist.
    e.g. set('exists.does_not.does_not.also_does_not', 5)

    The behavior of how this is done, however, depends on the
    file used. For example, with INI, subsections are not supported.
    So it would create a key in the section `exists` called `does_not`
    and set it to the value {'does_not': {'also_does_not': 5}}.

    Args:
        key: The section, sub-section, or key to delete.
        value: The value to set the key to.
    """
    self.__parser.set(key, value)