validmind 2.5.25__py3-none-any.whl → 2.6.7__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.
- validmind/__init__.py +8 -17
- validmind/__version__.py +1 -1
- validmind/ai/test_descriptions.py +66 -85
- validmind/ai/test_result_description/context.py +2 -2
- validmind/ai/utils.py +26 -1
- validmind/api_client.py +43 -79
- validmind/client.py +5 -7
- validmind/client_config.py +1 -1
- validmind/datasets/__init__.py +1 -1
- validmind/datasets/classification/customer_churn.py +7 -5
- validmind/datasets/nlp/__init__.py +2 -2
- validmind/errors.py +6 -10
- validmind/html_templates/content_blocks.py +18 -16
- validmind/logging.py +21 -16
- validmind/tests/__init__.py +28 -5
- validmind/tests/__types__.py +186 -170
- validmind/tests/_store.py +7 -21
- validmind/tests/comparison.py +362 -0
- validmind/tests/data_validation/ACFandPACFPlot.py +44 -73
- validmind/tests/data_validation/ADF.py +49 -83
- validmind/tests/data_validation/AutoAR.py +59 -96
- validmind/tests/data_validation/AutoMA.py +59 -96
- validmind/tests/data_validation/AutoStationarity.py +66 -114
- validmind/tests/data_validation/ClassImbalance.py +48 -117
- validmind/tests/data_validation/DatasetDescription.py +180 -209
- validmind/tests/data_validation/DatasetSplit.py +50 -75
- validmind/tests/data_validation/DescriptiveStatistics.py +59 -85
- validmind/tests/data_validation/{DFGLSArch.py → DickeyFullerGLS.py} +44 -76
- validmind/tests/data_validation/Duplicates.py +21 -90
- validmind/tests/data_validation/EngleGrangerCoint.py +53 -75
- validmind/tests/data_validation/HighCardinality.py +32 -80
- validmind/tests/data_validation/HighPearsonCorrelation.py +29 -97
- validmind/tests/data_validation/IQROutliersBarPlot.py +63 -94
- validmind/tests/data_validation/IQROutliersTable.py +40 -80
- validmind/tests/data_validation/IsolationForestOutliers.py +41 -63
- validmind/tests/data_validation/KPSS.py +33 -81
- validmind/tests/data_validation/LaggedCorrelationHeatmap.py +47 -95
- validmind/tests/data_validation/MissingValues.py +17 -58
- validmind/tests/data_validation/MissingValuesBarPlot.py +61 -87
- validmind/tests/data_validation/PhillipsPerronArch.py +56 -79
- validmind/tests/data_validation/RollingStatsPlot.py +50 -81
- validmind/tests/data_validation/SeasonalDecompose.py +102 -184
- validmind/tests/data_validation/Skewness.py +27 -64
- validmind/tests/data_validation/SpreadPlot.py +34 -57
- validmind/tests/data_validation/TabularCategoricalBarPlots.py +46 -65
- validmind/tests/data_validation/TabularDateTimeHistograms.py +23 -45
- validmind/tests/data_validation/TabularNumericalHistograms.py +27 -46
- validmind/tests/data_validation/TargetRateBarPlots.py +54 -93
- validmind/tests/data_validation/TimeSeriesFrequency.py +48 -133
- validmind/tests/data_validation/TimeSeriesHistogram.py +24 -3
- validmind/tests/data_validation/TimeSeriesLinePlot.py +29 -47
- validmind/tests/data_validation/TimeSeriesMissingValues.py +59 -135
- validmind/tests/data_validation/TimeSeriesOutliers.py +54 -171
- validmind/tests/data_validation/TooManyZeroValues.py +21 -70
- validmind/tests/data_validation/UniqueRows.py +23 -62
- validmind/tests/data_validation/WOEBinPlots.py +83 -109
- validmind/tests/data_validation/WOEBinTable.py +28 -69
- validmind/tests/data_validation/ZivotAndrewsArch.py +33 -75
- validmind/tests/data_validation/nlp/CommonWords.py +49 -57
- validmind/tests/data_validation/nlp/Hashtags.py +27 -49
- validmind/tests/data_validation/nlp/LanguageDetection.py +7 -13
- validmind/tests/data_validation/nlp/Mentions.py +32 -63
- validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +89 -14
- validmind/tests/data_validation/nlp/Punctuations.py +63 -47
- validmind/tests/data_validation/nlp/Sentiment.py +4 -0
- validmind/tests/data_validation/nlp/StopWords.py +62 -91
- validmind/tests/data_validation/nlp/TextDescription.py +116 -159
- validmind/tests/data_validation/nlp/Toxicity.py +12 -4
- validmind/tests/decorator.py +33 -242
- validmind/tests/load.py +212 -153
- validmind/tests/model_validation/BertScore.py +13 -7
- validmind/tests/model_validation/BleuScore.py +4 -0
- validmind/tests/model_validation/ClusterSizeDistribution.py +24 -47
- validmind/tests/model_validation/ContextualRecall.py +3 -0
- validmind/tests/model_validation/FeaturesAUC.py +43 -74
- validmind/tests/model_validation/MeteorScore.py +3 -0
- validmind/tests/model_validation/RegardScore.py +5 -1
- validmind/tests/model_validation/RegressionResidualsPlot.py +54 -75
- validmind/tests/model_validation/embeddings/ClusterDistribution.py +10 -33
- validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +11 -29
- validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +19 -31
- validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +40 -49
- validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +29 -15
- validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +25 -11
- validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +28 -13
- validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +67 -38
- validmind/tests/model_validation/embeddings/utils.py +53 -0
- validmind/tests/model_validation/ragas/AnswerCorrectness.py +37 -32
- validmind/tests/model_validation/ragas/{AspectCritique.py → AspectCritic.py} +33 -27
- validmind/tests/model_validation/ragas/ContextEntityRecall.py +44 -41
- validmind/tests/model_validation/ragas/ContextPrecision.py +40 -35
- validmind/tests/model_validation/ragas/ContextPrecisionWithoutReference.py +133 -0
- validmind/tests/model_validation/ragas/ContextRecall.py +40 -35
- validmind/tests/model_validation/ragas/Faithfulness.py +42 -30
- validmind/tests/model_validation/ragas/NoiseSensitivity.py +59 -35
- validmind/tests/model_validation/ragas/{AnswerRelevance.py → ResponseRelevancy.py} +52 -41
- validmind/tests/model_validation/ragas/{AnswerSimilarity.py → SemanticSimilarity.py} +39 -34
- validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +13 -16
- validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +13 -16
- validmind/tests/model_validation/sklearn/ClassifierPerformance.py +51 -89
- validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +31 -61
- validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +118 -83
- validmind/tests/model_validation/sklearn/CompletenessScore.py +13 -16
- validmind/tests/model_validation/sklearn/ConfusionMatrix.py +62 -94
- validmind/tests/model_validation/sklearn/FeatureImportance.py +7 -8
- validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +12 -15
- validmind/tests/model_validation/sklearn/HomogeneityScore.py +12 -15
- validmind/tests/model_validation/sklearn/HyperParametersTuning.py +23 -53
- validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +60 -74
- validmind/tests/model_validation/sklearn/MinimumAccuracy.py +16 -84
- validmind/tests/model_validation/sklearn/MinimumF1Score.py +22 -72
- validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +29 -78
- validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +52 -82
- validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +51 -145
- validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +60 -78
- validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +130 -172
- validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +26 -55
- validmind/tests/model_validation/sklearn/ROCCurve.py +43 -77
- validmind/tests/model_validation/sklearn/RegressionPerformance.py +41 -94
- validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +47 -136
- validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +164 -208
- validmind/tests/model_validation/sklearn/SilhouettePlot.py +54 -99
- validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +50 -124
- validmind/tests/model_validation/sklearn/VMeasure.py +12 -15
- validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +225 -281
- validmind/tests/model_validation/statsmodels/AutoARIMA.py +40 -45
- validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +22 -47
- validmind/tests/model_validation/statsmodels/Lilliefors.py +17 -28
- validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +37 -81
- validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +37 -105
- validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +62 -166
- validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +57 -119
- validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +20 -57
- validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +47 -80
- validmind/tests/ongoing_monitoring/PredictionCorrelation.py +2 -0
- validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +4 -2
- validmind/tests/output.py +120 -0
- validmind/tests/prompt_validation/Bias.py +55 -98
- validmind/tests/prompt_validation/Clarity.py +56 -99
- validmind/tests/prompt_validation/Conciseness.py +63 -101
- validmind/tests/prompt_validation/Delimitation.py +48 -89
- validmind/tests/prompt_validation/NegativeInstruction.py +62 -96
- validmind/tests/prompt_validation/Robustness.py +80 -121
- validmind/tests/prompt_validation/Specificity.py +61 -95
- validmind/tests/prompt_validation/ai_powered_test.py +2 -2
- validmind/tests/run.py +314 -496
- validmind/tests/test_providers.py +109 -79
- validmind/tests/utils.py +91 -0
- validmind/unit_metrics/__init__.py +16 -155
- validmind/unit_metrics/classification/F1.py +1 -0
- validmind/unit_metrics/classification/Precision.py +1 -0
- validmind/unit_metrics/classification/ROC_AUC.py +1 -0
- validmind/unit_metrics/classification/Recall.py +1 -0
- validmind/unit_metrics/regression/AdjustedRSquaredScore.py +1 -0
- validmind/unit_metrics/regression/GiniCoefficient.py +1 -0
- validmind/unit_metrics/regression/HuberLoss.py +1 -0
- validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +1 -0
- validmind/unit_metrics/regression/MeanAbsoluteError.py +1 -0
- validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +1 -0
- validmind/unit_metrics/regression/MeanBiasDeviation.py +1 -0
- validmind/unit_metrics/regression/MeanSquaredError.py +1 -0
- validmind/unit_metrics/regression/QuantileLoss.py +1 -0
- validmind/unit_metrics/regression/RSquaredScore.py +2 -1
- validmind/unit_metrics/regression/RootMeanSquaredError.py +1 -0
- validmind/utils.py +66 -17
- validmind/vm_models/__init__.py +2 -17
- validmind/vm_models/dataset/dataset.py +31 -4
- validmind/vm_models/figure.py +7 -37
- validmind/vm_models/model.py +3 -0
- validmind/vm_models/result/__init__.py +7 -0
- validmind/vm_models/result/result.jinja +21 -0
- validmind/vm_models/result/result.py +337 -0
- validmind/vm_models/result/utils.py +160 -0
- validmind/vm_models/test_suite/runner.py +16 -54
- validmind/vm_models/test_suite/summary.py +3 -3
- validmind/vm_models/test_suite/test.py +43 -77
- validmind/vm_models/test_suite/test_suite.py +8 -40
- validmind-2.6.7.dist-info/METADATA +137 -0
- {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/RECORD +182 -189
- validmind/tests/data_validation/AutoSeasonality.py +0 -190
- validmind/tests/metadata.py +0 -59
- validmind/tests/model_validation/embeddings/StabilityAnalysis.py +0 -176
- validmind/tests/model_validation/ragas/ContextUtilization.py +0 -161
- validmind/tests/model_validation/sklearn/ClusterPerformance.py +0 -80
- validmind/unit_metrics/composite.py +0 -238
- validmind/vm_models/test/metric.py +0 -98
- validmind/vm_models/test/metric_result.py +0 -61
- validmind/vm_models/test/output_template.py +0 -55
- validmind/vm_models/test/result_summary.py +0 -76
- validmind/vm_models/test/result_wrapper.py +0 -488
- validmind/vm_models/test/test.py +0 -103
- validmind/vm_models/test/threshold_test.py +0 -106
- validmind/vm_models/test/threshold_test_result.py +0 -75
- validmind/vm_models/test_context.py +0 -259
- validmind-2.5.25.dist-info/METADATA +0 -118
- {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/LICENSE +0 -0
- {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/WHEEL +0 -0
- {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/entry_points.txt +0 -0
validmind/client.py
CHANGED
@@ -27,7 +27,7 @@ from .template import get_template_test_suite
|
|
27
27
|
from .template import preview_template as _preview_template
|
28
28
|
from .test_suites import get_by_id as get_test_suite_by_id
|
29
29
|
from .utils import get_dataset_info, get_model_info
|
30
|
-
from .vm_models import
|
30
|
+
from .vm_models import TestSuite, TestSuiteRunner
|
31
31
|
from .vm_models.dataset import DataFrameDataset, PolarsDataset, TorchDataset, VMDataset
|
32
32
|
from .vm_models.model import (
|
33
33
|
ModelAttributes,
|
@@ -100,7 +100,6 @@ def init_dataset(
|
|
100
100
|
|
101
101
|
# Instantiate supported dataset types here
|
102
102
|
if isinstance(dataset, pd.DataFrame):
|
103
|
-
logger.info("Pandas dataset detected. Initializing VM Dataset instance...")
|
104
103
|
vm_dataset = DataFrameDataset(
|
105
104
|
input_id=input_id,
|
106
105
|
raw_dataset=dataset,
|
@@ -113,7 +112,6 @@ def init_dataset(
|
|
113
112
|
date_time_index=date_time_index,
|
114
113
|
)
|
115
114
|
elif isinstance(dataset, pl.DataFrame):
|
116
|
-
logger.info("Polars dataset detected. Initializing VM Dataset instance...")
|
117
115
|
vm_dataset = PolarsDataset(
|
118
116
|
input_id=input_id,
|
119
117
|
raw_dataset=dataset,
|
@@ -126,7 +124,6 @@ def init_dataset(
|
|
126
124
|
date_time_index=date_time_index,
|
127
125
|
)
|
128
126
|
elif dataset_class == "ndarray":
|
129
|
-
logger.info("Numpy ndarray detected. Initializing VM Dataset instance...")
|
130
127
|
vm_dataset = VMDataset(
|
131
128
|
input_id=input_id,
|
132
129
|
raw_dataset=dataset,
|
@@ -143,7 +140,6 @@ def init_dataset(
|
|
143
140
|
date_time_index=date_time_index,
|
144
141
|
)
|
145
142
|
elif dataset_class == "TensorDataset":
|
146
|
-
logger.info("Torch TensorDataset detected. Initializing VM Dataset instance...")
|
147
143
|
vm_dataset = TorchDataset(
|
148
144
|
input_id=input_id,
|
149
145
|
raw_dataset=dataset,
|
@@ -277,6 +273,7 @@ def init_model(
|
|
277
273
|
|
278
274
|
def init_r_model(
|
279
275
|
model_path: str,
|
276
|
+
input_id: str = "model",
|
280
277
|
) -> VMModel:
|
281
278
|
"""
|
282
279
|
Initializes a VM Model for an R model
|
@@ -325,6 +322,7 @@ def init_r_model(
|
|
325
322
|
vm_model = RModel(
|
326
323
|
r=r,
|
327
324
|
model=model,
|
325
|
+
input_id=input_id,
|
328
326
|
)
|
329
327
|
|
330
328
|
return vm_model
|
@@ -409,7 +407,7 @@ def run_test_suite(
|
|
409
407
|
|
410
408
|
TestSuiteRunner(
|
411
409
|
suite=suite,
|
412
|
-
|
410
|
+
inputs={**kwargs, **(inputs or {})},
|
413
411
|
config=config or {},
|
414
412
|
).run(fail_fast=fail_fast, send=send)
|
415
413
|
|
@@ -512,7 +510,7 @@ def _run_documentation_section(
|
|
512
510
|
|
513
511
|
TestSuiteRunner(
|
514
512
|
suite=test_suite,
|
515
|
-
|
513
|
+
inputs={**kwargs, **(inputs or {})},
|
516
514
|
config=config,
|
517
515
|
).run(send=send, fail_fast=fail_fast)
|
518
516
|
|
validmind/client_config.py
CHANGED
validmind/datasets/__init__.py
CHANGED
@@ -86,16 +86,18 @@ def get_demo_test_config(test_suite=None):
|
|
86
86
|
for _, test_config in default_config.items():
|
87
87
|
if "model" in test_config["inputs"]:
|
88
88
|
test_config["inputs"]["model"] = "model"
|
89
|
+
if "models" in test_config["inputs"]:
|
90
|
+
test_config["inputs"]["models"] = ["model"]
|
91
|
+
if "dataset" in test_config["inputs"]:
|
92
|
+
if "model" in test_config["inputs"] or "models" in test_config["inputs"]:
|
93
|
+
test_config["inputs"]["dataset"] = "test_dataset"
|
94
|
+
else:
|
95
|
+
test_config["inputs"]["dataset"] = "raw_dataset"
|
89
96
|
if "datasets" in test_config["inputs"]:
|
90
97
|
test_config["inputs"]["datasets"] = [
|
91
98
|
"train_dataset",
|
92
99
|
"test_dataset",
|
93
100
|
]
|
94
|
-
if "dataset" in test_config["inputs"]:
|
95
|
-
if "model" in test_config["inputs"]:
|
96
|
-
test_config["inputs"]["dataset"] = "test_dataset"
|
97
|
-
else:
|
98
|
-
test_config["inputs"]["dataset"] = "raw_dataset"
|
99
101
|
|
100
102
|
# ClassifierPerformance is a special case since we run an in-sample and out-of-sample
|
101
103
|
# test with two different datasets: train_dataset and test_dataset
|
@@ -3,10 +3,10 @@
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
|
4
4
|
|
5
5
|
"""
|
6
|
-
Example datasets that can be used with the
|
6
|
+
Example datasets that can be used with the ValidMind Library.
|
7
7
|
"""
|
8
8
|
|
9
9
|
__all__ = [
|
10
10
|
"cnn_dailymail",
|
11
|
-
"
|
11
|
+
"twitter_covid_19",
|
12
12
|
]
|
validmind/errors.py
CHANGED
@@ -3,13 +3,15 @@
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
|
4
4
|
|
5
5
|
"""
|
6
|
-
This module contains all the custom errors that are used in the
|
6
|
+
This module contains all the custom errors that are used in the ValidMind Library.
|
7
7
|
|
8
8
|
The following base errors are defined for others:
|
9
9
|
- BaseError
|
10
10
|
- APIRequestError
|
11
11
|
"""
|
12
|
+
|
12
13
|
import json
|
14
|
+
from typing import Optional
|
13
15
|
|
14
16
|
|
15
17
|
class BaseError(Exception):
|
@@ -79,14 +81,6 @@ class InvalidContentIdPrefixError(APIRequestError):
|
|
79
81
|
"""
|
80
82
|
|
81
83
|
|
82
|
-
class InvalidFigureForObjectError(BaseError):
|
83
|
-
"""
|
84
|
-
When a figure was constructed with an unsupported for_object value.
|
85
|
-
"""
|
86
|
-
|
87
|
-
pass
|
88
|
-
|
89
|
-
|
90
84
|
class InvalidMetricResultsError(APIRequestError):
|
91
85
|
"""
|
92
86
|
When an invalid metric results object is sent to the API.
|
@@ -164,7 +158,9 @@ class LoadTestError(BaseError):
|
|
164
158
|
Exception raised when an error occurs while loading a test
|
165
159
|
"""
|
166
160
|
|
167
|
-
|
161
|
+
def __init__(self, message: str, original_error: Optional[Exception] = None):
|
162
|
+
super().__init__(message)
|
163
|
+
self.original_error = original_error
|
168
164
|
|
169
165
|
|
170
166
|
class MismatchingClassLabelsError(BaseError):
|
@@ -14,7 +14,24 @@ non_test_content_block_html = """
|
|
14
14
|
test_content_block_html = """
|
15
15
|
<div>
|
16
16
|
<h2>{title}</h2>
|
17
|
-
|
17
|
+
<div style="border: 1px solid #ddd; border-radius: 4px; padding: 10px; margin: 10px 0;">
|
18
|
+
{description}
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<h4 class="vm_required_context">
|
23
|
+
Required Inputs: <span style="font-size: 13px"><i>{required_inputs}</i></span>
|
24
|
+
</h4>
|
25
|
+
|
26
|
+
<div style="display: {table_display};">
|
27
|
+
<h4>Parameters:</h4>
|
28
|
+
<table class="vm_params_table" style="display: {table_display};">
|
29
|
+
<tr>
|
30
|
+
<th>Parameter</th>
|
31
|
+
<th>Default Value</th>
|
32
|
+
</tr>
|
33
|
+
{params_table}
|
34
|
+
</table>
|
18
35
|
</div>
|
19
36
|
|
20
37
|
<div class="unset">
|
@@ -44,21 +61,6 @@ result = vm.tests.run_test(
|
|
44
61
|
# To see the result of the test, ensure that you have called `vm.init()` and then run:
|
45
62
|
result.log()</code>
|
46
63
|
</pre>
|
47
|
-
|
48
|
-
<h4 class="vm_required_context">
|
49
|
-
Required Inputs: <span style="font-size: 13px"><i>{required_inputs}</i></span>
|
50
|
-
</h4>
|
51
|
-
|
52
|
-
<div style="display: {table_display};">
|
53
|
-
<h4>Parameters:</h4>
|
54
|
-
<table class="vm_params_table" style="display: {table_display};">
|
55
|
-
<tr>
|
56
|
-
<th>Parameter</th>
|
57
|
-
<th>Default Value</th>
|
58
|
-
</tr>
|
59
|
-
{params_table}
|
60
|
-
</table>
|
61
|
-
</div>
|
62
64
|
</div>
|
63
65
|
</div>
|
64
66
|
|
validmind/logging.py
CHANGED
@@ -88,11 +88,10 @@ def init_sentry(server_config):
|
|
88
88
|
logger.debug(f"Sentry error: {str(e)}")
|
89
89
|
|
90
90
|
|
91
|
-
def log_performance(
|
91
|
+
def log_performance(name=None, logger=None, force=False):
|
92
92
|
"""Decorator to log the time it takes to run a function
|
93
93
|
|
94
94
|
Args:
|
95
|
-
func (function): The function to decorate
|
96
95
|
name (str, optional): The name of the function. Defaults to None.
|
97
96
|
logger (logging.Logger, optional): The logger to use. Defaults to None.
|
98
97
|
force (bool, optional): Whether to force logging even if env var is off
|
@@ -100,26 +99,32 @@ def log_performance(func, name=None, logger=None, force=False):
|
|
100
99
|
Returns:
|
101
100
|
function: The decorated function
|
102
101
|
"""
|
103
|
-
# check if log level is set to debug
|
104
|
-
if _get_log_level() != logging.DEBUG and not force:
|
105
|
-
return func
|
106
102
|
|
107
|
-
|
108
|
-
|
103
|
+
def decorator(func):
|
104
|
+
# check if log level is set to debug
|
105
|
+
if _get_log_level() != logging.DEBUG and not force:
|
106
|
+
return func
|
109
107
|
|
110
|
-
|
111
|
-
|
108
|
+
nonlocal logger
|
109
|
+
if logger is None:
|
110
|
+
logger = get_logger()
|
112
111
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
time2 = time.perf_counter()
|
112
|
+
nonlocal name
|
113
|
+
if name is None:
|
114
|
+
name = func.__name__
|
117
115
|
|
118
|
-
|
116
|
+
def wrapped(*args, **kwargs):
|
117
|
+
time1 = time.perf_counter()
|
118
|
+
return_val = func(*args, **kwargs)
|
119
|
+
time2 = time.perf_counter()
|
119
120
|
|
120
|
-
|
121
|
+
logger.debug("%s function took %0.3f ms" % (name, (time2 - time1) * 1000.0))
|
121
122
|
|
122
|
-
|
123
|
+
return return_val
|
124
|
+
|
125
|
+
return wrapped
|
126
|
+
|
127
|
+
return decorator
|
123
128
|
|
124
129
|
|
125
130
|
async def log_performance_async(func, name=None, logger=None, force=False):
|
validmind/tests/__init__.py
CHANGED
@@ -6,15 +6,39 @@
|
|
6
6
|
|
7
7
|
from ..errors import LoadTestError
|
8
8
|
from ..logging import get_logger
|
9
|
-
from .
|
10
|
-
from .
|
11
|
-
from .
|
9
|
+
from ._store import test_provider_store
|
10
|
+
from .decorator import tags, tasks, test
|
11
|
+
from .load import (
|
12
|
+
describe_test,
|
13
|
+
list_tags,
|
14
|
+
list_tasks,
|
15
|
+
list_tasks_and_tags,
|
16
|
+
list_tests,
|
17
|
+
load_test,
|
18
|
+
)
|
12
19
|
from .run import run_test
|
13
|
-
from .test_providers import LocalTestProvider, TestProvider
|
20
|
+
from .test_providers import LocalTestProvider, TestProvider
|
14
21
|
|
15
22
|
logger = get_logger(__name__)
|
16
23
|
|
17
24
|
|
25
|
+
# public-facing function for registering test providers
|
26
|
+
def register_test_provider(namespace: str, test_provider: TestProvider) -> None:
|
27
|
+
"""Register an external test provider
|
28
|
+
|
29
|
+
Args:
|
30
|
+
namespace (str): The namespace of the test provider
|
31
|
+
test_provider (TestProvider): The test provider
|
32
|
+
"""
|
33
|
+
if not hasattr(test_provider, "list_tests"):
|
34
|
+
raise ValueError("test_provider must implement `list_tests` method")
|
35
|
+
|
36
|
+
if not hasattr(test_provider, "load_test"):
|
37
|
+
raise ValueError("test_provider must implement `load_test` method")
|
38
|
+
|
39
|
+
test_provider_store.register_test_provider(namespace, test_provider)
|
40
|
+
|
41
|
+
|
18
42
|
__all__ = [
|
19
43
|
"data_validation",
|
20
44
|
"model_validation",
|
@@ -33,7 +57,6 @@ __all__ = [
|
|
33
57
|
"list_tasks_and_tags",
|
34
58
|
# Decorators for functional metrics
|
35
59
|
"test",
|
36
|
-
"metric", # DEPRECATED
|
37
60
|
"tags",
|
38
61
|
"tasks",
|
39
62
|
]
|