Skip to content

Modules

StuffSaver

StuffSaver class to save and reload data from a temporary folder

Attributes:

Name Type Description
path str

Path to the temporary folder where the data will be saved.

backend _type_

Backend to use for saving the data. It should have the methods load and dump.

Methods:

Name Description
exists

typing.Hashable) -> bool: Check if the data exists in the temporary folder.

reload

typing.Hashable) -> typing.Any: Reload the data from the temporary folder.

Source code in stuff_saver/stuff_saver.py
  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
 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
class StuffSaver:
    """StuffSaver class to save and reload data from a temporary folder

    Attributes:
        path (str): Path to the temporary folder where the data will be saved.
        backend (_type_): Backend to use for saving the data. It should have the methods load and dump.

    Methods:
        exists(request_key: typing.Hashable) -> bool: Check if the data exists in the temporary folder.
        reload(request_key: typing.Hashable) -> typing.Any: Reload the data from the temporary folder.



    """

    def __init__(self, path: str = "./tmp", backend: typing.Any = None):
        """Create a StuffSaver object

        Args:
            path (str, optional): Path to the temporary folder where the data will be saved. Defaults to "./tmp".
            backend (_type_, optional): Backend to use for saving the data. It should have the methods load and dump. Defaults to None which uses the pickle backend.
        """
        mkdir_p(path)
        self.path = path

        if backend is not None:
            self.backend = backend
        else:
            import pickle

            self.backend = pickle

    def exists(self, request_key: typing.Hashable) -> bool:
        """Check if the data exists in the temporary folder.

        Args:
            request_key (typing.Hashable): request_key key to check if the data exists.

        Returns:
            bool: True if the data exists in the temporary folder, False otherwise.
        """

        saving_path = os.path.join(self.path, hasher(request_key))
        return os.path.isfile(saving_path)

    def reload(self, request_key: typing.Hashable) -> typing.Any:
        """
        Reloads the data associated with the given request_key.

        Parameters:
            request_key (typing.Hashable): The request_key to reload the data for.

        Returns:
            typing.Any: The reloaded data.

        Raises:
            FileNotFoundError: If the file associated with the request_key does not exist.
            IOError: If there is an error reading the file.

        """
        saving_path = os.path.join(self.path, hasher(request_key))
        with open(saving_path, "rb") as handle:
            data = self.backend.load(handle)
        return data

    def save(self, request_key: typing.Hashable, data: typing.Any) -> None:
        """
        Save the given data to a file.

        Args:
            request_key (typing.Hashable): The request_key object used to generate the saving path.
            data (typing.Any): The data to be saved.

        Returns:
            None
        """
        saving_path = os.path.join(self.path, hasher(request_key))
        with open(saving_path, "wb") as handle:
            self.backend.dump(data, handle)

    def reload_folder(self) -> typing.List[typing.Any]:
        """
        Reloads the folder specified by `self.path` and returns a list of previously saved data.

        Returns:
            list: A list of loaded data from the files in the folder.
        """
        list_data = []
        for filename in os.listdir(self.path):
            saving_path = os.path.join(self.path, filename)
            with open(saving_path, "rb") as handle:
                data = self.backend.load(handle)
            list_data.append(data)
        return list_data

    def delete(self, request_key: typing.Hashable) -> None:
        """
        Deletes the file associated with the given request_key.
        Args:
            request_key (typing.Hashable): The request_key to delete the file for.
        Returns:
            None
        """

        saving_path = os.path.join(self.path, hasher(request_key))
        if os.path.exists(saving_path):
            os.remove(saving_path)

    def wrap(
        self,
        #
        request_key: typing.Hashable,
        fn: typing.Callable[..., typing.Any],
        *args: typing.Any,
        **kwargs: dict[str, typing.Any],
    ) -> typing.Any:
        """
        Wraps a function call with caching mechanism.
        Args:
            request_key (typing.Hashable): The key used to identify the cached result.
            fn (callable): The function to be wrapped.
            *args: Positional arguments to be passed to the function.
            **kwargs: Keyword arguments to be passed to the function.
        Returns:
            typing.Any: The result of the function call.
        Example:
            >>> def add(a, b):
            ...     return a + b
            ...
            >>> ss = StuffSaver()
            >>> wrapped_add = ss.wrap("add", add, 2, 3)
            >>> print(wrapped_add)
            5
        """

        if self.exists(request_key):
            return self.reload(request_key)
        else:
            result = fn(*args, **kwargs)
            self.save(request_key, result)
            return result

__init__(path='./tmp', backend=None)

Create a StuffSaver object

Parameters:

Name Type Description Default
path str

Path to the temporary folder where the data will be saved. Defaults to "./tmp".

'./tmp'
backend _type_

Backend to use for saving the data. It should have the methods load and dump. Defaults to None which uses the pickle backend.

None
Source code in stuff_saver/stuff_saver.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def __init__(self, path: str = "./tmp", backend: typing.Any = None):
    """Create a StuffSaver object

    Args:
        path (str, optional): Path to the temporary folder where the data will be saved. Defaults to "./tmp".
        backend (_type_, optional): Backend to use for saving the data. It should have the methods load and dump. Defaults to None which uses the pickle backend.
    """
    mkdir_p(path)
    self.path = path

    if backend is not None:
        self.backend = backend
    else:
        import pickle

        self.backend = pickle

delete(request_key)

Deletes the file associated with the given request_key. Args: request_key (typing.Hashable): The request_key to delete the file for. Returns: None

Source code in stuff_saver/stuff_saver.py
102
103
104
105
106
107
108
109
110
111
112
113
def delete(self, request_key: typing.Hashable) -> None:
    """
    Deletes the file associated with the given request_key.
    Args:
        request_key (typing.Hashable): The request_key to delete the file for.
    Returns:
        None
    """

    saving_path = os.path.join(self.path, hasher(request_key))
    if os.path.exists(saving_path):
        os.remove(saving_path)

exists(request_key)

Check if the data exists in the temporary folder.

Parameters:

Name Type Description Default
request_key Hashable

request_key key to check if the data exists.

required

Returns:

Name Type Description
bool bool

True if the data exists in the temporary folder, False otherwise.

Source code in stuff_saver/stuff_saver.py
39
40
41
42
43
44
45
46
47
48
49
50
def exists(self, request_key: typing.Hashable) -> bool:
    """Check if the data exists in the temporary folder.

    Args:
        request_key (typing.Hashable): request_key key to check if the data exists.

    Returns:
        bool: True if the data exists in the temporary folder, False otherwise.
    """

    saving_path = os.path.join(self.path, hasher(request_key))
    return os.path.isfile(saving_path)

reload(request_key)

Reloads the data associated with the given request_key.

Parameters:

Name Type Description Default
request_key Hashable

The request_key to reload the data for.

required

Returns:

Type Description
Any

typing.Any: The reloaded data.

Raises:

Type Description
FileNotFoundError

If the file associated with the request_key does not exist.

IOError

If there is an error reading the file.

Source code in stuff_saver/stuff_saver.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def reload(self, request_key: typing.Hashable) -> typing.Any:
    """
    Reloads the data associated with the given request_key.

    Parameters:
        request_key (typing.Hashable): The request_key to reload the data for.

    Returns:
        typing.Any: The reloaded data.

    Raises:
        FileNotFoundError: If the file associated with the request_key does not exist.
        IOError: If there is an error reading the file.

    """
    saving_path = os.path.join(self.path, hasher(request_key))
    with open(saving_path, "rb") as handle:
        data = self.backend.load(handle)
    return data

reload_folder()

Reloads the folder specified by self.path and returns a list of previously saved data.

Returns:

Name Type Description
list List[Any]

A list of loaded data from the files in the folder.

Source code in stuff_saver/stuff_saver.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def reload_folder(self) -> typing.List[typing.Any]:
    """
    Reloads the folder specified by `self.path` and returns a list of previously saved data.

    Returns:
        list: A list of loaded data from the files in the folder.
    """
    list_data = []
    for filename in os.listdir(self.path):
        saving_path = os.path.join(self.path, filename)
        with open(saving_path, "rb") as handle:
            data = self.backend.load(handle)
        list_data.append(data)
    return list_data

save(request_key, data)

Save the given data to a file.

Parameters:

Name Type Description Default
request_key Hashable

The request_key object used to generate the saving path.

required
data Any

The data to be saved.

required

Returns:

Type Description
None

None

Source code in stuff_saver/stuff_saver.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def save(self, request_key: typing.Hashable, data: typing.Any) -> None:
    """
    Save the given data to a file.

    Args:
        request_key (typing.Hashable): The request_key object used to generate the saving path.
        data (typing.Any): The data to be saved.

    Returns:
        None
    """
    saving_path = os.path.join(self.path, hasher(request_key))
    with open(saving_path, "wb") as handle:
        self.backend.dump(data, handle)

wrap(request_key, fn, *args, **kwargs)

Wraps a function call with caching mechanism. Args: request_key (typing.Hashable): The key used to identify the cached result. fn (callable): The function to be wrapped. args: Positional arguments to be passed to the function. *kwargs: Keyword arguments to be passed to the function. Returns: typing.Any: The result of the function call. Example: >>> def add(a, b): ... return a + b ... >>> ss = StuffSaver() >>> wrapped_add = ss.wrap("add", add, 2, 3) >>> print(wrapped_add) 5

Source code in stuff_saver/stuff_saver.py
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
def wrap(
    self,
    #
    request_key: typing.Hashable,
    fn: typing.Callable[..., typing.Any],
    *args: typing.Any,
    **kwargs: dict[str, typing.Any],
) -> typing.Any:
    """
    Wraps a function call with caching mechanism.
    Args:
        request_key (typing.Hashable): The key used to identify the cached result.
        fn (callable): The function to be wrapped.
        *args: Positional arguments to be passed to the function.
        **kwargs: Keyword arguments to be passed to the function.
    Returns:
        typing.Any: The result of the function call.
    Example:
        >>> def add(a, b):
        ...     return a + b
        ...
        >>> ss = StuffSaver()
        >>> wrapped_add = ss.wrap("add", add, 2, 3)
        >>> print(wrapped_add)
        5
    """

    if self.exists(request_key):
        return self.reload(request_key)
    else:
        result = fn(*args, **kwargs)
        self.save(request_key, result)
        return result

hasher(word)

Hashes a given word and returns the hashed value.

Parameters: - word (typing.Hashable): The word to be hashed.

Returns: - str: The hashed value of the word.

Source code in stuff_saver/utils.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def hasher(word: typing.Hashable) -> str:
    """
    Hashes a given word and returns the hashed value.

    Parameters:
    - word (typing.Hashable): The word to be hashed.

    Returns:
    - str: The hashed value of the word.
    """

    slug_word = slugify(str(word))
    hash_object = hashlib.sha512(slug_word.encode())
    slug_word = hash_object.hexdigest()
    return slug_word

mkdir_p(path)

Create a directory and its parent directories if they do not exist. Args: path (str): The path of the directory to be created. Raises: OSError: If an error occurs while creating the directory.

Source code in stuff_saver/utils.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def mkdir_p(path: str) -> None:
    """
    Create a directory and its parent directories if they do not exist.
    Args:
        path (str): The path of the directory to be created.
    Raises:
        OSError: If an error occurs while creating the directory.
    """

    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

slugify(value, lower=True)

Convert a string into a slug by removing special characters and replacing spaces with hyphens.

Parameters:

Name Type Description Default
value str

The string to be slugified.

required
lower bool

Whether to convert the slug to lowercase. Defaults to True.

True

Returns:

Name Type Description
str str

The slugified string.

Source code in stuff_saver/utils.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def slugify(value: str, lower: bool = True) -> str:
    """
    Convert a string into a slug by removing special characters and replacing spaces with hyphens.

    Args:
        value (str): The string to be slugified.
        lower (bool, optional): Whether to convert the slug to lowercase. Defaults to True.

    Returns:
        str: The slugified string.
    """

    value_bytes: bytes = unicodedata.normalize("NFKD", value).encode("utf-8", "ignore")
    value = re.sub(r"[^\w\s-]", "", value_bytes.decode("utf-8")).strip()
    if lower:
        value = value.lower()
    value = str(re.sub(r"[-\s]+", "-", value))
    return value