sain.default

The default trait for types that can have a default implementation.

Example
from sain import Default

class Generator(Default[str]):
    @staticmethod
    def default() -> str:
        return generator.random_str()

DEFAULT_GENERATOR = Generator.default()
 1# BSD 3-Clause License
 2#
 3# Copyright (c) 2022-Present, nxtlo
 4# All rights reserved.
 5#
 6# Redistribution and use in source and binary forms, with or without
 7# modification, are permitted provided that the following conditions are met:
 8#
 9# * Redistributions of source code must retain the above copyright notice, this
10#   list of conditions and the following disclaimer.
11#
12# * Redistributions in binary form must reproduce the above copyright notice,
13#   this list of conditions and the following disclaimer in the documentation
14#   and/or other materials provided with the distribution.
15#
16# * Neither the name of the copyright holder nor the names of its
17#   contributors may be used to endorse or promote products derived from
18#   this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30"""The default trait for types that can have a default implementation.
31
32Example
33-------
34```py
35
36from sain import Default
37
38class Generator(Default[str]):
39    @staticmethod
40    def default() -> str:
41        return generator.random_str()
42
43DEFAULT_GENERATOR = Generator.default()
44```
45"""
46
47from __future__ import annotations
48
49__all__ = ("Default",)
50
51import typing
52
53from .macros import rustc_diagnostic_item
54
55_T_co = typing.TypeVar("_T_co", covariant=True)
56
57
58@rustc_diagnostic_item("Default")
59@typing.runtime_checkable
60class Default(typing.Protocol[_T_co]):
61    """An interface for an object that has a default value.
62
63    Example
64    -------
65    ```py
66    from sain import Default
67
68    class Cache(Default[dict[str, Any]]):
69
70        @staticmethod
71        def default() -> dict[str, Any]:
72            return {}
73
74    cache = Cache.default()
75    print(cache)
76    assert isinstance(cache, Default)
77    # {}
78    ```
79    """
80
81    __slots__ = ()
82
83    # FIXME: `impl Default for String` knows the type of `Self` is `String` but we can't do that.
84    # So generics is the only way to achieve the same effect. But `Default` in Rust is not generic.
85    # in the future we just swap to `Self`.
86    @rustc_diagnostic_item("default_fn")
87    @staticmethod
88    def default() -> _T_co:
89        """Return the default value of the object."""
90        raise NotImplementedError
@rustc_diagnostic_item('Default')
@typing.runtime_checkable
class Default(typing.Protocol[+_T_co]):
59@rustc_diagnostic_item("Default")
60@typing.runtime_checkable
61class Default(typing.Protocol[_T_co]):
62    """An interface for an object that has a default value.
63
64    Example
65    -------
66    ```py
67    from sain import Default
68
69    class Cache(Default[dict[str, Any]]):
70
71        @staticmethod
72        def default() -> dict[str, Any]:
73            return {}
74
75    cache = Cache.default()
76    print(cache)
77    assert isinstance(cache, Default)
78    # {}
79    ```
80    """
81
82    __slots__ = ()
83
84    # FIXME: `impl Default for String` knows the type of `Self` is `String` but we can't do that.
85    # So generics is the only way to achieve the same effect. But `Default` in Rust is not generic.
86    # in the future we just swap to `Self`.
87    @rustc_diagnostic_item("default_fn")
88    @staticmethod
89    def default() -> _T_co:
90        """Return the default value of the object."""
91        raise NotImplementedError

An interface for an object that has a default value.

Example
from sain import Default

class Cache(Default[dict[str, Any]]):

    @staticmethod
    def default() -> dict[str, Any]:
        return {}

cache = Cache.default()
print(cache)
assert isinstance(cache, Default)
# {}

Implementations

This class implements Default in Rust.

Default(*args, **kwargs)
1941def _no_init_or_replace_init(self, *args, **kwargs):
1942    cls = type(self)
1943
1944    if cls._is_protocol:
1945        raise TypeError('Protocols cannot be instantiated')
1946
1947    # Already using a custom `__init__`. No need to calculate correct
1948    # `__init__` to call. This can lead to RecursionError. See bpo-45121.
1949    if cls.__init__ is not _no_init_or_replace_init:
1950        return
1951
1952    # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`.
1953    # The first instantiation of the subclass will call `_no_init_or_replace_init` which
1954    # searches for a proper new `__init__` in the MRO. The new `__init__`
1955    # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent
1956    # instantiation of the protocol subclass will thus use the new
1957    # `__init__` and no longer call `_no_init_or_replace_init`.
1958    for base in cls.__mro__:
1959        init = base.__dict__.get('__init__', _no_init_or_replace_init)
1960        if init is not _no_init_or_replace_init:
1961            cls.__init__ = init
1962            break
1963    else:
1964        # should not happen
1965        cls.__init__ = object.__init__
1966
1967    cls.__init__(self, *args, **kwargs)
@rustc_diagnostic_item('default_fn')
@staticmethod
def default() -> +_T_co:
87    @rustc_diagnostic_item("default_fn")
88    @staticmethod
89    def default() -> _T_co:
90        """Return the default value of the object."""
91        raise NotImplementedError

Return the default value of the object.