openstef 3.4.14__py3-none-any.whl → 3.4.16__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.
- openstef/data_classes/data_prep.py +1 -1
- openstef/data_classes/prediction_job.py +1 -1
- openstef/enums.py +0 -6
- openstef/feature_engineering/data_preparation.py +5 -5
- openstef/metrics/figure.py +3 -0
- openstef/metrics/metrics.py +7 -1
- openstef/model/confidence_interval_applicator.py +3 -0
- openstef/model/model_creator.py +1 -1
- openstef/model/objective_creator.py +1 -1
- openstef/model/regressors/arima.py +1 -1
- openstef/model/regressors/xgb_quantile.py +3 -0
- openstef/model/serializer.py +3 -0
- openstef/model_selection/model_selection.py +3 -0
- openstef/monitoring/performance_meter.py +1 -2
- openstef/pipeline/create_basecase_forecast.py +4 -1
- openstef/pipeline/create_component_forecast.py +1 -2
- openstef/pipeline/create_forecast.py +7 -0
- openstef/pipeline/optimize_hyperparameters.py +8 -1
- openstef/pipeline/train_create_forecast_backtest.py +8 -0
- openstef/pipeline/train_model.py +15 -0
- openstef/pipeline/utils.py +3 -0
- openstef/tasks/calculate_kpi.py +0 -7
- openstef/tasks/create_components_forecast.py +5 -1
- openstef/tasks/train_model.py +7 -5
- openstef/validation/validation.py +5 -2
- {openstef-3.4.14.dist-info → openstef-3.4.16.dist-info}/METADATA +1 -1
- {openstef-3.4.14.dist-info → openstef-3.4.16.dist-info}/RECORD +30 -31
- openstef/tasks/run_tracy.py +0 -145
- {openstef-3.4.14.dist-info → openstef-3.4.16.dist-info}/LICENSE +0 -0
- {openstef-3.4.14.dist-info → openstef-3.4.16.dist-info}/WHEEL +0 -0
- {openstef-3.4.14.dist-info → openstef-3.4.16.dist-info}/top_level.txt +0 -0
@@ -6,9 +6,9 @@ from typing import Optional, Union
|
|
6
6
|
|
7
7
|
from pydantic.v1 import BaseModel
|
8
8
|
|
9
|
+
from openstef.data_classes.data_prep import DataPrepDataClass
|
9
10
|
from openstef.data_classes.model_specifications import ModelSpecificationDataClass
|
10
11
|
from openstef.data_classes.split_function import SplitFuncDataClass
|
11
|
-
from openstef.data_classes.data_prep import DataPrepDataClass
|
12
12
|
from openstef.enums import PipelineType
|
13
13
|
|
14
14
|
|
openstef/enums.py
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# SPDX-FileCopyrightText: 2017-2023 Alliander N.V. <korte.termijn.prognoses@alliander.com> # noqa E501>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MPL-2.0
|
4
|
-
import structlog
|
5
|
-
|
6
4
|
from abc import ABC, abstractmethod
|
5
|
+
from datetime import timedelta
|
7
6
|
from typing import Optional
|
8
7
|
|
9
8
|
import pandas as pd
|
10
|
-
|
9
|
+
import structlog
|
10
|
+
|
11
11
|
from openstef.data_classes.model_specifications import ModelSpecificationDataClass
|
12
12
|
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
13
|
-
from openstef.model.regressors.regressor import OpenstfRegressor
|
14
13
|
from openstef.feature_engineering.feature_applicator import (
|
15
|
-
TrainFeatureApplicator,
|
16
14
|
OperationalPredictFeatureApplicator,
|
15
|
+
TrainFeatureApplicator,
|
17
16
|
)
|
18
17
|
from openstef.feature_engineering.general import (
|
19
18
|
enforce_feature_order,
|
20
19
|
remove_non_requested_feature_columns,
|
21
20
|
)
|
21
|
+
from openstef.model.regressors.regressor import OpenstfRegressor
|
22
22
|
from openstef.pipeline.utils import generate_forecast_datetime_range
|
23
23
|
|
24
24
|
|
openstef/metrics/figure.py
CHANGED
openstef/metrics/metrics.py
CHANGED
@@ -25,6 +25,9 @@ def get_eval_metric_function(metric_name: str) -> Callable:
|
|
25
25
|
Returns:
|
26
26
|
Function to calculate the metric.
|
27
27
|
|
28
|
+
Raises:
|
29
|
+
KeyError: If the metric is not available.
|
30
|
+
|
28
31
|
"""
|
29
32
|
evaluation_function = {
|
30
33
|
"rmse": rmse,
|
@@ -130,6 +133,9 @@ def r_mae_highest(
|
|
130
133
|
|
131
134
|
The range is based on the load range of the previous two weeks.
|
132
135
|
|
136
|
+
Raises:
|
137
|
+
ValueError: If the length of the realised and forecast arrays are not equal.
|
138
|
+
|
133
139
|
"""
|
134
140
|
# Check if length of both arrays is equal
|
135
141
|
if len(np.array(realised)) != len(np.array(forecast)):
|
@@ -395,7 +401,7 @@ def xgb_quantile_obj(
|
|
395
401
|
Args:
|
396
402
|
preds: numpy.ndarray
|
397
403
|
dmatrix: xgboost.DMatrix
|
398
|
-
quantile: float
|
404
|
+
quantile: float between 0 and 1
|
399
405
|
|
400
406
|
Returns:
|
401
407
|
Gradient and Hessian
|
@@ -74,6 +74,9 @@ class ConfidenceIntervalApplicator:
|
|
74
74
|
Forecast with added standard deviation. DataFrame with columns:
|
75
75
|
"forecast", "stdev"
|
76
76
|
|
77
|
+
Raises:
|
78
|
+
ModelWithoutStDev: If the model does not have a valid standard deviation.
|
79
|
+
|
77
80
|
"""
|
78
81
|
minimal_resolution: int = 15 # Minimal time resolution in minutes
|
79
82
|
standard_deviation = self.model.standard_deviation
|
openstef/model/model_creator.py
CHANGED
@@ -6,13 +6,13 @@ from typing import Union
|
|
6
6
|
import structlog
|
7
7
|
|
8
8
|
from openstef.enums import MLModelType
|
9
|
+
from openstef.model.regressors.arima import ARIMAOpenstfRegressor
|
9
10
|
from openstef.model.regressors.custom_regressor import is_custom_type, load_custom_model
|
10
11
|
from openstef.model.regressors.lgbm import LGBMOpenstfRegressor
|
11
12
|
from openstef.model.regressors.linear import LinearOpenstfRegressor
|
12
13
|
from openstef.model.regressors.regressor import OpenstfRegressor
|
13
14
|
from openstef.model.regressors.xgb import XGBOpenstfRegressor
|
14
15
|
from openstef.model.regressors.xgb_quantile import XGBQuantileOpenstfRegressor
|
15
|
-
from openstef.model.regressors.arima import ARIMAOpenstfRegressor
|
16
16
|
|
17
17
|
logger = structlog.get_logger(__name__)
|
18
18
|
|
@@ -6,12 +6,12 @@ from typing import Union
|
|
6
6
|
|
7
7
|
from openstef.enums import MLModelType
|
8
8
|
from openstef.model.objective import (
|
9
|
+
ARIMARegressorObjective,
|
9
10
|
LGBRegressorObjective,
|
10
11
|
LinearRegressorObjective,
|
11
12
|
RegressorObjective,
|
12
13
|
XGBQuantileRegressorObjective,
|
13
14
|
XGBRegressorObjective,
|
14
|
-
ARIMARegressorObjective,
|
15
15
|
)
|
16
16
|
from openstef.model.regressors.custom_regressor import (
|
17
17
|
create_custom_objective,
|
@@ -52,6 +52,9 @@ class XGBQuantileOpenstfRegressor(OpenstfRegressor):
|
|
52
52
|
alpha: Alpha
|
53
53
|
max_delta_step: Maximum delta step
|
54
54
|
|
55
|
+
Raises:
|
56
|
+
ValueError in case quantile 0.5 is not in the requested quantiles
|
57
|
+
|
55
58
|
"""
|
56
59
|
super().__init__()
|
57
60
|
# Check if quantile 0.5 is pressent this is required
|
openstef/model/serializer.py
CHANGED
@@ -140,6 +140,9 @@ def split_data_train_validation_test(
|
|
140
140
|
- Validation data.
|
141
141
|
- Test data.
|
142
142
|
|
143
|
+
Raises:
|
144
|
+
ValueError: When the test and validation fractions are too high.
|
145
|
+
|
143
146
|
"""
|
144
147
|
test_fraction = test_fraction if back_test else 0
|
145
148
|
train_fraction = 1 - (test_fraction + validation_fraction)
|
@@ -20,8 +20,7 @@ class PerformanceMeter:
|
|
20
20
|
|
21
21
|
Args:
|
22
22
|
level_label: The label of the new level. This could i.e. be 'task'
|
23
|
-
level_name: The name of the specified level.
|
24
|
-
'tracy_todo'
|
23
|
+
level_name: The name of the specified level.
|
25
24
|
**kwargs: Any other kwargs are appended to the logging.
|
26
25
|
|
27
26
|
Returns:
|
@@ -7,7 +7,7 @@ import pandas as pd
|
|
7
7
|
import structlog
|
8
8
|
|
9
9
|
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
10
|
-
from openstef.exceptions import
|
10
|
+
from openstef.exceptions import InputDataOngoingZeroFlatlinerError, NoRealisedLoadError
|
11
11
|
from openstef.feature_engineering.feature_applicator import (
|
12
12
|
OperationalPredictFeatureApplicator,
|
13
13
|
)
|
@@ -38,6 +38,9 @@ def create_basecase_forecast_pipeline(
|
|
38
38
|
Returns:
|
39
39
|
Base case forecast
|
40
40
|
|
41
|
+
Raises:
|
42
|
+
NoRealisedLoadError: When no realised load for given datetime range.
|
43
|
+
|
41
44
|
"""
|
42
45
|
logger = structlog.get_logger(__name__)
|
43
46
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# SPDX-License-Identifier: MPL-2.0
|
4
4
|
|
5
5
|
import joblib
|
6
|
+
import numpy as np
|
6
7
|
import pandas as pd
|
7
8
|
import structlog
|
8
9
|
|
@@ -12,8 +13,6 @@ from openstef.data_classes.prediction_job import PredictionJobDataClass
|
|
12
13
|
from openstef.enums import ForecastType
|
13
14
|
from openstef.model.regressors.dazls import Dazls
|
14
15
|
|
15
|
-
import numpy as np
|
16
|
-
|
17
16
|
# Set the path for the Dazls stored model
|
18
17
|
DAZLS_STORED = str(
|
19
18
|
PROJECT_ROOT / "openstef" / "data" / "dazls_model_3.4.7" / "dazls_stored_3.4.7_"
|
@@ -40,6 +40,10 @@ def create_forecast_pipeline(
|
|
40
40
|
Returns:
|
41
41
|
DataFrame with the forecast
|
42
42
|
|
43
|
+
Raises:
|
44
|
+
InputDataOngoingZeroFlatlinerError: When all recent load measurements are zero.
|
45
|
+
LookupError: When no model is found for the given prediction job in MLflow.
|
46
|
+
|
43
47
|
"""
|
44
48
|
prediction_model_pid = pj["id"]
|
45
49
|
# Use the alternative forecast model if it's specify in the pj
|
@@ -76,6 +80,9 @@ def create_forecast_pipeline_core(
|
|
76
80
|
Returns:
|
77
81
|
Forecast
|
78
82
|
|
83
|
+
Raises:
|
84
|
+
InputDataOngoingZeroFlatlinerError: When all recent load measurements are zero.
|
85
|
+
|
79
86
|
"""
|
80
87
|
logger = structlog.get_logger(__name__)
|
81
88
|
|
@@ -21,12 +21,12 @@ from openstef.model.objective import RegressorObjective
|
|
21
21
|
from openstef.model.objective_creator import ObjectiveCreator
|
22
22
|
from openstef.model.regressors.regressor import OpenstfRegressor
|
23
23
|
from openstef.model.serializer import MLflowSerializer
|
24
|
+
from openstef.model_selection.model_selection import split_data_train_validation_test
|
24
25
|
from openstef.pipeline.train_model import (
|
25
26
|
DEFAULT_TRAIN_HORIZONS_HOURS,
|
26
27
|
train_model_pipeline_core,
|
27
28
|
)
|
28
29
|
from openstef.validation import validation
|
29
|
-
from openstef.model_selection.model_selection import split_data_train_validation_test
|
30
30
|
|
31
31
|
optuna.logging.enable_propagation() # Propagate logs to the root logger.
|
32
32
|
optuna.logging.disable_default_handler() # Stop showing logs in sys.stderr.
|
@@ -59,6 +59,9 @@ def optimize_hyperparameters_pipeline(
|
|
59
59
|
|
60
60
|
Raises:
|
61
61
|
ValueError: If the input_date is insufficient.
|
62
|
+
InputDataInsufficientError: If the input dataframe is empty.
|
63
|
+
InputDataWrongColumnOrderError: If the load column is missing in the input dataframe.
|
64
|
+
OldModelHigherScoreError: When old model is better than new model.
|
62
65
|
|
63
66
|
Returns:
|
64
67
|
Optimized hyperparameters.
|
@@ -119,6 +122,10 @@ def optimize_hyperparameters_pipeline_core(
|
|
119
122
|
|
120
123
|
Raises:
|
121
124
|
ValueError: If the input_date is insufficient.
|
125
|
+
InputDataInsufficientError: If the input dataframe is empty.
|
126
|
+
InputDataWrongColumnOrderError: If the load column is missing in the input dataframe.
|
127
|
+
OldModelHigherScoreError: When old model is better than new model.
|
128
|
+
InputDataOngoingZeroFlatlinerError: When all recent load measurements are zero.
|
122
129
|
|
123
130
|
Returns:
|
124
131
|
- Best model,
|
@@ -56,6 +56,11 @@ def train_model_and_forecast_back_test(
|
|
56
56
|
- Validation data sets (list[pd.DataFrame])
|
57
57
|
- Test data sets (list[pd.DataFrame])
|
58
58
|
|
59
|
+
Raises:
|
60
|
+
InputDataInsufficientError: when input data is insufficient.
|
61
|
+
InputDataWrongColumnOrderError: when input data has a invalid column order.
|
62
|
+
ValueError: when the horizon is a string and the corresponding column in not in the input data
|
63
|
+
InputDataOngoingZeroFlatlinerError: when all recent load measurements are zero.
|
59
64
|
"""
|
60
65
|
if pj.backtest_split_func is None:
|
61
66
|
backtest_split_func = backtest_split_default
|
@@ -124,6 +129,9 @@ def train_model_and_forecast_test_core(
|
|
124
129
|
- The trained model
|
125
130
|
- The forecast on the test set.
|
126
131
|
|
132
|
+
Raises:
|
133
|
+
NotImplementedError: When using invalid model type in the prediction job.
|
134
|
+
InputDataWrongColumnOrderError: When 'load' column is not first and 'horizon' column is not last.
|
127
135
|
"""
|
128
136
|
model = train_model.train_pipeline_step_train_model(
|
129
137
|
pj, modelspecs, train_data, validation_data
|
openstef/pipeline/train_model.py
CHANGED
@@ -60,6 +60,13 @@ def train_model_pipeline(
|
|
60
60
|
- The validation dataset with forecasts
|
61
61
|
- The test dataset with forecasts
|
62
62
|
|
63
|
+
Raises:
|
64
|
+
InputDataInsufficientError: when input data is insufficient.
|
65
|
+
InputDataWrongColumnOrderError: when input data has a invalid column order.
|
66
|
+
'load' column should be first and 'horizon' column last.
|
67
|
+
OldModelHigherScoreError: When old model is better than new model.
|
68
|
+
SkipSaveTrainingForecasts: If old model is better or younger than `MAXIMUM_MODEL_AGE`, the model is not saved.
|
69
|
+
|
63
70
|
"""
|
64
71
|
# Initialize serializer
|
65
72
|
serializer = MLflowSerializer(mlflow_tracking_uri=mlflow_tracking_uri)
|
@@ -164,6 +171,7 @@ def train_model_pipeline_core(
|
|
164
171
|
InputDataInsufficientError: when input data is insufficient.
|
165
172
|
InputDataWrongColumnOrderError: when input data has a invalid column order.
|
166
173
|
OldModelHigherScoreError: When old model is better than new model.
|
174
|
+
InputDataOngoingZeroFlatlinerError: when all recent load measurements are zero.
|
167
175
|
|
168
176
|
Returns:
|
169
177
|
- Fitted_model (OpenstfRegressor)
|
@@ -257,6 +265,8 @@ def train_pipeline_common(
|
|
257
265
|
Raises:
|
258
266
|
InputDataInsufficientError: when input data is insufficient.
|
259
267
|
InputDataWrongColumnOrderError: when input data has a invalid column order.
|
268
|
+
'load' column should be first and 'horizon' column last.
|
269
|
+
InputDataOngoingZeroFlatlinerError: when all recent load measurements are zero.
|
260
270
|
|
261
271
|
"""
|
262
272
|
data_with_features = train_pipeline_step_compute_features(
|
@@ -346,6 +356,7 @@ def train_pipeline_step_compute_features(
|
|
346
356
|
InputDataInsufficientError: when input data is insufficient.
|
347
357
|
InputDataWrongColumnOrderError: when input data has a invalid column order.
|
348
358
|
ValueError: when the horizon is a string and the corresponding column in not in the input data
|
359
|
+
InputDataOngoingZeroFlatlinerError: when all recent load measurements are zero.
|
349
360
|
|
350
361
|
"""
|
351
362
|
if input_data.empty:
|
@@ -419,6 +430,10 @@ def train_pipeline_step_train_model(
|
|
419
430
|
Returns:
|
420
431
|
The trained model
|
421
432
|
|
433
|
+
Raises:
|
434
|
+
NotImplementedError: When using invalid model type in the prediction job.
|
435
|
+
InputDataWrongColumnOrderError: When 'load' column is not first and 'horizon' column is not last.
|
436
|
+
|
422
437
|
"""
|
423
438
|
# Test if first column is "load" and last column is "horizon"
|
424
439
|
if train_data.columns[0] != "load" or train_data.columns[-1] != "horizon":
|
openstef/pipeline/utils.py
CHANGED
@@ -27,6 +27,9 @@ def generate_forecast_datetime_range(
|
|
27
27
|
Returns:
|
28
28
|
Start and end datetimes of the forecast range.
|
29
29
|
|
30
|
+
Raises:
|
31
|
+
ValueError: If the target column does not have null values.
|
32
|
+
|
30
33
|
"""
|
31
34
|
# By labeling the True/False values (based on the isnull() statement) as clusters,
|
32
35
|
# we find what True value belongs to what cluster and the amount of True clusters.
|
openstef/tasks/calculate_kpi.py
CHANGED
@@ -106,10 +106,6 @@ def check_kpi_task(
|
|
106
106
|
rMAE=kpis["47.0h"]["rMAE"],
|
107
107
|
retraining_threshold=THRESHOLD_RETRAINING,
|
108
108
|
)
|
109
|
-
function_name = "train_model"
|
110
|
-
|
111
|
-
context.logger.info("Adding tracy job", function=function_name)
|
112
|
-
context.database.ktp_api.add_tracy_job(pj["id"], function=function_name)
|
113
109
|
|
114
110
|
if kpis["47.0h"]["rMAE"] > THRESHOLD_OPTIMIZING:
|
115
111
|
context.logger.warning(
|
@@ -118,9 +114,6 @@ def check_kpi_task(
|
|
118
114
|
rMAE=kpis["47.0h"]["rMAE"],
|
119
115
|
optimizing_threshold=THRESHOLD_OPTIMIZING,
|
120
116
|
)
|
121
|
-
function_name = "optimize_hyperparameters"
|
122
|
-
context.logger.info("Adding tracy job", function=function_name)
|
123
|
-
context.database.ktp_api.add_tracy_job(pj["id"], function=function_name)
|
124
117
|
|
125
118
|
|
126
119
|
def calc_kpi_for_specific_pid(
|
@@ -24,8 +24,8 @@ Example:
|
|
24
24
|
from datetime import datetime, timedelta, timezone
|
25
25
|
from pathlib import Path
|
26
26
|
|
27
|
-
import structlog
|
28
27
|
import pandas as pd
|
28
|
+
import structlog
|
29
29
|
|
30
30
|
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
31
31
|
from openstef.enums import MLModelType
|
@@ -51,6 +51,10 @@ def create_components_forecast_task(
|
|
51
51
|
pj: Prediction job
|
52
52
|
context: Contect object that holds a config manager and a database connection
|
53
53
|
|
54
|
+
Raises:
|
55
|
+
ComponentForecastTooShortHorizonError: If the forecast horizon is too short
|
56
|
+
(less than 30 minutes in advance)
|
57
|
+
|
54
58
|
"""
|
55
59
|
logger = structlog.get_logger(__name__)
|
56
60
|
if pj["train_components"] == 0:
|
openstef/tasks/train_model.py
CHANGED
@@ -23,22 +23,20 @@ from datetime import datetime, timedelta
|
|
23
23
|
from pathlib import Path
|
24
24
|
|
25
25
|
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
26
|
-
|
27
26
|
from openstef.enums import MLModelType, PipelineType
|
28
27
|
from openstef.exceptions import (
|
29
|
-
SkipSaveTrainingForecasts,
|
30
28
|
InputDataOngoingZeroFlatlinerError,
|
29
|
+
SkipSaveTrainingForecasts,
|
31
30
|
)
|
31
|
+
from openstef.model.serializer import MLflowSerializer
|
32
32
|
from openstef.pipeline.train_model import (
|
33
|
+
MAXIMUM_MODEL_AGE,
|
33
34
|
train_model_pipeline,
|
34
35
|
train_pipeline_step_load_model,
|
35
|
-
MAXIMUM_MODEL_AGE,
|
36
36
|
)
|
37
37
|
from openstef.tasks.utils.predictionjobloop import PredictionJobLoop
|
38
38
|
from openstef.tasks.utils.taskcontext import TaskContext
|
39
39
|
|
40
|
-
from openstef.model.serializer import MLflowSerializer
|
41
|
-
|
42
40
|
TRAINING_PERIOD_DAYS: int = 120
|
43
41
|
DEFAULT_CHECK_MODEL_AGE: bool = True
|
44
42
|
|
@@ -65,6 +63,10 @@ def train_model_task(
|
|
65
63
|
datetime_start: Start
|
66
64
|
datetime_end: End
|
67
65
|
|
66
|
+
Raises:
|
67
|
+
SkipSaveTrainingForecasts: If old model is better or too young, you don't need to save the traing forcast.
|
68
|
+
InputDataOngoingZeroFlatlinerError: If all recent load measurements are zero.
|
69
|
+
|
68
70
|
"""
|
69
71
|
# Check pipeline types
|
70
72
|
if PipelineType.TRAIN not in pj.pipelines_to_run:
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MPL-2.0
|
4
|
+
import math
|
4
5
|
from datetime import datetime, timedelta
|
5
6
|
from typing import Union
|
6
7
|
|
7
|
-
import math
|
8
8
|
import numpy as np
|
9
9
|
import pandas as pd
|
10
10
|
import structlog
|
11
11
|
|
12
12
|
from openstef.exceptions import InputDataOngoingZeroFlatlinerError
|
13
|
-
from openstef.preprocessing.preprocessing import replace_repeated_values_with_nan
|
14
13
|
from openstef.model.regressors.regressor import OpenstfRegressor
|
14
|
+
from openstef.preprocessing.preprocessing import replace_repeated_values_with_nan
|
15
15
|
|
16
16
|
|
17
17
|
def validate(
|
@@ -37,6 +37,9 @@ def validate(
|
|
37
37
|
Returns:
|
38
38
|
Dataframe where repeated values are set to None
|
39
39
|
|
40
|
+
Raises:
|
41
|
+
InputDataOngoingZeroFlatlinerError: If all recent load measurements are zero.
|
42
|
+
|
40
43
|
"""
|
41
44
|
logger = structlog.get_logger(__name__)
|
42
45
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
openstef/__init__.py,sha256=93UM6m0LLQhO69-mSqLuUy73jgs4W7Iuxfo3Lm8c98g,419
|
2
2
|
openstef/__main__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
3
|
-
openstef/enums.py,sha256=
|
3
|
+
openstef/enums.py,sha256=f3Gw-HlNXeqMZahIAEYSZkPKtKWeNt3tfOJBL45Z2fM,629
|
4
4
|
openstef/exceptions.py,sha256=fVqjyrVMBiSGxcoZ3JfTcgZjIur1cPennZpfwqgc9qY,1992
|
5
5
|
openstef/data/dutch_holidays_2020-2022.csv,sha256=pS-CjE0igYXd-2dG-MlqyvR2fgYgXkbNmgCKyTjmwxs,23704
|
6
6
|
openstef/data/dutch_holidays_2020-2022.csv.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
|
@@ -25,13 +25,13 @@ openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target.z.license,sha256=AxxHu
|
|
25
25
|
openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z,sha256=HFldCZItBFxDkFrtg36RS-zyrHHGKOILXya-_hmluYM,686
|
26
26
|
openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
|
27
27
|
openstef/data_classes/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
28
|
-
openstef/data_classes/data_prep.py,sha256=
|
28
|
+
openstef/data_classes/data_prep.py,sha256=gRSL7UiHvZis8m8z7VoTCZc0Ccffhef5_hmSyApnqK0,3417
|
29
29
|
openstef/data_classes/model_specifications.py,sha256=Uod1W3QzhRqVLb6zvXwxh9wRL3EHCzSvX0oDNd28cFk,1197
|
30
|
-
openstef/data_classes/prediction_job.py,sha256=
|
30
|
+
openstef/data_classes/prediction_job.py,sha256=lORSocNT8wkq4JhPFsDM8A3EDRi2Pyx28IaVroImfEk,5048
|
31
31
|
openstef/data_classes/split_function.py,sha256=ljQIQQu1t1Y_CVWGAy25jrM6wG9odIVVQVimrT1n-1s,3358
|
32
32
|
openstef/feature_engineering/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
33
33
|
openstef/feature_engineering/apply_features.py,sha256=-3fyisOVj9ckIkRe2iYfWutbXSX8iqBkcvt8AYr-gmE,3906
|
34
|
-
openstef/feature_engineering/data_preparation.py,sha256=
|
34
|
+
openstef/feature_engineering/data_preparation.py,sha256=rH0e5W47OfKisnvusI9J74MPKz48mDrAD2P016QUZpo,5399
|
35
35
|
openstef/feature_engineering/feature_adder.py,sha256=aSqDl_gUrB3H2TD3cNvU5JniY_KOb4u4a2A6J7zB2BQ,6835
|
36
36
|
openstef/feature_engineering/feature_applicator.py,sha256=DR7jayrEMlra4BFL1Ps5WV2fxbkQ6VaOTa5RIKM-YNk,7447
|
37
37
|
openstef/feature_engineering/general.py,sha256=igAPyejYN5d09-a_c53C79a0A4cHjvMCa47KC4IfgCo,4072
|
@@ -39,66 +39,65 @@ openstef/feature_engineering/holiday_features.py,sha256=3Ff4Lkm26h8wJVoBplUewt4H
|
|
39
39
|
openstef/feature_engineering/lag_features.py,sha256=Dr6qS8UhdgEHPZZSe-w6ibtjl_lcbcQohhqdZN9fqEU,5652
|
40
40
|
openstef/feature_engineering/weather_features.py,sha256=wy3KFXUIIwSydFJZpiejsJMwURtDpv9l0HBHu-uLAGQ,15561
|
41
41
|
openstef/metrics/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
42
|
-
openstef/metrics/figure.py,sha256=
|
43
|
-
openstef/metrics/metrics.py,sha256=
|
42
|
+
openstef/metrics/figure.py,sha256=KDoezYem9wdS13kUx7M7FOy-4u88Sg3OX1DuhNT6kgQ,9751
|
43
|
+
openstef/metrics/metrics.py,sha256=t2BIqflvmwzfa6UqS5jpAtNvailpDgD0J09bxjvGlMc,13341
|
44
44
|
openstef/metrics/reporter.py,sha256=V6pa4IUOzVcZ8OY632g5KoF8hr2MT2ySexrjZCjnuwY,7668
|
45
45
|
openstef/model/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
46
46
|
openstef/model/basecase.py,sha256=caI6Q-8y0ymlxGK9Js_H3Vh0q6ruNHlGD5RG0_kE5M0,2878
|
47
|
-
openstef/model/confidence_interval_applicator.py,sha256=
|
47
|
+
openstef/model/confidence_interval_applicator.py,sha256=SXUVCnKrhc7lygWqerkBx4eG4tNeLgNEUz-WPqB4Mng,8705
|
48
48
|
openstef/model/fallback.py,sha256=VV9ehgnoMZtWzqKk9H1t8wnERFh5CyC4TvDIuRP_ZDI,2861
|
49
|
-
openstef/model/model_creator.py,sha256
|
49
|
+
openstef/model/model_creator.py,sha256=-AGAxDr9xxyDFQ0rIh0lvzgYUQQJoHPKVYC3q9azZSk,4790
|
50
50
|
openstef/model/objective.py,sha256=eqNBYGfhEVGegOm0PbizowuFImKblRqHgxkp9lgaKQc,13500
|
51
|
-
openstef/model/objective_creator.py,sha256=
|
52
|
-
openstef/model/serializer.py,sha256=
|
51
|
+
openstef/model/objective_creator.py,sha256=Rjd2YF1Ie9Z-au_v4fOuR63IcM69EEeoe_5Hj_Dz8-E,1970
|
52
|
+
openstef/model/serializer.py,sha256=SGhhk-NU-J8khRwDqeBnO3wywS193XrkYRe7WFkfiMU,17009
|
53
53
|
openstef/model/standard_deviation_generator.py,sha256=Od9bzXi2TLb1v8Nz-VhBMZHSopWH6ssaDe8gYLlqO1I,2911
|
54
54
|
openstef/model/metamodels/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
55
55
|
openstef/model/metamodels/grouped_regressor.py,sha256=yMN_a6TnQSyFaqlB_6Nifq-ydpb5hs6w_b97IaBbHj4,8337
|
56
56
|
openstef/model/metamodels/missing_values_handler.py,sha256=veyvYZHhKvlYZxaUpxRQ7XoE033_3Lcg9LrbuKchlOk,5241
|
57
57
|
openstef/model/regressors/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
58
|
-
openstef/model/regressors/arima.py,sha256=
|
58
|
+
openstef/model/regressors/arima.py,sha256=wt7FVykjSvljpl7vjtliq61SiyjQ7KKtw8PF9x0xf04,7587
|
59
59
|
openstef/model/regressors/custom_regressor.py,sha256=Hsmxahc9nfSWD0aEZ6cm4pxW2noQ8B1SujS17_fmxcU,1768
|
60
60
|
openstef/model/regressors/dazls.py,sha256=cCYFewJEv3Fn01wdZpaKNSiYmEwzuED7PQrrWzwyTEg,8084
|
61
61
|
openstef/model/regressors/lgbm.py,sha256=zCdn1euEdSFxYJzH8XqQFFnb6R4JVUnmineKjX_Gy-g,800
|
62
62
|
openstef/model/regressors/linear.py,sha256=uOvZMLGZH_9nXfmS5honCMfyVeyGXP1Cza9A_BdXlVw,3665
|
63
63
|
openstef/model/regressors/regressor.py,sha256=uJcx59AyCPE9f_yPcAQ59h2ZS7eNsDpIHJrladKvHIw,3461
|
64
64
|
openstef/model/regressors/xgb.py,sha256=HggA1U10srzdysjV560BMMX66kfaxCKAnOZB3JyyT_Y,808
|
65
|
-
openstef/model/regressors/xgb_quantile.py,sha256=
|
65
|
+
openstef/model/regressors/xgb_quantile.py,sha256=PzKIxqN_CnEPFmzXACNuzLSmZSHbooTuiJ5ckJ9vh_E,7805
|
66
66
|
openstef/model_selection/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
67
|
-
openstef/model_selection/model_selection.py,sha256=
|
67
|
+
openstef/model_selection/model_selection.py,sha256=R34tJBecZo6IiUwCCRLeBI2ZCX6GP8W7FDBlGFWtmG8,11167
|
68
68
|
openstef/monitoring/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
69
|
-
openstef/monitoring/performance_meter.py,sha256=
|
69
|
+
openstef/monitoring/performance_meter.py,sha256=6aCGjJFXFq-7qwaJyBkF3MLqjgVK6FMFVcO-bcLLUb4,2803
|
70
70
|
openstef/monitoring/teams.py,sha256=fnZScPD55z9yC0q3YavWj40GEZmL7tsSGhWzG_sMPws,6401
|
71
71
|
openstef/pipeline/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
72
|
-
openstef/pipeline/create_basecase_forecast.py,sha256=
|
73
|
-
openstef/pipeline/create_component_forecast.py,sha256=
|
74
|
-
openstef/pipeline/create_forecast.py,sha256=
|
75
|
-
openstef/pipeline/optimize_hyperparameters.py,sha256=
|
76
|
-
openstef/pipeline/train_create_forecast_backtest.py,sha256=
|
77
|
-
openstef/pipeline/train_model.py,sha256=
|
78
|
-
openstef/pipeline/utils.py,sha256=
|
72
|
+
openstef/pipeline/create_basecase_forecast.py,sha256=osrAlPjveM_fK0TEyVaA6rtqdn-jd1dV7fxU5c3-Muo,4414
|
73
|
+
openstef/pipeline/create_component_forecast.py,sha256=qrIfpCNeoHgSddlzG_-XMHfBmSMclGoOkW-jH35ugkk,6254
|
74
|
+
openstef/pipeline/create_forecast.py,sha256=bE1gTSP-HAjFSt-Xdoiy5BxDIo7lYq-Z-gvU7zFrRfw,5350
|
75
|
+
openstef/pipeline/optimize_hyperparameters.py,sha256=dG2GMTwxb5lHBit_xRgVabcC-PHbifccoPgl9nL-1Xk,10836
|
76
|
+
openstef/pipeline/train_create_forecast_backtest.py,sha256=7uNeY8dKtJLha_LkwroyU76oB54R9p3zRlTJAJj4OoI,6048
|
77
|
+
openstef/pipeline/train_model.py,sha256=LWvqANH8fpo8blwQ8Rgc1Z7EXvmZC0vTYwaOvSbr7qM,19496
|
78
|
+
openstef/pipeline/utils.py,sha256=23mB31p19FoGWelLJzxNmqlzGwEr3fCDBEA37V2kpYY,2167
|
79
79
|
openstef/postprocessing/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
80
80
|
openstef/postprocessing/postprocessing.py,sha256=nehd0tDpkdIaWFJggQ-fDizIKdfmqJ3IOGfk0sDnrzk,8409
|
81
81
|
openstef/preprocessing/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
82
82
|
openstef/preprocessing/preprocessing.py,sha256=bM_cSSSb2vGTD79RGzUrI6KoELbzlCyJwc7jqQGNEsE,1454
|
83
83
|
openstef/tasks/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
84
|
-
openstef/tasks/calculate_kpi.py,sha256
|
84
|
+
openstef/tasks/calculate_kpi.py,sha256=-qwZtA5E88t59R53osZegw6-cKkYNrf03EG5bTp1IgE,11589
|
85
85
|
openstef/tasks/create_basecase_forecast.py,sha256=Hk9fDljXvo5TfeS3nWHrerWi7y-lQzoJEaqWbqaxHOs,3852
|
86
|
-
openstef/tasks/create_components_forecast.py,sha256=
|
86
|
+
openstef/tasks/create_components_forecast.py,sha256=X0Vvhm4F3stcq-QSgZsohlrZQ1myAdDwaBLAeIpQ9D4,5660
|
87
87
|
openstef/tasks/create_forecast.py,sha256=FPILsCqt2lT2QIjseXyKjViZG6SVRoGCxoj9tPiozIg,5575
|
88
88
|
openstef/tasks/create_solar_forecast.py,sha256=bTr7NThTF6Yj405qAqRaJmlBUrL7HATqVVzsi9hMdMw,15049
|
89
89
|
openstef/tasks/create_wind_forecast.py,sha256=RhshkmNSyFWx4Y6yQn02GzHjWTREbN5A5GAeWv0JpcE,2907
|
90
90
|
openstef/tasks/optimize_hyperparameters.py,sha256=s-z8YQJF6Lf3DdYgKHEpAdlbFJ3a-0Gj0Ahsqj1DErc,4758
|
91
|
-
openstef/tasks/run_tracy.py,sha256=mWRg5u74iSaUGHRQzIa-2Weyg6ChuW5w3JBL-7MrNBc,5036
|
92
91
|
openstef/tasks/split_forecast.py,sha256=hBRoIlZ_DK4747EtMpY-HVh_tmTdGa65oYOtrjHRUxQ,9118
|
93
|
-
openstef/tasks/train_model.py,sha256
|
92
|
+
openstef/tasks/train_model.py,sha256=3-7QzyOFQ2jK_RHd7ISpFRnn0V9yEHCWQN3O8qLglqc,7475
|
94
93
|
openstef/tasks/utils/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
95
94
|
openstef/tasks/utils/dependencies.py,sha256=Jy9dtV_G7lTEa5Cdy--wvMxJuAb0adb3R0X4QDjVteM,3077
|
96
95
|
openstef/tasks/utils/predictionjobloop.py,sha256=Ysy3zF5lzPMz_asYDKeF5m0qgVT3tCtwSPihqMjnI5Q,9580
|
97
96
|
openstef/tasks/utils/taskcontext.py,sha256=yI6TntOkZcW8JiNVuw4uJIigEBL0_iIrkPklF4ZeCX4,5401
|
98
97
|
openstef/validation/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
99
|
-
openstef/validation/validation.py,sha256=
|
100
|
-
openstef-3.4.
|
101
|
-
openstef-3.4.
|
102
|
-
openstef-3.4.
|
103
|
-
openstef-3.4.
|
104
|
-
openstef-3.4.
|
98
|
+
openstef/validation/validation.py,sha256=F2tMG8T4sxl3-3zVzshgbBd5xVi7ERmKuqfPVAUp9p0,10445
|
99
|
+
openstef-3.4.16.dist-info/LICENSE,sha256=7Pm2fWFFHHUG5lDHed1vl5CjzxObIXQglnYsEdtjo_k,14907
|
100
|
+
openstef-3.4.16.dist-info/METADATA,sha256=tjLeznPeOd1mRLGirVr8ou6G6s-6TrX62BQ3xMKGPJ4,8125
|
101
|
+
openstef-3.4.16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
102
|
+
openstef-3.4.16.dist-info/top_level.txt,sha256=kD0H4PqrQoncZ957FvqwfBxa89kTrun4Z_RAPs_HhLs,9
|
103
|
+
openstef-3.4.16.dist-info/RECORD,,
|
openstef/tasks/run_tracy.py
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MPL-2.0
|
4
|
-
"""Tracy checks the mysql todolist and tries her best to execute the functions with desired inputs.
|
5
|
-
|
6
|
-
This scripts works as follows:
|
7
|
-
1. Checks the mysql table 'todolist' for jobs (which are not already in progress and
|
8
|
-
which are not already failed)
|
9
|
-
2. Set all newly acquired jobs to 'in progress'
|
10
|
-
For each job:
|
11
|
-
3. Convert input arguments to a dict with 'args' and 'kwargs'
|
12
|
-
4. Interpret the given function and arguments
|
13
|
-
5. Execute the job
|
14
|
-
6. Post result to Teams
|
15
|
-
7. Remove job from mysql table
|
16
|
-
If job fails, set in progress to 2
|
17
|
-
All functions that tracy is able to execute need to be imported and defined in the
|
18
|
-
available_functions.
|
19
|
-
|
20
|
-
Example:
|
21
|
-
This module is meant to be called directly from a CRON job.
|
22
|
-
|
23
|
-
Alternatively this code can be run directly by running::
|
24
|
-
$ python run_tracy.py
|
25
|
-
|
26
|
-
"""
|
27
|
-
# sql to create the Tracy jobs table (todolist)
|
28
|
-
|
29
|
-
# CREATE TABLE IF NOT EXISTS `tst_icarus`.`todolist` (
|
30
|
-
# `id` INT NOT NULL AUTO_INCREMENT ,
|
31
|
-
# `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
|
32
|
-
# `function` VARCHAR(200) NOT NULL ,
|
33
|
-
# `args` VARCHAR(200) NOT NULL ,
|
34
|
-
# `inprogress` BOOLEAN NULL DEFAULT NULL ,
|
35
|
-
# PRIMARY KEY (`id`), UNIQUE `id` (`id`))
|
36
|
-
# ENGINE = InnoDB;
|
37
|
-
from pathlib import Path
|
38
|
-
|
39
|
-
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
40
|
-
from openstef.enums import TracyJobResult
|
41
|
-
from openstef.monitoring import teams
|
42
|
-
from openstef.tasks.optimize_hyperparameters import optimize_hyperparameters_task
|
43
|
-
from openstef.tasks.train_model import train_model_task
|
44
|
-
from openstef.tasks.utils.taskcontext import TaskContext
|
45
|
-
|
46
|
-
|
47
|
-
def run_tracy(context: TaskContext) -> None:
|
48
|
-
# Get all Tracy jobs
|
49
|
-
tracy_jobs = context.database.ktp_api.get_all_tracy_jobs(inprogress=0)
|
50
|
-
num_jobs = len(tracy_jobs)
|
51
|
-
|
52
|
-
if num_jobs == 0:
|
53
|
-
context.logger.warning(f"Number of tracy jobs is {num_jobs}, exit task")
|
54
|
-
return
|
55
|
-
|
56
|
-
context.logger.info("Start processing Tracy jobs", num_jobs=num_jobs)
|
57
|
-
|
58
|
-
for i, job in enumerate(tracy_jobs):
|
59
|
-
# get a new logger with bound job
|
60
|
-
logger = context.logger.bind(job=job)
|
61
|
-
logger.info("Process job", job_counter=i, total_jobs=num_jobs)
|
62
|
-
|
63
|
-
# Set all retrieved items of the todolist to inprogress
|
64
|
-
job["inprogress"] = 1
|
65
|
-
context.database.ktp_api.update_tracy_job(job)
|
66
|
-
|
67
|
-
pid = int(job["args"])
|
68
|
-
pj = context.database.get_prediction_job(pid)
|
69
|
-
result, exc = run_tracy_job(job, pj, context)
|
70
|
-
# job processing was succefull
|
71
|
-
if result is TracyJobResult.SUCCESS:
|
72
|
-
logger.info("Succesfully processed Tracy job")
|
73
|
-
# Delete job when succesfull
|
74
|
-
context.database.ktp_api.delete_tracy_job(job)
|
75
|
-
logger.info("Delete Tracy job")
|
76
|
-
|
77
|
-
# job was unknown
|
78
|
-
elif result is TracyJobResult.UNKNOWN:
|
79
|
-
logger.error(f"Unkown Tracy job {job['function']}")
|
80
|
-
|
81
|
-
# job processing failed / raised an exception
|
82
|
-
elif result is TracyJobResult.FAILED:
|
83
|
-
job["inprogress"] = 2
|
84
|
-
context.database.ktp_api.update_tracy_job(job)
|
85
|
-
msg = "Exception occured while processing Tracy job"
|
86
|
-
logger.error(msg, exc_info=exc)
|
87
|
-
teams.post_teams(teams.format_message(title=msg, params=job))
|
88
|
-
|
89
|
-
context.logger.info("Finished processing all Tracy jobs - Tracy out!")
|
90
|
-
|
91
|
-
|
92
|
-
def run_tracy_job(
|
93
|
-
job: dict, pj: PredictionJobDataClass, context: TaskContext
|
94
|
-
) -> TracyJobResult:
|
95
|
-
"""Run tracy job.
|
96
|
-
|
97
|
-
Args:
|
98
|
-
job: Tracy jon
|
99
|
-
pj: Prediction job
|
100
|
-
context: Task context.
|
101
|
-
|
102
|
-
Returns:
|
103
|
-
Result of the Tracy job.
|
104
|
-
|
105
|
-
"""
|
106
|
-
# Try to process Tracy job
|
107
|
-
try:
|
108
|
-
# If train model job (TODO remove old name when jobs are done)
|
109
|
-
if job["function"] in ["train_model", "train_specific_model"]:
|
110
|
-
train_model_task(pj, context, check_old_model_age=False)
|
111
|
-
|
112
|
-
# If optimize hyperparameters job (TODO remove old name when jobs are done)
|
113
|
-
elif job["function"] in [
|
114
|
-
"optimize_hyperparameters",
|
115
|
-
"optimize_hyperparameters_for_specific_pid",
|
116
|
-
]:
|
117
|
-
optimize_hyperparameters_task(pj, context, check_hyper_param_age=False)
|
118
|
-
|
119
|
-
# Else unknown job
|
120
|
-
else:
|
121
|
-
return TracyJobResult.UNKNOWN, None
|
122
|
-
|
123
|
-
# job processing was succesfull
|
124
|
-
return TracyJobResult.SUCCESS, None
|
125
|
-
|
126
|
-
# Processing of Tracy job failed
|
127
|
-
except Exception as e:
|
128
|
-
return TracyJobResult.FAILED, e
|
129
|
-
|
130
|
-
|
131
|
-
def main(config=None, database=None):
|
132
|
-
taskname = Path(__file__).name.replace(".py", "")
|
133
|
-
|
134
|
-
if database is None or config is None:
|
135
|
-
raise RuntimeError(
|
136
|
-
"Please specifiy a config object and/or database connection object. These"
|
137
|
-
" can be found in the openstef-dbc package."
|
138
|
-
)
|
139
|
-
|
140
|
-
with TaskContext(taskname, config, database) as context:
|
141
|
-
run_tracy(context)
|
142
|
-
|
143
|
-
|
144
|
-
if __name__ == "__main__":
|
145
|
-
main()
|
File without changes
|
File without changes
|
File without changes
|