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.
Files changed (198) hide show
  1. validmind/__init__.py +8 -17
  2. validmind/__version__.py +1 -1
  3. validmind/ai/test_descriptions.py +66 -85
  4. validmind/ai/test_result_description/context.py +2 -2
  5. validmind/ai/utils.py +26 -1
  6. validmind/api_client.py +43 -79
  7. validmind/client.py +5 -7
  8. validmind/client_config.py +1 -1
  9. validmind/datasets/__init__.py +1 -1
  10. validmind/datasets/classification/customer_churn.py +7 -5
  11. validmind/datasets/nlp/__init__.py +2 -2
  12. validmind/errors.py +6 -10
  13. validmind/html_templates/content_blocks.py +18 -16
  14. validmind/logging.py +21 -16
  15. validmind/tests/__init__.py +28 -5
  16. validmind/tests/__types__.py +186 -170
  17. validmind/tests/_store.py +7 -21
  18. validmind/tests/comparison.py +362 -0
  19. validmind/tests/data_validation/ACFandPACFPlot.py +44 -73
  20. validmind/tests/data_validation/ADF.py +49 -83
  21. validmind/tests/data_validation/AutoAR.py +59 -96
  22. validmind/tests/data_validation/AutoMA.py +59 -96
  23. validmind/tests/data_validation/AutoStationarity.py +66 -114
  24. validmind/tests/data_validation/ClassImbalance.py +48 -117
  25. validmind/tests/data_validation/DatasetDescription.py +180 -209
  26. validmind/tests/data_validation/DatasetSplit.py +50 -75
  27. validmind/tests/data_validation/DescriptiveStatistics.py +59 -85
  28. validmind/tests/data_validation/{DFGLSArch.py → DickeyFullerGLS.py} +44 -76
  29. validmind/tests/data_validation/Duplicates.py +21 -90
  30. validmind/tests/data_validation/EngleGrangerCoint.py +53 -75
  31. validmind/tests/data_validation/HighCardinality.py +32 -80
  32. validmind/tests/data_validation/HighPearsonCorrelation.py +29 -97
  33. validmind/tests/data_validation/IQROutliersBarPlot.py +63 -94
  34. validmind/tests/data_validation/IQROutliersTable.py +40 -80
  35. validmind/tests/data_validation/IsolationForestOutliers.py +41 -63
  36. validmind/tests/data_validation/KPSS.py +33 -81
  37. validmind/tests/data_validation/LaggedCorrelationHeatmap.py +47 -95
  38. validmind/tests/data_validation/MissingValues.py +17 -58
  39. validmind/tests/data_validation/MissingValuesBarPlot.py +61 -87
  40. validmind/tests/data_validation/PhillipsPerronArch.py +56 -79
  41. validmind/tests/data_validation/RollingStatsPlot.py +50 -81
  42. validmind/tests/data_validation/SeasonalDecompose.py +102 -184
  43. validmind/tests/data_validation/Skewness.py +27 -64
  44. validmind/tests/data_validation/SpreadPlot.py +34 -57
  45. validmind/tests/data_validation/TabularCategoricalBarPlots.py +46 -65
  46. validmind/tests/data_validation/TabularDateTimeHistograms.py +23 -45
  47. validmind/tests/data_validation/TabularNumericalHistograms.py +27 -46
  48. validmind/tests/data_validation/TargetRateBarPlots.py +54 -93
  49. validmind/tests/data_validation/TimeSeriesFrequency.py +48 -133
  50. validmind/tests/data_validation/TimeSeriesHistogram.py +24 -3
  51. validmind/tests/data_validation/TimeSeriesLinePlot.py +29 -47
  52. validmind/tests/data_validation/TimeSeriesMissingValues.py +59 -135
  53. validmind/tests/data_validation/TimeSeriesOutliers.py +54 -171
  54. validmind/tests/data_validation/TooManyZeroValues.py +21 -70
  55. validmind/tests/data_validation/UniqueRows.py +23 -62
  56. validmind/tests/data_validation/WOEBinPlots.py +83 -109
  57. validmind/tests/data_validation/WOEBinTable.py +28 -69
  58. validmind/tests/data_validation/ZivotAndrewsArch.py +33 -75
  59. validmind/tests/data_validation/nlp/CommonWords.py +49 -57
  60. validmind/tests/data_validation/nlp/Hashtags.py +27 -49
  61. validmind/tests/data_validation/nlp/LanguageDetection.py +7 -13
  62. validmind/tests/data_validation/nlp/Mentions.py +32 -63
  63. validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +89 -14
  64. validmind/tests/data_validation/nlp/Punctuations.py +63 -47
  65. validmind/tests/data_validation/nlp/Sentiment.py +4 -0
  66. validmind/tests/data_validation/nlp/StopWords.py +62 -91
  67. validmind/tests/data_validation/nlp/TextDescription.py +116 -159
  68. validmind/tests/data_validation/nlp/Toxicity.py +12 -4
  69. validmind/tests/decorator.py +33 -242
  70. validmind/tests/load.py +212 -153
  71. validmind/tests/model_validation/BertScore.py +13 -7
  72. validmind/tests/model_validation/BleuScore.py +4 -0
  73. validmind/tests/model_validation/ClusterSizeDistribution.py +24 -47
  74. validmind/tests/model_validation/ContextualRecall.py +3 -0
  75. validmind/tests/model_validation/FeaturesAUC.py +43 -74
  76. validmind/tests/model_validation/MeteorScore.py +3 -0
  77. validmind/tests/model_validation/RegardScore.py +5 -1
  78. validmind/tests/model_validation/RegressionResidualsPlot.py +54 -75
  79. validmind/tests/model_validation/embeddings/ClusterDistribution.py +10 -33
  80. validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +11 -29
  81. validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +19 -31
  82. validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +40 -49
  83. validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +29 -15
  84. validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +25 -11
  85. validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +28 -13
  86. validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +67 -38
  87. validmind/tests/model_validation/embeddings/utils.py +53 -0
  88. validmind/tests/model_validation/ragas/AnswerCorrectness.py +37 -32
  89. validmind/tests/model_validation/ragas/{AspectCritique.py → AspectCritic.py} +33 -27
  90. validmind/tests/model_validation/ragas/ContextEntityRecall.py +44 -41
  91. validmind/tests/model_validation/ragas/ContextPrecision.py +40 -35
  92. validmind/tests/model_validation/ragas/ContextPrecisionWithoutReference.py +133 -0
  93. validmind/tests/model_validation/ragas/ContextRecall.py +40 -35
  94. validmind/tests/model_validation/ragas/Faithfulness.py +42 -30
  95. validmind/tests/model_validation/ragas/NoiseSensitivity.py +59 -35
  96. validmind/tests/model_validation/ragas/{AnswerRelevance.py → ResponseRelevancy.py} +52 -41
  97. validmind/tests/model_validation/ragas/{AnswerSimilarity.py → SemanticSimilarity.py} +39 -34
  98. validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +13 -16
  99. validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +13 -16
  100. validmind/tests/model_validation/sklearn/ClassifierPerformance.py +51 -89
  101. validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +31 -61
  102. validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +118 -83
  103. validmind/tests/model_validation/sklearn/CompletenessScore.py +13 -16
  104. validmind/tests/model_validation/sklearn/ConfusionMatrix.py +62 -94
  105. validmind/tests/model_validation/sklearn/FeatureImportance.py +7 -8
  106. validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +12 -15
  107. validmind/tests/model_validation/sklearn/HomogeneityScore.py +12 -15
  108. validmind/tests/model_validation/sklearn/HyperParametersTuning.py +23 -53
  109. validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +60 -74
  110. validmind/tests/model_validation/sklearn/MinimumAccuracy.py +16 -84
  111. validmind/tests/model_validation/sklearn/MinimumF1Score.py +22 -72
  112. validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +29 -78
  113. validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +52 -82
  114. validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +51 -145
  115. validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +60 -78
  116. validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +130 -172
  117. validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +26 -55
  118. validmind/tests/model_validation/sklearn/ROCCurve.py +43 -77
  119. validmind/tests/model_validation/sklearn/RegressionPerformance.py +41 -94
  120. validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +47 -136
  121. validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +164 -208
  122. validmind/tests/model_validation/sklearn/SilhouettePlot.py +54 -99
  123. validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +50 -124
  124. validmind/tests/model_validation/sklearn/VMeasure.py +12 -15
  125. validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +225 -281
  126. validmind/tests/model_validation/statsmodels/AutoARIMA.py +40 -45
  127. validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +22 -47
  128. validmind/tests/model_validation/statsmodels/Lilliefors.py +17 -28
  129. validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +37 -81
  130. validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +37 -105
  131. validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +62 -166
  132. validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +57 -119
  133. validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +20 -57
  134. validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +47 -80
  135. validmind/tests/ongoing_monitoring/PredictionCorrelation.py +2 -0
  136. validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +4 -2
  137. validmind/tests/output.py +120 -0
  138. validmind/tests/prompt_validation/Bias.py +55 -98
  139. validmind/tests/prompt_validation/Clarity.py +56 -99
  140. validmind/tests/prompt_validation/Conciseness.py +63 -101
  141. validmind/tests/prompt_validation/Delimitation.py +48 -89
  142. validmind/tests/prompt_validation/NegativeInstruction.py +62 -96
  143. validmind/tests/prompt_validation/Robustness.py +80 -121
  144. validmind/tests/prompt_validation/Specificity.py +61 -95
  145. validmind/tests/prompt_validation/ai_powered_test.py +2 -2
  146. validmind/tests/run.py +314 -496
  147. validmind/tests/test_providers.py +109 -79
  148. validmind/tests/utils.py +91 -0
  149. validmind/unit_metrics/__init__.py +16 -155
  150. validmind/unit_metrics/classification/F1.py +1 -0
  151. validmind/unit_metrics/classification/Precision.py +1 -0
  152. validmind/unit_metrics/classification/ROC_AUC.py +1 -0
  153. validmind/unit_metrics/classification/Recall.py +1 -0
  154. validmind/unit_metrics/regression/AdjustedRSquaredScore.py +1 -0
  155. validmind/unit_metrics/regression/GiniCoefficient.py +1 -0
  156. validmind/unit_metrics/regression/HuberLoss.py +1 -0
  157. validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +1 -0
  158. validmind/unit_metrics/regression/MeanAbsoluteError.py +1 -0
  159. validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +1 -0
  160. validmind/unit_metrics/regression/MeanBiasDeviation.py +1 -0
  161. validmind/unit_metrics/regression/MeanSquaredError.py +1 -0
  162. validmind/unit_metrics/regression/QuantileLoss.py +1 -0
  163. validmind/unit_metrics/regression/RSquaredScore.py +2 -1
  164. validmind/unit_metrics/regression/RootMeanSquaredError.py +1 -0
  165. validmind/utils.py +66 -17
  166. validmind/vm_models/__init__.py +2 -17
  167. validmind/vm_models/dataset/dataset.py +31 -4
  168. validmind/vm_models/figure.py +7 -37
  169. validmind/vm_models/model.py +3 -0
  170. validmind/vm_models/result/__init__.py +7 -0
  171. validmind/vm_models/result/result.jinja +21 -0
  172. validmind/vm_models/result/result.py +337 -0
  173. validmind/vm_models/result/utils.py +160 -0
  174. validmind/vm_models/test_suite/runner.py +16 -54
  175. validmind/vm_models/test_suite/summary.py +3 -3
  176. validmind/vm_models/test_suite/test.py +43 -77
  177. validmind/vm_models/test_suite/test_suite.py +8 -40
  178. validmind-2.6.7.dist-info/METADATA +137 -0
  179. {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/RECORD +182 -189
  180. validmind/tests/data_validation/AutoSeasonality.py +0 -190
  181. validmind/tests/metadata.py +0 -59
  182. validmind/tests/model_validation/embeddings/StabilityAnalysis.py +0 -176
  183. validmind/tests/model_validation/ragas/ContextUtilization.py +0 -161
  184. validmind/tests/model_validation/sklearn/ClusterPerformance.py +0 -80
  185. validmind/unit_metrics/composite.py +0 -238
  186. validmind/vm_models/test/metric.py +0 -98
  187. validmind/vm_models/test/metric_result.py +0 -61
  188. validmind/vm_models/test/output_template.py +0 -55
  189. validmind/vm_models/test/result_summary.py +0 -76
  190. validmind/vm_models/test/result_wrapper.py +0 -488
  191. validmind/vm_models/test/test.py +0 -103
  192. validmind/vm_models/test/threshold_test.py +0 -106
  193. validmind/vm_models/test/threshold_test_result.py +0 -75
  194. validmind/vm_models/test_context.py +0 -259
  195. validmind-2.5.25.dist-info/METADATA +0 -118
  196. {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/LICENSE +0 -0
  197. {validmind-2.5.25.dist-info → validmind-2.6.7.dist-info}/WHEEL +0 -0
  198. {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 TestInput, TestSuite, TestSuiteRunner
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
- input=TestInput({**kwargs, **(inputs or {})}),
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
- input=TestInput({**kwargs, **(inputs or {})}),
513
+ inputs={**kwargs, **(inputs or {})},
516
514
  config=config,
517
515
  ).run(send=send, fail_fast=fail_fast)
518
516
 
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
4
 
5
5
  """
6
- Central class to track configuration of the library
6
+ Central class to track configuration of the ValidMind Library
7
7
  client against the ValidMind API
8
8
  """
9
9
 
@@ -3,5 +3,5 @@
3
3
  # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
4
 
5
5
  """
6
- Example datasets that can be used with the library.
6
+ Example datasets that can be used with the ValidMind Library.
7
7
  """
@@ -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 library.
6
+ Example datasets that can be used with the ValidMind Library.
7
7
  """
8
8
 
9
9
  __all__ = [
10
10
  "cnn_dailymail",
11
- "twitter_covide_19",
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 library.
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
- pass
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
- {description}
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(func, name=None, logger=None, force=False):
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
- if logger is None:
108
- logger = get_logger()
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
- if name is None:
111
- name = func.__name__
108
+ nonlocal logger
109
+ if logger is None:
110
+ logger = get_logger()
112
111
 
113
- def wrap(*args, **kwargs):
114
- time1 = time.perf_counter()
115
- return_val = func(*args, **kwargs)
116
- time2 = time.perf_counter()
112
+ nonlocal name
113
+ if name is None:
114
+ name = func.__name__
117
115
 
118
- logger.debug("%s function took %0.3f ms" % (name, (time2 - time1) * 1000.0))
116
+ def wrapped(*args, **kwargs):
117
+ time1 = time.perf_counter()
118
+ return_val = func(*args, **kwargs)
119
+ time2 = time.perf_counter()
119
120
 
120
- return return_val
121
+ logger.debug("%s function took %0.3f ms" % (name, (time2 - time1) * 1000.0))
121
122
 
122
- return wrap
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):
@@ -6,15 +6,39 @@
6
6
 
7
7
  from ..errors import LoadTestError
8
8
  from ..logging import get_logger
9
- from .decorator import metric, tags, tasks, test
10
- from .load import describe_test, list_tests, load_test
11
- from .metadata import list_tags, list_tasks, list_tasks_and_tags
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, register_test_provider
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
  ]