1
1
from __future__ import annotations
2
2
3
- from typing import Any , NoReturn , Optional , Sequence
3
+ from typing import Any , NoReturn , Optional , Sequence , Union
4
4
5
5
import os
6
6
import pathlib
@@ -19,21 +19,21 @@ class OnDiskStorage:
19
19
"""Class responsible for storing/retrieving vectors on/from disk.
20
20
21
21
Attributes:
22
- _enums: ?
23
- _files: ?
24
- is_eternal: ?
22
+ _enums: Mapping of file paths to possible Enum values.
23
+ _files: Mapping of periods to file paths for stored vectors.
24
+ is_eternal: Flag indicating if the storage of period eternity.
25
+ preserve_storage_dir: Flag indicating if folders should be preserved.
25
26
storage_dir: Path to store calculated vectors.
26
- preserve_storage_dir: ?
27
27
28
28
Args:
29
29
storage_dir: Path to store calculated vectors.
30
- is_eternal: ?
31
- preserve_storage_dir: ?
30
+ is_eternal: Flag indicating if the storage of period eternity.
31
+ preserve_storage_dir: Flag indicating if folders should be preserved.
32
32
33
33
"""
34
34
35
- _enums : Enums
36
- _files : Files
35
+ _enums : Enums = Enums ({})
36
+ _files : Files = Files ({})
37
37
is_eternal : bool
38
38
storage_dir : str
39
39
preserve_storage_dir : bool
@@ -44,13 +44,44 @@ def __init__(
44
44
is_eternal : bool = False ,
45
45
preserve_storage_dir : bool = False ,
46
46
) -> None :
47
- self ._enums = Enums ({})
48
- self ._files = Files ({})
49
47
self .is_eternal = is_eternal
50
48
self .storage_dir = storage_dir
51
49
self .preserve_storage_dir = preserve_storage_dir
52
50
53
51
def _decode_file (self , file : str ) -> Any :
52
+ """Decodes a file by loading its contents as a NumPy array.
53
+
54
+ If the file is associated with Enum values, the array is converted back
55
+ to an EnumArray object.
56
+
57
+ Args:
58
+ file: Path to the file to be decoded.
59
+
60
+ Returns:
61
+ NumPy array or EnumArray object representing the data in the file.
62
+
63
+ Examples
64
+ >>> import tempfile
65
+
66
+ >>> class Housing(enums.Enum):
67
+ ... OWNER = "Owner"
68
+ ... TENANT = "Tenant"
69
+ ... FREE_LODGER = "Free lodger"
70
+ ... HOMELESS = "Homeless"
71
+
72
+ >>> array = numpy.array([1])
73
+ >>> value = enums.EnumArray(array, Housing)
74
+ >>> instant = periods.Instant((2017, 1, 1))
75
+ >>> period = periods.Period(("year", instant, 1))
76
+
77
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
78
+ ... storage = OnDiskStorage(storage_dir)
79
+ ... storage.put(value, period)
80
+ ... storage._decode_file(storage._files[period])
81
+ EnumArray([<Housing.TENANT: 'Tenant'>])
82
+
83
+ """
84
+
54
85
enum = self ._enums .get (file )
55
86
load = numpy .load (file )
56
87
@@ -59,7 +90,34 @@ def _decode_file(self, file: str) -> Any:
59
90
60
91
return enums .EnumArray (load , enum )
61
92
62
- def get (self , period : types .Period ) -> Any :
93
+ def get (
94
+ self ,
95
+ period : types .Period ,
96
+ ) -> Optional [Union [numpy .ndarray , enums .EnumArray ]]:
97
+ """Retrieve the data for the specified period from disk.
98
+
99
+ Args:
100
+ period: The period for which data should be retrieved.
101
+
102
+ Returns:
103
+ A NumPy array or EnumArray object representing the vector for the
104
+ specified period, or None if no vector is stored for that period.
105
+
106
+ Examples:
107
+ >>> import tempfile
108
+
109
+ >>> value = numpy.array([1, 2, 3])
110
+ >>> instant = periods.Instant((2017, 1, 1))
111
+ >>> period = periods.Period(("year", instant, 1))
112
+
113
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
114
+ ... storage = OnDiskStorage(storage_dir)
115
+ ... storage.put(value, period)
116
+ ... storage.get(period)
117
+ array([1, 2, 3])
118
+
119
+ """
120
+
63
121
period = _funcs .parse_period (period , self .is_eternal )
64
122
values = self ._files .get (period )
65
123
@@ -69,6 +127,27 @@ def get(self, period: types.Period) -> Any:
69
127
return self ._decode_file (values )
70
128
71
129
def put (self , value : Any , period : types .Period ) -> None :
130
+ """Store the specified data on disk for the specified period.
131
+
132
+ Args:
133
+ value: The data to store
134
+ period: The period for which the data should be stored.
135
+
136
+ Examples:
137
+ >>> import tempfile
138
+
139
+ >>> value = numpy.array([1, 2, 3])
140
+ >>> instant = periods.Instant((2017, 1, 1))
141
+ >>> period = periods.Period(("year", instant, 1))
142
+
143
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
144
+ ... storage = OnDiskStorage(storage_dir)
145
+ ... storage.put(value, period)
146
+ ... storage.get(period)
147
+ array([1, 2, 3])
148
+
149
+ """
150
+
72
151
period = _funcs .parse_period (period , self .is_eternal )
73
152
stem = str (period )
74
153
path = os .path .join (self .storage_dir , f"{ stem } .npy" )
@@ -81,35 +160,69 @@ def put(self, value: Any, period: types.Period) -> None:
81
160
self ._files = Files ({period : path , ** self ._files })
82
161
83
162
def delete (self , period : Optional [types .Period ] = None ) -> None :
163
+ """Delete the data for the specified period from disk.
164
+
165
+ Args:
166
+ period: The period for which data should be deleted. If not
167
+ specified, all data will be deleted.
168
+
169
+ Examples:
170
+ >>> import tempfile
171
+
172
+ >>> value = numpy.array([1, 2, 3])
173
+ >>> instant = periods.Instant((2017, 1, 1))
174
+ >>> period = periods.Period(("year", instant, 1))
175
+
176
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
177
+ ... storage = OnDiskStorage(storage_dir)
178
+ ... storage.put(value, period)
179
+ ... storage.get(period)
180
+ array([1, 2, 3])
181
+
182
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
183
+ ... storage = OnDiskStorage(storage_dir)
184
+ ... storage.put(value, period)
185
+ ... storage.delete(period)
186
+ ... storage.get(period)
187
+
188
+ >>> with tempfile.TemporaryDirectory() as storage_dir:
189
+ ... storage = OnDiskStorage(storage_dir)
190
+ ... storage.put(value, period)
191
+ ... storage.delete()
192
+ ... storage.get(period)
193
+
194
+ """
195
+
84
196
if period is None :
85
197
self ._files = Files ({})
86
198
return None
87
199
88
200
period = _funcs .parse_period (period , self .is_eternal )
89
201
90
202
self ._files = Files ({
91
- period_item : value
92
- for period_item , value in self ._files .items ()
93
- if not period .contains (period_item )
203
+ key : value
204
+ for key , value in self ._files .items ()
205
+ if not period .contains (key )
94
206
})
95
207
96
208
def get_known_periods (self ) -> Sequence [types .Period ]:
97
209
"""List of storage's known periods.
98
210
99
211
Returns:
100
- A list of periods.
212
+ A sequence containing the storage's known periods.
101
213
102
214
Examples:
103
215
>>> import tempfile
104
216
217
+ >>> instant = periods.Instant((2017, 1, 1))
218
+ >>> period = periods.Period(("year", instant, 1))
219
+
105
220
>>> with tempfile.TemporaryDirectory() as storage_dir:
106
221
... storage = OnDiskStorage(storage_dir)
107
222
... storage.get_known_periods()
108
223
[]
109
224
110
225
>>> with tempfile.TemporaryDirectory() as storage_dir:
111
- ... instant = periods.Instant((2017, 1, 1))
112
- ... period = periods.Period(("year", instant, 1))
113
226
... storage = OnDiskStorage(storage_dir)
114
227
... storage.put([], period)
115
228
... storage.get_known_periods()
0 commit comments