Skip to content

Defaults

toolbox_python.defaults 🔗

Summary

The defaults module is used how to set and control default values for our various Python processes.

toolbox_python.defaults.Defaults 🔗

Summary

When we create and use Python variables, it is sometimes handy to add a default value for that variable. This class will handle that process.

Examples
Set up data for examples
1
2
>>> from toolbox_python.defaults import Defaults
>>> defaults = Defaults()

Example 1: Call direct from class
1
>>> print(Defaults()(value="this"))
Terminal
"this"

Conclusion: Successfully printed default value direct from class.

Example 2: Call from instantiated class
1
>>> print(defaults(value="that"))
Terminal
"that"

Conclusion: Successfully printed default value from instantiated class.

Example 3: Cast to `bool`
1
>>> print(defaults(value="True", cast=bool))
Terminal
True

Conclusion: Successfully casted to bool.

Example 4: Cast to `int`
1
>>> print(defaults(value="1", cast=int))
Terminal
1

Conclusion: Successfully casted to int.

Example 5: Cast to `str`
1
>>> print(defaults(value=1, cast=str))
Terminal
"1"

Conclusion: Successfully casted to str.

Example 6: Cast to string `'str'`
1
>>> print(defaults(value=1, cast="str"))
Terminal
"1"

Conclusion: Successfully casted to str.

Note: The only difference between this and the previous example is the type of the cast parameter. Here, it is a string representation of the type, whereas in the previous example, we parse'ed in the actual str class.

Example 7: Invalid cast type
1
>>> print(defaults(value="next", cast="bad_type"))
Terminal
AttributeError: The value for `type` is invalid: `bad_type`.
Must be a valid type: ['bool', 'dict', 'int', 'float', 'list', 'str', 'tuple']

Conclusion: Invalid cast type.

Example 8: All blank values
1
>>> print(defaults(value=None, cast=None))
Terminal
AttributeError: Both `value` and `default` are blank: 'None', 'None'.
If `value` is blank, then `default` cannot be blank.

Conclusion: Both value and default are blank.

Credit

Inspiration from:
https://github.com/henriquebastos/python-decouple/

Source code in src/toolbox_python/defaults.py
 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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
class Defaults:
    """
    !!! note "Summary"
        When we create and use Python variables, it is sometimes handy to add a default value for that variable.
        This class will handle that process.

    ???+ example "Examples"

        ```{.py .python linenums="1" title="Set up data for examples"}
        >>> from toolbox_python.defaults import Defaults
        >>> defaults = Defaults()
        ```

        ```{.py .python linenums="1" title="Example 1: Call direct from class"}
        >>> print(Defaults()(value="this"))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        "this"
        ```
        !!! success "Conclusion: Successfully printed default value direct from class."
        </div>

        ```{.py .python linenums="1" title="Example 2: Call from instantiated class"}
        >>> print(defaults(value="that"))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        "that"
        ```
        !!! success "Conclusion: Successfully printed default value from instantiated class."
        </div>

        ```{.py .python linenums="1" title="Example 3: Cast to `bool`"}
        >>> print(defaults(value="True", cast=bool))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        True
        ```
        !!! success "Conclusion: Successfully casted to `#!py bool`."
        </div>

        ```{.py .python linenums="1" title="Example 4: Cast to `int`"}
        >>> print(defaults(value="1", cast=int))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        1
        ```
        !!! success "Conclusion: Successfully casted to `#!py int`."
        </div>

        ```{.py .python linenums="1" title="Example 5: Cast to `str`"}
        >>> print(defaults(value=1, cast=str))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        "1"
        ```
        !!! success "Conclusion: Successfully casted to `#!py str`."
        </div>

        ```{.py .python linenums="1" title="Example 6: Cast to string `'str'`"}
        >>> print(defaults(value=1, cast="str"))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        "1"
        ```
        !!! success "Conclusion: Successfully casted to `#!py str`."
        !!! observation "Note: The only difference between this and the previous example is the type of the `cast` parameter. Here, it is a string representation of the type, whereas in the previous example, we parse'ed in the actual `str` class."
        </div>

        ```{.py .python linenums="1" title="Example 7: Invalid cast type"}
        >>> print(defaults(value="next", cast="bad_type"))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        AttributeError: The value for `type` is invalid: `bad_type`.
        Must be a valid type: ['bool', 'dict', 'int', 'float', 'list', 'str', 'tuple']
        ```
        !!! failure "Conclusion: Invalid cast type."
        </div>

        ```{.py .python linenums="1" title="Example 8: All blank values"}
        >>> print(defaults(value=None, cast=None))
        ```
        <div class="result" markdown>
        ```{.txt .text title="Terminal"}
        AttributeError: Both `value` and `default` are blank: 'None', 'None'.
        If `value` is blank, then `default` cannot be blank.
        ```
        !!! failure "Conclusion: Both `value` and `default` are blank."
        </div>

    ??? success "Credit"
        Inspiration from:<br>
        https://github.com/henriquebastos/python-decouple/
    """

    def __init__(self) -> None:
        """
        !!! note "Summary"
            Nothing is initialised when this class is instantiated.
            Use the [`__call__()`][toolbox_python.defaults.Defaults.__call__] method instead.

        ??? tip "See Also"
            - [`Defaults.__call__()`][toolbox_python.defaults.Defaults.__call__]
        """
        return None

    def __call__(self, *args, **kwargs) -> Any:
        """
        !!! note "Summary"
            When this class is called, it will pass through all parameters to the internal [`.get()`][toolbox_python.defaults.Defaults.get] method.

        ??? tip "See Also"
            - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
        """
        return self.get(*args, **kwargs)

    @typechecked
    def get(
        self,
        value: Any,
        default: Any | None = None,
        cast: str | type | None = None,
    ) -> Any:
        """
        !!! note "Summary"
            From the value that is parsed in to the `value` parameter, convert it to `default` if `value` is `#!py None`, and convert it to `cast` if `cast` is not `#!py None`.

        ???+ info "Details"
            The detailed steps will be:

            1. Validate the input (using the internal [`._validate_value_and_default()`][toolbox_python.defaults.Defaults._validate_value_and_default] & [`._validate_type()`][toolbox_python.defaults.Defaults._validate_type] methods),
            1. If `value` is `#!py None`, then assign `default` to `value`.
            1. If `cast` is _not_ `#!py None`, then cast `value` to the data type in `cast`.
                - Note, `cast` can be _either_ the actual type to convert to, _or_ a string representation of the type.
            1. Return the updated/defaulted/casted `value` back to the user.

        Params:
            value (Any):
                The value to check.
            default (Optional[Any], optional):
                The default value for `value`.<br>
                Note, can be a `#!py None` value; however, if `value` is also `#!py None`, then `default` _cannot_ be `#!py None`.<br>
                Defaults to `#!py None`.
            cast (Optional[Union[str, type]], optional):
                The data type to convert to.<br>
                Must be one of: `#!py ["bool", "dict", "int", "float", "list", "str", "tuple"]`.<br>
                Defaults to `#!py None`.

        Returns:
            value (Any):
                The updated/defaulted/casted value.

        ??? tip "See Also"
            - [`Defaults._validate_value_and_default()`][toolbox_python.defaults.Defaults._validate_value_and_default]
            - [`Defaults._validate_type()`][toolbox_python.defaults.Defaults._validate_type]
        """
        (
            self._validate_value_and_default(
                value=value, default=default
            )._validate_type(check_type=cast)
        )
        if value is None:
            value = default
        if cast is not None:
            if (cast is bool or cast == "bool") and is_type(value, str):
                value = bool(strtobool(value))
            elif isinstance(cast, str):
                value = eval(cast)(value)
            else:
                value = cast(value)
        return value

    def _validate_value_and_default(
        self,
        value: Any | None = None,
        default: Any | None = None,
    ) -> Defaults:
        """
        !!! note "Summary"
            Validate to ensure that `value` and `default` are not both `#!py None`.

        Params:
            value (Optional[Any], optional):
                The `value` to check.<br>
                Defaults to `#!py None`.
            default (Optional[Any], optional):
                The `default` value to check.<br>
                Defaults to `#!py None`.

        Raises:
            AttributeError: If both `value` and `default` are `#!py None`.

        Returns:
            self (Defaults):
                If both `value` and `default` are not both `#!py None`, then return `self`.

        ??? tip "See Also"
            - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
        """
        if value is None and default is None:
            raise AttributeError(
                f"Both `value` and `default` are blank: '{value}', '{default}'.\n"
                f"If `value` is blank, then `default` cannot be blank."
            )
        return self

    def _validate_type(
        self,
        check_type: str | type | None = None,
    ) -> Defaults:
        """
        !!! note "Summary"
            Check to ensure that `check_type` is a valid Python type.<br>
            Must be one of: `#!py ["bool", "dict", "int", "float", "list", "str", "tuple"]`.

        Params:
            check_type (Optional[Union[str, type]], optional):
                The type to check against. Can either be an actual Python type, or it's string representation.<br>
                Defaults to `#!py None`.

        Raises:
            AttributeError: If `check_type` is _both_ not `#!py None` _and_ if it is not one of the valid Python types.

        Returns:
            self (Defaults):
                If the type is valid, return `self`.

        ??? tip "See Also"
            - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
        """
        valid_types: str_list = [
            "bool",
            "dict",
            "int",
            "float",
            "list",
            "str",
            "tuple",
        ]
        if check_type is None:
            return self
        elif is_type(check_type, str):
            retype = check_type
        elif type(check_type).__name__ == "type":
            retype = check_type.__name__  # type: ignore
        if retype is not None and retype not in valid_types:
            raise AttributeError(
                f"The value for `type` is invalid: `{retype}`.\n"
                f"Must be a valid type: {valid_types}."
            )
        return self

__init__ 🔗

__init__() -> None

Summary

Nothing is initialised when this class is instantiated. Use the __call__() method instead.

See Also
Source code in src/toolbox_python/defaults.py
175
176
177
178
179
180
181
182
183
184
def __init__(self) -> None:
    """
    !!! note "Summary"
        Nothing is initialised when this class is instantiated.
        Use the [`__call__()`][toolbox_python.defaults.Defaults.__call__] method instead.

    ??? tip "See Also"
        - [`Defaults.__call__()`][toolbox_python.defaults.Defaults.__call__]
    """
    return None

__call__ 🔗

__call__(*args, **kwargs) -> Any

Summary

When this class is called, it will pass through all parameters to the internal .get() method.

See Also
Source code in src/toolbox_python/defaults.py
186
187
188
189
190
191
192
193
194
def __call__(self, *args, **kwargs) -> Any:
    """
    !!! note "Summary"
        When this class is called, it will pass through all parameters to the internal [`.get()`][toolbox_python.defaults.Defaults.get] method.

    ??? tip "See Also"
        - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
    """
    return self.get(*args, **kwargs)

get 🔗

get(
    value: Any,
    default: Any | None = None,
    cast: str | type | None = None,
) -> Any

Summary

From the value that is parsed in to the value parameter, convert it to default if value is None, and convert it to cast if cast is not None.

Details

The detailed steps will be:

  1. Validate the input (using the internal ._validate_value_and_default() & ._validate_type() methods),
  2. If value is None, then assign default to value.
  3. If cast is not None, then cast value to the data type in cast.
    • Note, cast can be either the actual type to convert to, or a string representation of the type.
  4. Return the updated/defaulted/casted value back to the user.

Parameters:

Name Type Description Default
value Any

The value to check.

required
default Optional[Any]

The default value for value.
Note, can be a None value; however, if value is also None, then default cannot be None.
Defaults to None.

None
cast Optional[Union[str, type]]

The data type to convert to.
Must be one of: ["bool", "dict", "int", "float", "list", "str", "tuple"].
Defaults to None.

None

Returns:

Name Type Description
value Any

The updated/defaulted/casted value.

See Also
Source code in src/toolbox_python/defaults.py
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
@typechecked
def get(
    self,
    value: Any,
    default: Any | None = None,
    cast: str | type | None = None,
) -> Any:
    """
    !!! note "Summary"
        From the value that is parsed in to the `value` parameter, convert it to `default` if `value` is `#!py None`, and convert it to `cast` if `cast` is not `#!py None`.

    ???+ info "Details"
        The detailed steps will be:

        1. Validate the input (using the internal [`._validate_value_and_default()`][toolbox_python.defaults.Defaults._validate_value_and_default] & [`._validate_type()`][toolbox_python.defaults.Defaults._validate_type] methods),
        1. If `value` is `#!py None`, then assign `default` to `value`.
        1. If `cast` is _not_ `#!py None`, then cast `value` to the data type in `cast`.
            - Note, `cast` can be _either_ the actual type to convert to, _or_ a string representation of the type.
        1. Return the updated/defaulted/casted `value` back to the user.

    Params:
        value (Any):
            The value to check.
        default (Optional[Any], optional):
            The default value for `value`.<br>
            Note, can be a `#!py None` value; however, if `value` is also `#!py None`, then `default` _cannot_ be `#!py None`.<br>
            Defaults to `#!py None`.
        cast (Optional[Union[str, type]], optional):
            The data type to convert to.<br>
            Must be one of: `#!py ["bool", "dict", "int", "float", "list", "str", "tuple"]`.<br>
            Defaults to `#!py None`.

    Returns:
        value (Any):
            The updated/defaulted/casted value.

    ??? tip "See Also"
        - [`Defaults._validate_value_and_default()`][toolbox_python.defaults.Defaults._validate_value_and_default]
        - [`Defaults._validate_type()`][toolbox_python.defaults.Defaults._validate_type]
    """
    (
        self._validate_value_and_default(
            value=value, default=default
        )._validate_type(check_type=cast)
    )
    if value is None:
        value = default
    if cast is not None:
        if (cast is bool or cast == "bool") and is_type(value, str):
            value = bool(strtobool(value))
        elif isinstance(cast, str):
            value = eval(cast)(value)
        else:
            value = cast(value)
    return value

_validate_value_and_default 🔗

_validate_value_and_default(
    value: Any | None = None, default: Any | None = None
) -> Defaults

Summary

Validate to ensure that value and default are not both None.

Parameters:

Name Type Description Default
value Optional[Any]

The value to check.
Defaults to None.

None
default Optional[Any]

The default value to check.
Defaults to None.

None

Raises:

Type Description
AttributeError

If both value and default are None.

Returns:

Name Type Description
self Defaults

If both value and default are not both None, then return self.

See Also
Source code in src/toolbox_python/defaults.py
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
def _validate_value_and_default(
    self,
    value: Any | None = None,
    default: Any | None = None,
) -> Defaults:
    """
    !!! note "Summary"
        Validate to ensure that `value` and `default` are not both `#!py None`.

    Params:
        value (Optional[Any], optional):
            The `value` to check.<br>
            Defaults to `#!py None`.
        default (Optional[Any], optional):
            The `default` value to check.<br>
            Defaults to `#!py None`.

    Raises:
        AttributeError: If both `value` and `default` are `#!py None`.

    Returns:
        self (Defaults):
            If both `value` and `default` are not both `#!py None`, then return `self`.

    ??? tip "See Also"
        - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
    """
    if value is None and default is None:
        raise AttributeError(
            f"Both `value` and `default` are blank: '{value}', '{default}'.\n"
            f"If `value` is blank, then `default` cannot be blank."
        )
    return self

_validate_type 🔗

_validate_type(
    check_type: str | type | None = None,
) -> Defaults

Summary

Check to ensure that check_type is a valid Python type.
Must be one of: ["bool", "dict", "int", "float", "list", "str", "tuple"].

Parameters:

Name Type Description Default
check_type Optional[Union[str, type]]

The type to check against. Can either be an actual Python type, or it's string representation.
Defaults to None.

None

Raises:

Type Description
AttributeError

If check_type is both not None and if it is not one of the valid Python types.

Returns:

Name Type Description
self Defaults

If the type is valid, return self.

See Also
Source code in src/toolbox_python/defaults.py
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
def _validate_type(
    self,
    check_type: str | type | None = None,
) -> Defaults:
    """
    !!! note "Summary"
        Check to ensure that `check_type` is a valid Python type.<br>
        Must be one of: `#!py ["bool", "dict", "int", "float", "list", "str", "tuple"]`.

    Params:
        check_type (Optional[Union[str, type]], optional):
            The type to check against. Can either be an actual Python type, or it's string representation.<br>
            Defaults to `#!py None`.

    Raises:
        AttributeError: If `check_type` is _both_ not `#!py None` _and_ if it is not one of the valid Python types.

    Returns:
        self (Defaults):
            If the type is valid, return `self`.

    ??? tip "See Also"
        - [`Defaults.get()`][toolbox_python.defaults.Defaults.get]
    """
    valid_types: str_list = [
        "bool",
        "dict",
        "int",
        "float",
        "list",
        "str",
        "tuple",
    ]
    if check_type is None:
        return self
    elif is_type(check_type, str):
        retype = check_type
    elif type(check_type).__name__ == "type":
        retype = check_type.__name__  # type: ignore
    if retype is not None and retype not in valid_types:
        raise AttributeError(
            f"The value for `type` is invalid: `{retype}`.\n"
            f"Must be a valid type: {valid_types}."
        )
    return self

toolbox_python.defaults.defaults module-attribute 🔗

defaults = Defaults()