spotforecast2 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spotforecast2/.DS_Store +0 -0
- spotforecast2/__init__.py +2 -0
- spotforecast2/data/__init__.py +0 -0
- spotforecast2/data/data.py +130 -0
- spotforecast2/data/fetch_data.py +209 -0
- spotforecast2/exceptions.py +681 -0
- spotforecast2/forecaster/.DS_Store +0 -0
- spotforecast2/forecaster/__init__.py +7 -0
- spotforecast2/forecaster/base.py +448 -0
- spotforecast2/forecaster/metrics.py +527 -0
- spotforecast2/forecaster/recursive/__init__.py +4 -0
- spotforecast2/forecaster/recursive/_forecaster_equivalent_date.py +1075 -0
- spotforecast2/forecaster/recursive/_forecaster_recursive.py +939 -0
- spotforecast2/forecaster/recursive/_warnings.py +15 -0
- spotforecast2/forecaster/utils.py +954 -0
- spotforecast2/model_selection/__init__.py +5 -0
- spotforecast2/model_selection/bayesian_search.py +453 -0
- spotforecast2/model_selection/grid_search.py +314 -0
- spotforecast2/model_selection/random_search.py +151 -0
- spotforecast2/model_selection/split_base.py +357 -0
- spotforecast2/model_selection/split_one_step.py +245 -0
- spotforecast2/model_selection/split_ts_cv.py +634 -0
- spotforecast2/model_selection/utils_common.py +718 -0
- spotforecast2/model_selection/utils_metrics.py +103 -0
- spotforecast2/model_selection/validation.py +685 -0
- spotforecast2/preprocessing/__init__.py +30 -0
- spotforecast2/preprocessing/_binner.py +378 -0
- spotforecast2/preprocessing/_common.py +123 -0
- spotforecast2/preprocessing/_differentiator.py +123 -0
- spotforecast2/preprocessing/_rolling.py +136 -0
- spotforecast2/preprocessing/curate_data.py +254 -0
- spotforecast2/preprocessing/imputation.py +92 -0
- spotforecast2/preprocessing/outlier.py +114 -0
- spotforecast2/preprocessing/split.py +139 -0
- spotforecast2/py.typed +0 -0
- spotforecast2/utils/__init__.py +43 -0
- spotforecast2/utils/convert_to_utc.py +44 -0
- spotforecast2/utils/data_transform.py +208 -0
- spotforecast2/utils/forecaster_config.py +344 -0
- spotforecast2/utils/generate_holiday.py +70 -0
- spotforecast2/utils/validation.py +569 -0
- spotforecast2/weather/__init__.py +0 -0
- spotforecast2/weather/weather_client.py +288 -0
- spotforecast2-0.0.1.dist-info/METADATA +47 -0
- spotforecast2-0.0.1.dist-info/RECORD +46 -0
- spotforecast2-0.0.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
"""Custom exceptions and warnings for spotforecast2.
|
|
2
|
+
|
|
3
|
+
This module contains all the custom warnings and error classes used
|
|
4
|
+
across spotforecast2.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
Using custom warnings::
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
from spotforecast2.exceptions import MissingValuesWarning
|
|
11
|
+
|
|
12
|
+
# Raise a warning
|
|
13
|
+
warnings.warn(
|
|
14
|
+
"Missing values detected in input data.",
|
|
15
|
+
MissingValuesWarning
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# Suppress a specific warning
|
|
19
|
+
warnings.simplefilter('ignore', category=MissingValuesWarning)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import warnings
|
|
23
|
+
import inspect
|
|
24
|
+
from functools import wraps
|
|
25
|
+
import textwrap
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
from rich.console import Console
|
|
29
|
+
from rich.panel import Panel
|
|
30
|
+
from rich.text import Text
|
|
31
|
+
|
|
32
|
+
HAS_RICH = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
HAS_RICH = False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def runtime_deprecated(
|
|
38
|
+
replacement: str = None,
|
|
39
|
+
version: str = None,
|
|
40
|
+
removal: str = None,
|
|
41
|
+
category=FutureWarning,
|
|
42
|
+
) -> object:
|
|
43
|
+
"""Decorator to mark functions or classes as deprecated.
|
|
44
|
+
|
|
45
|
+
Works for both function and class targets, and ensures warnings are visible
|
|
46
|
+
even inside Jupyter notebooks.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
replacement: Name of the replacement function/class to use instead.
|
|
50
|
+
version: Version in which the function/class was deprecated.
|
|
51
|
+
removal: Version in which the function/class will be removed.
|
|
52
|
+
category: Warning category to use. Default is FutureWarning.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Decorator function.
|
|
56
|
+
|
|
57
|
+
Examples:
|
|
58
|
+
>>> @runtime_deprecated(replacement='new_function', version='0.5', removal='1.0')
|
|
59
|
+
... def old_function():
|
|
60
|
+
... pass
|
|
61
|
+
>>> old_function() # doctest: +SKIP
|
|
62
|
+
FutureWarning: old_function() is deprecated since version 0.5; use new_function instead...
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def decorator(obj):
|
|
66
|
+
is_function = inspect.isfunction(obj) or inspect.ismethod(obj)
|
|
67
|
+
is_class = inspect.isclass(obj)
|
|
68
|
+
|
|
69
|
+
if not (is_function or is_class):
|
|
70
|
+
raise TypeError(
|
|
71
|
+
"@runtime_deprecated can only be used on functions or classes"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# ----- Build warning message -----
|
|
75
|
+
name = obj.__name__
|
|
76
|
+
message = (
|
|
77
|
+
f"{name}() is deprecated" if is_function else f"{name} class is deprecated"
|
|
78
|
+
)
|
|
79
|
+
if version:
|
|
80
|
+
message += f" since version {version}"
|
|
81
|
+
if replacement:
|
|
82
|
+
message += f"; use {replacement} instead"
|
|
83
|
+
if removal:
|
|
84
|
+
message += f". It will be removed in version {removal}."
|
|
85
|
+
else:
|
|
86
|
+
message += "."
|
|
87
|
+
|
|
88
|
+
def issue_warning():
|
|
89
|
+
"""Emit warning in a way that always shows in notebooks."""
|
|
90
|
+
with warnings.catch_warnings():
|
|
91
|
+
warnings.simplefilter("always", category)
|
|
92
|
+
warnings.warn(message, category, stacklevel=3)
|
|
93
|
+
|
|
94
|
+
# ----- Case 1: decorating a function -----
|
|
95
|
+
if is_function:
|
|
96
|
+
|
|
97
|
+
@wraps(obj)
|
|
98
|
+
def wrapper(*args, **kwargs):
|
|
99
|
+
issue_warning()
|
|
100
|
+
return obj(*args, **kwargs)
|
|
101
|
+
|
|
102
|
+
# Add metadata
|
|
103
|
+
wrapper.__deprecated__ = True
|
|
104
|
+
wrapper.__replacement__ = replacement
|
|
105
|
+
wrapper.__version__ = version
|
|
106
|
+
wrapper.__removal__ = removal
|
|
107
|
+
return wrapper
|
|
108
|
+
|
|
109
|
+
# ----- Case 2: decorating a class -----
|
|
110
|
+
elif is_class:
|
|
111
|
+
orig_init = getattr(obj, "__init__", None)
|
|
112
|
+
orig_new = getattr(obj, "__new__", None)
|
|
113
|
+
|
|
114
|
+
# Only wrap whichever exists (some classes use __new__, others __init__)
|
|
115
|
+
if orig_new and (orig_new is not object.__new__):
|
|
116
|
+
|
|
117
|
+
@wraps(orig_new)
|
|
118
|
+
def wrapped_new(cls, *args, **kwargs):
|
|
119
|
+
issue_warning()
|
|
120
|
+
return orig_new(cls, *args, **kwargs)
|
|
121
|
+
|
|
122
|
+
obj.__new__ = staticmethod(wrapped_new)
|
|
123
|
+
|
|
124
|
+
elif orig_init:
|
|
125
|
+
|
|
126
|
+
@wraps(orig_init)
|
|
127
|
+
def wrapped_init(self, *args, **kwargs):
|
|
128
|
+
issue_warning()
|
|
129
|
+
return orig_init(self, *args, **kwargs)
|
|
130
|
+
|
|
131
|
+
obj.__init__ = wrapped_init
|
|
132
|
+
|
|
133
|
+
# Add metadata
|
|
134
|
+
obj.__deprecated__ = True
|
|
135
|
+
obj.__replacement__ = replacement
|
|
136
|
+
obj.__version__ = version
|
|
137
|
+
obj.__removal__ = removal
|
|
138
|
+
|
|
139
|
+
return obj
|
|
140
|
+
|
|
141
|
+
return decorator
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class DataTypeWarning(UserWarning):
|
|
145
|
+
"""Warning for incompatible data types in exogenous data.
|
|
146
|
+
|
|
147
|
+
Used to notify there are dtypes in the exogenous data that are not
|
|
148
|
+
'int', 'float', 'bool' or 'category'. Most machine learning models do not
|
|
149
|
+
accept other data types, therefore the forecaster `fit` and `predict` may fail.
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
>>> import warnings
|
|
153
|
+
>>> warnings.warn(
|
|
154
|
+
... "Exogenous data contains unsupported dtypes.",
|
|
155
|
+
... DataTypeWarning
|
|
156
|
+
... ) # doctest: +SKIP
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
def __init__(self, message):
|
|
160
|
+
self.message = message
|
|
161
|
+
|
|
162
|
+
def __str__(self):
|
|
163
|
+
extra_message = (
|
|
164
|
+
"You can suppress this warning using: "
|
|
165
|
+
"warnings.simplefilter('ignore', category=DataTypeWarning)"
|
|
166
|
+
)
|
|
167
|
+
return self.message + "\\n" + extra_message
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class DataTransformationWarning(UserWarning):
|
|
171
|
+
"""Warning for output data in transformed space.
|
|
172
|
+
|
|
173
|
+
Used to notify that the output data is in the transformed space.
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
>>> import warnings
|
|
177
|
+
>>> warnings.warn(
|
|
178
|
+
... "Output is in transformed space.",
|
|
179
|
+
... DataTransformationWarning
|
|
180
|
+
... ) # doctest: +SKIP
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
def __init__(self, message):
|
|
184
|
+
self.message = message
|
|
185
|
+
|
|
186
|
+
def __str__(self):
|
|
187
|
+
extra_message = (
|
|
188
|
+
"You can suppress this warning using: "
|
|
189
|
+
"warnings.simplefilter('ignore', category=DataTransformationWarning)"
|
|
190
|
+
)
|
|
191
|
+
return self.message + "\\n" + extra_message
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ExogenousInterpretationWarning(UserWarning):
|
|
195
|
+
"""Warning about implications when using exogenous variables.
|
|
196
|
+
|
|
197
|
+
Used to notify about important implications when using exogenous
|
|
198
|
+
variables with models that use a two-step approach (e.g., regression + ARAR).
|
|
199
|
+
|
|
200
|
+
Examples:
|
|
201
|
+
>>> import warnings
|
|
202
|
+
>>> warnings.warn(
|
|
203
|
+
... "Exogenous variables may not be used as expected.",
|
|
204
|
+
... ExogenousInterpretationWarning
|
|
205
|
+
... ) # doctest: +SKIP
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
def __init__(self, message):
|
|
209
|
+
self.message = message
|
|
210
|
+
|
|
211
|
+
def __str__(self):
|
|
212
|
+
extra_message = (
|
|
213
|
+
"You can suppress this warning using: "
|
|
214
|
+
"warnings.simplefilter('ignore', category=ExogenousInterpretationWarning)"
|
|
215
|
+
)
|
|
216
|
+
return self.message + "\\n" + extra_message
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class FeatureOutOfRangeWarning(UserWarning):
|
|
220
|
+
"""Warning for features out of training range.
|
|
221
|
+
|
|
222
|
+
Used to notify that a feature is out of the range seen during training.
|
|
223
|
+
|
|
224
|
+
Examples:
|
|
225
|
+
>>> import warnings
|
|
226
|
+
>>> warnings.warn(
|
|
227
|
+
... "Feature value exceeds training range.",
|
|
228
|
+
... FeatureOutOfRangeWarning
|
|
229
|
+
... ) # doctest: +SKIP
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
def __init__(self, message):
|
|
233
|
+
self.message = message
|
|
234
|
+
|
|
235
|
+
def __str__(self):
|
|
236
|
+
extra_message = (
|
|
237
|
+
"You can suppress this warning using: "
|
|
238
|
+
"warnings.simplefilter('ignore', category=FeatureOutOfRangeWarning)"
|
|
239
|
+
)
|
|
240
|
+
return self.message + "\\n" + extra_message
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class IgnoredArgumentWarning(UserWarning):
|
|
244
|
+
"""Warning for ignored arguments.
|
|
245
|
+
|
|
246
|
+
Used to notify that an argument is ignored when using a method
|
|
247
|
+
or a function.
|
|
248
|
+
|
|
249
|
+
Examples:
|
|
250
|
+
>>> import warnings
|
|
251
|
+
>>> warnings.warn(
|
|
252
|
+
... "Argument 'x' is ignored in this context.",
|
|
253
|
+
... IgnoredArgumentWarning
|
|
254
|
+
... ) # doctest: +SKIP
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
def __init__(self, message):
|
|
258
|
+
self.message = message
|
|
259
|
+
|
|
260
|
+
def __str__(self):
|
|
261
|
+
extra_message = (
|
|
262
|
+
"You can suppress this warning using: "
|
|
263
|
+
"warnings.simplefilter('ignore', category=IgnoredArgumentWarning)"
|
|
264
|
+
)
|
|
265
|
+
return self.message + "\\n" + extra_message
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class InputTypeWarning(UserWarning):
|
|
269
|
+
"""Warning for inefficient input format.
|
|
270
|
+
|
|
271
|
+
Used to notify that input format is not the most efficient or
|
|
272
|
+
recommended for the forecaster.
|
|
273
|
+
|
|
274
|
+
Examples:
|
|
275
|
+
>>> import warnings
|
|
276
|
+
>>> warnings.warn(
|
|
277
|
+
... "Input format is not optimal for this forecaster.",
|
|
278
|
+
... InputTypeWarning
|
|
279
|
+
... ) # doctest: +SKIP
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
def __init__(self, message):
|
|
283
|
+
self.message = message
|
|
284
|
+
|
|
285
|
+
def __str__(self):
|
|
286
|
+
extra_message = (
|
|
287
|
+
"You can suppress this warning using: "
|
|
288
|
+
"warnings.simplefilter('ignore', category=InputTypeWarning)"
|
|
289
|
+
)
|
|
290
|
+
return self.message + "\\n" + extra_message
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class LongTrainingWarning(UserWarning):
|
|
294
|
+
"""Warning for potentially long training processes.
|
|
295
|
+
|
|
296
|
+
Used to notify that a large number of models will be trained and the
|
|
297
|
+
the process may take a while to run.
|
|
298
|
+
|
|
299
|
+
Examples:
|
|
300
|
+
>>> import warnings
|
|
301
|
+
>>> warnings.warn(
|
|
302
|
+
... "Training may take a long time.",
|
|
303
|
+
... LongTrainingWarning
|
|
304
|
+
... ) # doctest: +SKIP
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
def __init__(self, message):
|
|
308
|
+
self.message = message
|
|
309
|
+
|
|
310
|
+
def __str__(self):
|
|
311
|
+
extra_message = (
|
|
312
|
+
"You can suppress this warning using: "
|
|
313
|
+
"warnings.simplefilter('ignore', category=LongTrainingWarning)"
|
|
314
|
+
)
|
|
315
|
+
return self.message + "\\n" + extra_message
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class MissingExogWarning(UserWarning):
|
|
319
|
+
"""Warning for missing exogenous variables.
|
|
320
|
+
|
|
321
|
+
Used to indicate that there are missing exogenous variables in the
|
|
322
|
+
data. Most machine learning models do not accept missing values, so the
|
|
323
|
+
Forecaster's `fit' and `predict' methods may fail.
|
|
324
|
+
|
|
325
|
+
Examples:
|
|
326
|
+
>>> import warnings
|
|
327
|
+
>>> warnings.warn(
|
|
328
|
+
... "Missing exogenous variables detected.",
|
|
329
|
+
... MissingExogWarning
|
|
330
|
+
... ) # doctest: +SKIP
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
def __init__(self, message):
|
|
334
|
+
self.message = message
|
|
335
|
+
|
|
336
|
+
def __str__(self):
|
|
337
|
+
extra_message = (
|
|
338
|
+
"You can suppress this warning using: "
|
|
339
|
+
"warnings.simplefilter('ignore', category=MissingExogWarning)"
|
|
340
|
+
)
|
|
341
|
+
return self.message + "\\n" + extra_message
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class MissingValuesWarning(UserWarning):
|
|
345
|
+
"""Warning for missing values in data.
|
|
346
|
+
|
|
347
|
+
Used to indicate that there are missing values in the data. This
|
|
348
|
+
warning occurs when the input data contains missing values, or the training
|
|
349
|
+
matrix generates missing values. Most machine learning models do not accept
|
|
350
|
+
missing values, so the Forecaster's `fit' and `predict' methods may fail.
|
|
351
|
+
|
|
352
|
+
Examples:
|
|
353
|
+
>>> import warnings
|
|
354
|
+
>>> warnings.warn(
|
|
355
|
+
... "Missing values detected in input data.",
|
|
356
|
+
... MissingValuesWarning
|
|
357
|
+
... ) # doctest: +SKIP
|
|
358
|
+
"""
|
|
359
|
+
|
|
360
|
+
def __init__(self, message):
|
|
361
|
+
self.message = message
|
|
362
|
+
|
|
363
|
+
def __str__(self):
|
|
364
|
+
extra_message = (
|
|
365
|
+
"You can suppress this warning using: "
|
|
366
|
+
"warnings.simplefilter('ignore', category=MissingValuesWarning)"
|
|
367
|
+
)
|
|
368
|
+
return self.message + "\\n" + extra_message
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class OneStepAheadValidationWarning(UserWarning):
|
|
372
|
+
"""Warning for one-step-ahead validation usage.
|
|
373
|
+
|
|
374
|
+
Used to notify that the one-step-ahead validation is being used.
|
|
375
|
+
|
|
376
|
+
Examples:
|
|
377
|
+
>>> import warnings
|
|
378
|
+
>>> warnings.warn(
|
|
379
|
+
... "Using one-step-ahead validation.",
|
|
380
|
+
... OneStepAheadValidationWarning
|
|
381
|
+
... ) # doctest: +SKIP
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
def __init__(self, message):
|
|
385
|
+
self.message = message
|
|
386
|
+
|
|
387
|
+
def __str__(self):
|
|
388
|
+
extra_message = (
|
|
389
|
+
"You can suppress this warning using: "
|
|
390
|
+
"warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)"
|
|
391
|
+
)
|
|
392
|
+
return self.message + "\\n" + extra_message
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class ResidualsUsageWarning(UserWarning):
|
|
396
|
+
"""Warning for incorrect residuals usage.
|
|
397
|
+
|
|
398
|
+
Used to notify that a residual are not correctly used in the
|
|
399
|
+
probabilistic forecasting process.
|
|
400
|
+
|
|
401
|
+
Examples:
|
|
402
|
+
>>> import warnings
|
|
403
|
+
>>> warnings.warn(
|
|
404
|
+
... "Residuals are not properly used.",
|
|
405
|
+
... ResidualsUsageWarning
|
|
406
|
+
... ) # doctest: +SKIP
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
def __init__(self, message):
|
|
410
|
+
self.message = message
|
|
411
|
+
|
|
412
|
+
def __str__(self):
|
|
413
|
+
extra_message = (
|
|
414
|
+
"You can suppress this warning using: "
|
|
415
|
+
"warnings.simplefilter('ignore', category=ResidualsUsageWarning)"
|
|
416
|
+
)
|
|
417
|
+
return self.message + "\\n" + extra_message
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
class UnknownLevelWarning(UserWarning):
|
|
421
|
+
"""Warning for unknown levels in prediction.
|
|
422
|
+
|
|
423
|
+
Used to notify that a level being predicted was not part of the
|
|
424
|
+
training data.
|
|
425
|
+
|
|
426
|
+
Examples:
|
|
427
|
+
>>> import warnings
|
|
428
|
+
>>> warnings.warn(
|
|
429
|
+
... "Predicting for an unknown level.",
|
|
430
|
+
... UnknownLevelWarning
|
|
431
|
+
... ) # doctest: +SKIP
|
|
432
|
+
"""
|
|
433
|
+
|
|
434
|
+
def __init__(self, message):
|
|
435
|
+
self.message = message
|
|
436
|
+
|
|
437
|
+
def __str__(self):
|
|
438
|
+
extra_message = (
|
|
439
|
+
"You can suppress this warning using: "
|
|
440
|
+
"warnings.simplefilter('ignore', category=UnknownLevelWarning)"
|
|
441
|
+
)
|
|
442
|
+
return self.message + "\\n" + extra_message
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class SaveLoadSkforecastWarning(UserWarning):
|
|
446
|
+
"""Warning for save/load operations.
|
|
447
|
+
|
|
448
|
+
Used to notify any issues that may arise when saving or loading
|
|
449
|
+
a forecaster.
|
|
450
|
+
|
|
451
|
+
Examples:
|
|
452
|
+
>>> import warnings
|
|
453
|
+
>>> warnings.warn(
|
|
454
|
+
... "Issues detected when saving forecaster.",
|
|
455
|
+
... SaveLoadSkforecastWarning
|
|
456
|
+
... ) # doctest: +SKIP
|
|
457
|
+
"""
|
|
458
|
+
|
|
459
|
+
def __init__(self, message):
|
|
460
|
+
self.message = message
|
|
461
|
+
|
|
462
|
+
def __str__(self):
|
|
463
|
+
extra_message = (
|
|
464
|
+
"You can suppress this warning using: "
|
|
465
|
+
"warnings.simplefilter('ignore', category=SaveLoadSkforecastWarning)"
|
|
466
|
+
)
|
|
467
|
+
return self.message + "\\n" + extra_message
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
class SpotforecastVersionWarning(UserWarning):
|
|
471
|
+
"""Warning for version mismatch.
|
|
472
|
+
|
|
473
|
+
Used to notify that the version installed in the
|
|
474
|
+
environment differs from the version used to initialize the forecaster.
|
|
475
|
+
|
|
476
|
+
Examples:
|
|
477
|
+
>>> import warnings
|
|
478
|
+
>>> warnings.warn(
|
|
479
|
+
... "Version mismatch detected.",
|
|
480
|
+
... SpotforecastVersionWarning
|
|
481
|
+
... ) # doctest: +SKIP
|
|
482
|
+
"""
|
|
483
|
+
|
|
484
|
+
def __init__(self, message):
|
|
485
|
+
self.message = message
|
|
486
|
+
|
|
487
|
+
def __str__(self):
|
|
488
|
+
extra_message = (
|
|
489
|
+
"You can suppress this warning using: "
|
|
490
|
+
"warnings.simplefilter('ignore', category=SpotforecastVersionWarning)"
|
|
491
|
+
)
|
|
492
|
+
return self.message + "\\n" + extra_message
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class NotFittedError(ValueError, AttributeError):
|
|
496
|
+
"""Exception class to raise if estimator is used before fitting.
|
|
497
|
+
|
|
498
|
+
This class inherits from both ValueError and AttributeError to help with
|
|
499
|
+
exception handling and backward compatibility.
|
|
500
|
+
|
|
501
|
+
Examples:
|
|
502
|
+
>>> from spotforecast2.exceptions import NotFittedError
|
|
503
|
+
>>> try:
|
|
504
|
+
... raise NotFittedError("Forecaster not fitted")
|
|
505
|
+
... except NotFittedError as e:
|
|
506
|
+
... print(e)
|
|
507
|
+
Forecaster not fitted
|
|
508
|
+
"""
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
warn_skforecast_categories = [
|
|
512
|
+
DataTypeWarning,
|
|
513
|
+
DataTransformationWarning,
|
|
514
|
+
ExogenousInterpretationWarning,
|
|
515
|
+
FeatureOutOfRangeWarning,
|
|
516
|
+
IgnoredArgumentWarning,
|
|
517
|
+
InputTypeWarning,
|
|
518
|
+
LongTrainingWarning,
|
|
519
|
+
MissingExogWarning,
|
|
520
|
+
MissingValuesWarning,
|
|
521
|
+
OneStepAheadValidationWarning,
|
|
522
|
+
ResidualsUsageWarning,
|
|
523
|
+
UnknownLevelWarning,
|
|
524
|
+
SaveLoadSkforecastWarning,
|
|
525
|
+
SpotforecastVersionWarning,
|
|
526
|
+
]
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def format_warning_handler(
|
|
530
|
+
message: str,
|
|
531
|
+
category: str,
|
|
532
|
+
filename: str,
|
|
533
|
+
lineno: str,
|
|
534
|
+
file: object = None,
|
|
535
|
+
line: str = None,
|
|
536
|
+
) -> None:
|
|
537
|
+
"""Custom warning handler to format warnings in a box.
|
|
538
|
+
|
|
539
|
+
Args:
|
|
540
|
+
message: Warning message.
|
|
541
|
+
category: Warning category.
|
|
542
|
+
filename: Filename where the warning was raised.
|
|
543
|
+
lineno: Line number where the warning was raised.
|
|
544
|
+
file: File where the warning was raised.
|
|
545
|
+
line: Line where the warning was raised.
|
|
546
|
+
|
|
547
|
+
Returns:
|
|
548
|
+
None
|
|
549
|
+
|
|
550
|
+
Examples:
|
|
551
|
+
>>> # This is used internally by the warnings module
|
|
552
|
+
>>> set_warnings_style('skforecast') # doctest: +SKIP
|
|
553
|
+
"""
|
|
554
|
+
|
|
555
|
+
if isinstance(message, tuple(warn_skforecast_categories)):
|
|
556
|
+
width = 88
|
|
557
|
+
title = type(message).__name__
|
|
558
|
+
output_text = ["\\n"]
|
|
559
|
+
|
|
560
|
+
wrapped_message = textwrap.fill(
|
|
561
|
+
str(message), width=width - 2, expand_tabs=True, replace_whitespace=True
|
|
562
|
+
)
|
|
563
|
+
title_top_border = f"╭{'─' * ((width - len(title) - 2) // 2)} {title} {'─' * ((width - len(title) - 2) // 2)}╮"
|
|
564
|
+
if len(title) % 2 != 0:
|
|
565
|
+
title_top_border = title_top_border[:-1] + "─" + "╮"
|
|
566
|
+
bottom_border = f"╰{'─' * width}╯"
|
|
567
|
+
output_text.append(title_top_border)
|
|
568
|
+
|
|
569
|
+
for line in wrapped_message.split("\\n"):
|
|
570
|
+
output_text.append(f"│ {line.ljust(width - 2)} │")
|
|
571
|
+
|
|
572
|
+
output_text.append(bottom_border)
|
|
573
|
+
output_text = "\\n".join(output_text)
|
|
574
|
+
color = "\\033[38;5;208m"
|
|
575
|
+
reset = "\\033[0m"
|
|
576
|
+
output_text = f"{color}{output_text}{reset}"
|
|
577
|
+
print(output_text)
|
|
578
|
+
else:
|
|
579
|
+
# Fallback to default Python warning formatting
|
|
580
|
+
warnings._original_showwarning(message, category, filename, lineno, file, line)
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
def rich_warning_handler(
|
|
584
|
+
message: str,
|
|
585
|
+
category: str,
|
|
586
|
+
filename: str,
|
|
587
|
+
lineno: str,
|
|
588
|
+
file: object = None,
|
|
589
|
+
line: str = None,
|
|
590
|
+
) -> None:
|
|
591
|
+
"""Custom handler for warnings that uses rich to display formatted panels.
|
|
592
|
+
|
|
593
|
+
Args:
|
|
594
|
+
message: Warning message.
|
|
595
|
+
category: Warning category.
|
|
596
|
+
filename: Filename where the warning was raised.
|
|
597
|
+
lineno: Line number where the warning was raised.
|
|
598
|
+
file: File where the warning was raised.
|
|
599
|
+
line: Line where the warning was raised.
|
|
600
|
+
|
|
601
|
+
Returns:
|
|
602
|
+
None
|
|
603
|
+
|
|
604
|
+
Examples:
|
|
605
|
+
>>> # This is used internally when rich is available
|
|
606
|
+
>>> set_warnings_style('skforecast') # doctest: +SKIP
|
|
607
|
+
"""
|
|
608
|
+
|
|
609
|
+
if isinstance(message, tuple(warn_skforecast_categories)):
|
|
610
|
+
if not HAS_RICH:
|
|
611
|
+
# Fallback to format_warning_handler if rich is not available
|
|
612
|
+
format_warning_handler(message, category, filename, lineno, file, line)
|
|
613
|
+
return
|
|
614
|
+
|
|
615
|
+
console = Console()
|
|
616
|
+
|
|
617
|
+
category_name = category.__name__
|
|
618
|
+
text = (
|
|
619
|
+
f"{message.message}\\n\\n"
|
|
620
|
+
f"Category : spotforecast2.exceptions.{category_name}\\n"
|
|
621
|
+
f"Location : {filename}:{lineno}\\n"
|
|
622
|
+
f"Suppress : warnings.simplefilter('ignore', category={category_name})"
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
panel = Panel(
|
|
626
|
+
Text(text, justify="left"),
|
|
627
|
+
title=category_name,
|
|
628
|
+
title_align="center",
|
|
629
|
+
border_style="color(214)",
|
|
630
|
+
width=88,
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
console.print(panel)
|
|
634
|
+
else:
|
|
635
|
+
# Fallback to default Python warning formatting
|
|
636
|
+
warnings._original_showwarning(message, category, filename, lineno, file, line)
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
def set_warnings_style(style: str = "skforecast") -> None:
|
|
640
|
+
"""Set the warning handler based on the provided style.
|
|
641
|
+
|
|
642
|
+
Args:
|
|
643
|
+
style: The style of the warning handler. Either 'skforecast' or 'default'.
|
|
644
|
+
|
|
645
|
+
Returns:
|
|
646
|
+
None
|
|
647
|
+
|
|
648
|
+
Examples:
|
|
649
|
+
>>> set_warnings_style('skforecast')
|
|
650
|
+
>>> # Now warnings will be displayed with formatting
|
|
651
|
+
>>> set_warnings_style('default')
|
|
652
|
+
>>> # Back to default Python warning format
|
|
653
|
+
"""
|
|
654
|
+
if style == "skforecast":
|
|
655
|
+
if not hasattr(warnings, "_original_showwarning"):
|
|
656
|
+
warnings._original_showwarning = warnings.showwarning
|
|
657
|
+
if HAS_RICH:
|
|
658
|
+
warnings.showwarning = rich_warning_handler
|
|
659
|
+
else:
|
|
660
|
+
warnings.showwarning = format_warning_handler
|
|
661
|
+
else:
|
|
662
|
+
if hasattr(warnings, "_original_showwarning"):
|
|
663
|
+
warnings.showwarning = warnings._original_showwarning
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
set_warnings_style(style="skforecast")
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
def set_skforecast_warnings(suppress_warnings: bool, action: str = "ignore") -> None:
|
|
670
|
+
"""
|
|
671
|
+
Suppress spotforecast warnings.
|
|
672
|
+
|
|
673
|
+
Args:
|
|
674
|
+
suppress_warnings : bool
|
|
675
|
+
If True, spotforecast warnings will be suppressed.
|
|
676
|
+
action : str, default 'ignore'
|
|
677
|
+
Action to take regarding the warnings.
|
|
678
|
+
"""
|
|
679
|
+
if suppress_warnings:
|
|
680
|
+
for category in warn_skforecast_categories:
|
|
681
|
+
warnings.simplefilter(action, category=category)
|
|
Binary file
|