fiddler-client 3.7.1__tar.gz → 3.8.1__tar.gz

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 (119) hide show
  1. {fiddler_client-3.7.1/fiddler_client.egg-info → fiddler-client-3.8.1}/PKG-INFO +6 -13
  2. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/PUBLIC.md +1 -1
  3. fiddler-client-3.8.1/fiddler/VERSION +1 -0
  4. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/__init__.py +2 -0
  5. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/alert_rule.py +9 -0
  6. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/alert_record.py +6 -0
  7. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/alert_rule.py +35 -2
  8. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/project.py +5 -2
  9. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/alert_record.py +3 -0
  10. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/alert_rule.py +10 -2
  11. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_alert_record.py +7 -1
  12. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_alert_rule.py +175 -22
  13. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_project.py +2 -2
  14. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/constants.py +2 -1
  15. {fiddler_client-3.7.1 → fiddler-client-3.8.1/fiddler_client.egg-info}/PKG-INFO +6 -13
  16. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler_client.egg-info/requires.txt +7 -7
  17. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/setup.py +1 -1
  18. fiddler_client-3.7.1/fiddler/VERSION +0 -1
  19. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/LICENSE.txt +0 -0
  20. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/MANIFEST.in +0 -0
  21. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/README.md +0 -0
  22. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/configs.py +0 -0
  23. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/connection.py +0 -0
  24. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/__init__.py +0 -0
  25. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/baseline.py +0 -0
  26. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/common.py +0 -0
  27. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/dataset.py +0 -0
  28. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/events.py +0 -0
  29. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/job.py +0 -0
  30. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/model.py +0 -0
  31. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/model_deployment.py +0 -0
  32. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/constants/xai.py +0 -0
  33. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/decorators.py +0 -0
  34. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/__init__.py +0 -0
  35. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/base.py +0 -0
  36. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/baseline.py +0 -0
  37. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/custom_expression.py +0 -0
  38. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/dataset.py +0 -0
  39. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/events.py +0 -0
  40. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/file.py +0 -0
  41. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/job.py +0 -0
  42. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/model.py +0 -0
  43. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/model_artifact.py +0 -0
  44. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/model_deployment.py +0 -0
  45. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/organization.py +0 -0
  46. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/surrogate.py +0 -0
  47. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/user.py +0 -0
  48. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/webhook.py +0 -0
  49. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/entities/xai.py +0 -0
  50. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/exceptions.py +0 -0
  51. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/libs/__init__.py +0 -0
  52. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/libs/aws.py +0 -0
  53. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/libs/http_client.py +0 -0
  54. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/libs/json_encoder.py +0 -0
  55. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/libs/semver.py +0 -0
  56. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/packtools/__init__.py +0 -0
  57. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/packtools/gem.py +0 -0
  58. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/packtools/keras_ig_helpers.py +0 -0
  59. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/packtools/project_attributions_helpers.py +0 -0
  60. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/packtools/template_model.py +0 -0
  61. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/__init__.py +0 -0
  62. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/base.py +0 -0
  63. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/baseline.py +0 -0
  64. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/custom_expression.py +0 -0
  65. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/custom_features.py +0 -0
  66. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/dataset.py +0 -0
  67. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/events.py +0 -0
  68. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/file.py +0 -0
  69. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/filter_query.py +0 -0
  70. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/job.py +0 -0
  71. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/model.py +0 -0
  72. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/model_deployment.py +0 -0
  73. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/model_schema.py +0 -0
  74. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/model_spec.py +0 -0
  75. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/model_task_params.py +0 -0
  76. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/organization.py +0 -0
  77. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/project.py +0 -0
  78. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/response.py +0 -0
  79. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/server_info.py +0 -0
  80. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/user.py +0 -0
  81. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/webhook.py +0 -0
  82. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/xai.py +0 -0
  83. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/schemas/xai_params.py +0 -0
  84. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/__init__.py +0 -0
  85. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/__init__.py +0 -0
  86. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_baseline.py +0 -0
  87. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_custom_metric.py +0 -0
  88. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_dataset.py +0 -0
  89. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_events.py +0 -0
  90. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_files.py +0 -0
  91. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_generate_model.py +0 -0
  92. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_job.py +0 -0
  93. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_mixin.py +0 -0
  94. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_model.py +0 -0
  95. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_model_artifact.py +0 -0
  96. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_model_deployment.py +0 -0
  97. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  98. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_segment.py +0 -0
  99. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_webhook.py +0 -0
  100. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/apis/test_xai.py +0 -0
  101. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/conftest.py +0 -0
  102. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/test_connection.py +0 -0
  103. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/test_json_encoder.py +0 -0
  104. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/test_logger.py +0 -0
  105. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/test_sagemaker_auth.py +0 -0
  106. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/test_utils.py +0 -0
  107. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/tests/utils.py +0 -0
  108. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/__init__.py +0 -0
  109. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/decorators.py +0 -0
  110. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/helpers.py +0 -0
  111. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/logger.py +0 -0
  112. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/model_generator.py +0 -0
  113. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/validations.py +0 -0
  114. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/utils/version.py +0 -0
  115. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler/version.py +0 -0
  116. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler_client.egg-info/SOURCES.txt +0 -0
  117. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler_client.egg-info/dependency_links.txt +0 -0
  118. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/fiddler_client.egg-info/top_level.txt +0 -0
  119. {fiddler_client-3.7.1 → fiddler-client-3.8.1}/setup.cfg +0 -0
@@ -1,26 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.7.1
3
+ Version: 3.8.1
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
7
+ License: UNKNOWN
8
+ Platform: UNKNOWN
7
9
  Classifier: Programming Language :: Python :: 3
8
10
  Classifier: License :: OSI Approved :: Apache Software License
9
11
  Classifier: Operating System :: OS Independent
10
12
  Requires-Python: >3.8.0
11
13
  Description-Content-Type: text/markdown
12
14
  License-File: LICENSE.txt
13
- Requires-Dist: pip>=21.0
14
- Requires-Dist: requests<3
15
- Requires-Dist: requests-toolbelt
16
- Requires-Dist: pandas>=1.2.5
17
- Requires-Dist: pydantic>=1.10.17
18
- Requires-Dist: deprecated==1.2.14
19
- Requires-Dist: tqdm
20
- Requires-Dist: simplejson>=3.17.0
21
- Requires-Dist: pyarrow>=7.0.0
22
- Requires-Dist: pyyaml
23
- Requires-Dist: typing-extensions<5,>=4.6.0
24
15
 
25
16
  Fiddler Client
26
17
  =============
@@ -39,8 +30,10 @@ Installation
39
30
 
40
31
  API Example Usage
41
32
  -------------
42
- Documentation for the API can be found [here](https://docs.fiddler.ai). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
33
+ Documentation for the API can be found [here](https://docs.fiddler.ai/reference/about-the-fiddler-client). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
43
34
 
44
35
  Version History
45
36
  -------------
46
37
  Version history is available on [Fiddler documentation page](https://docs.fiddler.ai/page/python-client-version-history).
38
+
39
+
@@ -15,7 +15,7 @@ Installation
15
15
 
16
16
  API Example Usage
17
17
  -------------
18
- Documentation for the API can be found [here](https://docs.fiddler.ai). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
18
+ Documentation for the API can be found [here](https://docs.fiddler.ai/reference/about-the-fiddler-client). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
19
19
 
20
20
  Version History
21
21
  -------------
@@ -0,0 +1 @@
1
+ 3.8.1
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from fiddler.connection import Connection, ConnectionMixin, init # noqa
4
4
  from fiddler.constants.alert_rule import ( # noqa
5
5
  AlertCondition,
6
+ AlertThresholdAlgo,
6
7
  BinSize,
7
8
  CompareTo,
8
9
  Priority,
@@ -83,6 +84,7 @@ __all__ = [
83
84
  'AlertCondition',
84
85
  'ArtifactStatus',
85
86
  'ArtifactType',
87
+ 'AlertThresholdAlgo',
86
88
  'BaselineType',
87
89
  'BinSize',
88
90
  'CompareTo',
@@ -28,3 +28,12 @@ class Priority(str, enum.Enum):
28
28
  HIGH = 'HIGH'
29
29
  MEDIUM = 'MEDIUM'
30
30
  LOW = 'LOW'
31
+
32
+
33
+ @enum.unique
34
+ class AlertThresholdAlgo(str, enum.Enum):
35
+ MANUAL = 'manual'
36
+ STD_DEV_AUTO_THRESHOLD = 'standard_deviation_auto_threshold'
37
+
38
+ def __str__(self) -> str:
39
+ return self.value
@@ -19,6 +19,8 @@ class AlertRecord(BaseEntity):
19
19
  self.baseline_time_bucket: int | None = None
20
20
  self.baseline_value: float | None = None
21
21
  self.is_alert: bool | None = None
22
+ self.warning_threshold: float | None = None
23
+ self.critical_threshold: float | None = None
22
24
  self.severity: str | None = None
23
25
  self.failure_reason: str | None = None
24
26
  self.message: str | None = None
@@ -28,6 +30,7 @@ class AlertRecord(BaseEntity):
28
30
 
29
31
  self.id: UUID | None = None
30
32
  self.alert_rule_id: UUID | None = None
33
+ self.alert_rule_revision: int | None = None
31
34
  self.created_at: datetime | None = None
32
35
  self.updated_at: datetime | None = None
33
36
 
@@ -48,12 +51,15 @@ class AlertRecord(BaseEntity):
48
51
  fields = [
49
52
  'id',
50
53
  'alert_rule_id',
54
+ 'alert_rule_revision',
51
55
  'alert_run_start_time',
52
56
  'alert_time_bucket',
53
57
  'alert_value',
54
58
  'baseline_time_bucket',
55
59
  'baseline_value',
56
60
  'is_alert',
61
+ 'warning_threshold',
62
+ 'critical_threshold',
57
63
  'severity',
58
64
  'failure_reason',
59
65
  'message',
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import builtins
4
+ import json
4
5
  import logging
5
6
  from datetime import datetime
6
7
  from typing import Any, Iterator
@@ -8,7 +9,13 @@ from uuid import UUID
8
9
 
9
10
  from pydantic.v1 import ValidationError
10
11
 
11
- from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
12
+ from fiddler.constants.alert_rule import (
13
+ AlertCondition,
14
+ AlertThresholdAlgo,
15
+ BinSize,
16
+ CompareTo,
17
+ Priority
18
+ )
12
19
  from fiddler.decorators import handle_api_error
13
20
  from fiddler.entities.base import BaseEntity
14
21
  from fiddler.entities.baseline import BaselineCompactMixin
@@ -33,13 +40,15 @@ class AlertRule(
33
40
  compare_to: CompareTo | str,
34
41
  condition: AlertCondition | str,
35
42
  bin_size: BinSize | str,
36
- critical_threshold: float,
43
+ threshold_type: AlertThresholdAlgo | str = AlertThresholdAlgo.MANUAL,
44
+ critical_threshold: float | None = None,
37
45
  warning_threshold: float | None = None,
38
46
  columns: list[str] | None = None,
39
47
  baseline_id: UUID | str | None = None,
40
48
  segment_id: UUID | str | None = None,
41
49
  compare_bin_delta: int | None = None,
42
50
  evaluation_delay: int = 0,
51
+ category: str | None = None,
43
52
  ) -> None:
44
53
  """Construct a alert rule instance."""
45
54
  self.name = name
@@ -51,11 +60,13 @@ class AlertRule(
51
60
  self.compare_to = compare_to
52
61
  self.compare_bin_delta = compare_bin_delta
53
62
  self.evaluation_delay = evaluation_delay
63
+ self.threshold_type = threshold_type
54
64
  self.warning_threshold = warning_threshold
55
65
  self.critical_threshold = critical_threshold
56
66
  self.condition = condition
57
67
  self.bin_size = bin_size
58
68
  self.segment_id = segment_id
69
+ self.category = category
59
70
 
60
71
  self.id: UUID | None = None
61
72
  self.project_id: UUID | None = None
@@ -93,6 +104,7 @@ class AlertRule(
93
104
  compare_to=resp_obj.compare_to,
94
105
  condition=resp_obj.condition,
95
106
  bin_size=resp_obj.bin_size,
107
+ threshold_type=resp_obj.threshold_type,
96
108
  critical_threshold=resp_obj.critical_threshold,
97
109
  warning_threshold=resp_obj.warning_threshold,
98
110
  columns=resp_obj.columns,
@@ -100,6 +112,7 @@ class AlertRule(
100
112
  segment_id=resp_obj.segment.id if resp_obj.segment else None,
101
113
  compare_bin_delta=resp_obj.compare_bin_delta,
102
114
  evaluation_delay=resp_obj.evaluation_delay,
115
+ category=resp_obj.category
103
116
  )
104
117
 
105
118
  # Add remaining fields
@@ -224,11 +237,13 @@ class AlertRule(
224
237
  'condition': self.condition,
225
238
  'bin_size': self.bin_size,
226
239
  'segment_id': self.segment_id,
240
+ 'threshold_type': self.threshold_type,
227
241
  'critical_threshold': self.critical_threshold,
228
242
  'warning_threshold': self.warning_threshold,
229
243
  'feature_names': self.columns,
230
244
  'compare_bin_delta': self.compare_bin_delta,
231
245
  'evaluation_delay': self.evaluation_delay,
246
+ 'category': self.category,
232
247
  }
233
248
  if self.baseline_id:
234
249
  payload['baseline_id'] = self.baseline_id
@@ -242,6 +257,24 @@ class AlertRule(
242
257
  self._refresh_from_response(response=response)
243
258
  return self
244
259
 
260
+ @handle_api_error
261
+ def update(self) -> None:
262
+ """Update an existing alert rule."""
263
+ body: dict[str, Any] = {
264
+ 'critical_threshold': self.critical_threshold,
265
+ 'warning_threshold': self.warning_threshold,
266
+ 'evaluation_delay': self.evaluation_delay,
267
+ }
268
+
269
+ response = self._client().patch(
270
+ url=self._get_url(id_=self.id),
271
+ json=body,
272
+ )
273
+ self._refresh_from_response(response=response)
274
+ logger.info(
275
+ 'Alert rule has been updated with properties: %s', json.dumps(body)
276
+ )
277
+
245
278
  @handle_api_error
246
279
  def enable_notifications(self) -> None:
247
280
  """Enable notifications for an alert rule"""
@@ -12,6 +12,7 @@ from fiddler.entities.base import BaseEntity
12
12
  from fiddler.exceptions import NotFound
13
13
  from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
14
14
  from fiddler.schemas.project import ProjectResp
15
+ from fiddler.utils.decorators import check_version
15
16
  from fiddler.utils.helpers import raise_not_found
16
17
 
17
18
  logger = logging.getLogger(__name__)
@@ -129,11 +130,13 @@ class Project(BaseEntity):
129
130
  logger.info('Project not found, creating a new one - `%s`', name)
130
131
  return Project(name=name).create()
131
132
 
133
+ @check_version(version_expr='>=25.2.0')
132
134
  @handle_api_error
133
135
  def delete(self) -> None:
134
136
  """Delete project"""
135
- # @TODO - Switch this to v3 once we have the endpoint
136
- self._client().delete(url=f'/v2/projects/{self.organization_name}:{self.name}')
137
+ assert self.id is not None
138
+
139
+ self._client().delete(url=self._get_url(id_=self.id))
137
140
 
138
141
  @property
139
142
  def models(self) -> Iterator[ModelCompact]:
@@ -10,9 +10,12 @@ from fiddler.schemas.base import BaseModel
10
10
  class AlertRecordResp(BaseModel):
11
11
  id: UUID = Field(alias='uuid')
12
12
  alert_rule_id: UUID = Field(alias='alert_config_uuid')
13
+ alert_rule_revision: int = Field(alias='alert_config_revision')
13
14
  alert_run_start_time: int
14
15
  alert_time_bucket: int
15
16
  alert_value: float
17
+ warning_threshold: Optional[float]
18
+ critical_threshold: float
16
19
  baseline_time_bucket: Optional[int]
17
20
  baseline_value: Optional[float]
18
21
  is_alert: bool
@@ -4,7 +4,13 @@ from uuid import UUID
4
4
 
5
5
  from pydantic.v1 import Field
6
6
 
7
- from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
7
+ from fiddler.constants.alert_rule import (
8
+ AlertCondition,
9
+ AlertThresholdAlgo,
10
+ BinSize,
11
+ CompareTo,
12
+ Priority
13
+ )
8
14
  from fiddler.schemas.base import BaseModel
9
15
  from fiddler.schemas.baseline import BaselineCompactResp
10
16
  from fiddler.schemas.custom_expression import SegmentCompactResp
@@ -29,8 +35,10 @@ class AlertRuleResp(BaseModel):
29
35
  evaluation_delay: int
30
36
  bin_size: Union[str, BinSize]
31
37
  columns: Optional[List[str]] = Field(alias='feature_names')
32
- critical_threshold: float
38
+ threshold_type: Union[str, AlertThresholdAlgo]
39
+ critical_threshold: Optional[float]
33
40
  warning_threshold: Optional[float]
41
+ category: Optional[str]
34
42
 
35
43
  created_at: datetime
36
44
  updated_at: datetime
@@ -3,7 +3,7 @@ from datetime import datetime
3
3
  import responses
4
4
 
5
5
  from fiddler.entities.alert_record import AlertRecord
6
- from fiddler.tests.constants import ALERT_RULE_ID, URL
6
+ from fiddler.tests.constants import ALERT_RULE_ID, ALERT_RULE_REVISION, URL
7
7
 
8
8
  ALERT_RECORD_LIST_RESPONSE = {
9
9
  'data': {
@@ -18,6 +18,7 @@ ALERT_RECORD_LIST_RESPONSE = {
18
18
  'id': 26410,
19
19
  'uuid': 'b520da6b-c01c-4375-bde6-2560cd972485',
20
20
  'alert_config_uuid': ALERT_RULE_ID,
21
+ 'alert_config_revision': ALERT_RULE_REVISION,
21
22
  'alert_run_start_time': 1703255503133,
22
23
  'alert_time_bucket': 1703116800000,
23
24
  'baseline_time_bucket': None,
@@ -27,6 +28,8 @@ ALERT_RECORD_LIST_RESPONSE = {
27
28
  'failure_reason': 'NA',
28
29
  'message': '',
29
30
  'alert_value': 37.0,
31
+ 'warning_threshold': 2.0,
32
+ 'critical_threshold': 3.0,
30
33
  'feature_name': 'estimatedsalary',
31
34
  'alert_record_main_version': 1,
32
35
  'alert_record_sub_version': 2,
@@ -37,6 +40,7 @@ ALERT_RECORD_LIST_RESPONSE = {
37
40
  'id': 26418,
38
41
  'uuid': '6e55540c-9053-4af8-b20e-1728b1436f35',
39
42
  'alert_config_uuid': ALERT_RULE_ID,
43
+ 'alert_config_revision': ALERT_RULE_REVISION,
40
44
  'alert_run_start_time': 1703259102527,
41
45
  'alert_time_bucket': 1703116800000,
42
46
  'baseline_time_bucket': None,
@@ -46,6 +50,8 @@ ALERT_RECORD_LIST_RESPONSE = {
46
50
  'failure_reason': 'NA',
47
51
  'message': '',
48
52
  'alert_value': 37.0,
53
+ 'warning_threshold': 2.0,
54
+ 'critical_threshold': 3.0,
49
55
  'feature_name': 'estimatedsalary',
50
56
  'alert_record_main_version': 1,
51
57
  'alert_record_sub_version': 3,
@@ -8,14 +8,16 @@ import pytest
8
8
  import responses
9
9
  from pydantic.v1 import ValidationError
10
10
 
11
- from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
11
+ from fiddler.constants.alert_rule import (
12
+ AlertThresholdAlgo,
13
+ AlertCondition,
14
+ BinSize,
15
+ CompareTo,
16
+ Priority
17
+ )
12
18
  from fiddler.entities.alert_rule import AlertRule
13
19
  from fiddler.exceptions import NotFound
14
20
  from fiddler.schemas.alert_rule import NotificationConfig
15
- from fiddler.tests.apis.test_baseline import (
16
- API_RESPONSE_200 as BASELINE_API_RESPONSE_200,
17
- )
18
- from fiddler.tests.apis.test_model import API_RESPONSE_200 as MODEL_API_RESPONSE_200
19
21
  from fiddler.tests.constants import (
20
22
  ALERT_RULE_ID,
21
23
  BASELINE_ID,
@@ -49,8 +51,9 @@ API_RESPONSE_200 = {
49
51
  'bin_size': 'Hour',
50
52
  'compare_to': 'raw_value',
51
53
  'condition': 'greater',
52
- 'warning_threshold': 1.0,
53
54
  'evaluation_delay': 10,
55
+ 'threshold_type': AlertThresholdAlgo.MANUAL.value,
56
+ 'warning_threshold': 1.0,
54
57
  'critical_threshold': 2.0,
55
58
  'updated_at': '2024-04-17T12:42:15.672909+00:00',
56
59
  'enable_notification': True,
@@ -131,6 +134,7 @@ LIST_API_RESPONSE = {
131
134
  'bin_size': 'Hour',
132
135
  'compare_to': 'raw_value',
133
136
  'condition': 'greater',
137
+ 'threshold_type': AlertThresholdAlgo.MANUAL.value,
134
138
  'warning_threshold': 1e-05,
135
139
  'critical_threshold': 0.001,
136
140
  'updated_at': '2024-04-17T12:43:23.871997+00:00',
@@ -250,38 +254,187 @@ def test_delete_alert_rule_not_found() -> None:
250
254
 
251
255
 
252
256
  @responses.activate
253
- def test_add_alert_rule_success() -> None:
254
- responses.get(
255
- url=f'{URL}/v3/models/{MODEL_ID}',
256
- json=MODEL_API_RESPONSE_200,
257
+ def test_add_alert_rule_success_manual_thresholds(mocker) -> None:
258
+ responses.post(
259
+ url=f'{URL}/v3/alert-rules',
260
+ json=API_RESPONSE_200,
257
261
  )
258
- responses.get(
259
- url=f'{URL}/v3/baselines/{BASELINE_ID}',
260
- json=BASELINE_API_RESPONSE_200,
262
+
263
+ # Test with manual threshold
264
+ alert_rule_1 = AlertRule(
265
+ name='alert_name',
266
+ model_id=MODEL_ID,
267
+ metric_id='drift',
268
+ priority=Priority.HIGH,
269
+ compare_to=CompareTo.RAW_VALUE,
270
+ condition=AlertCondition.GREATER,
271
+ bin_size=BinSize.HOUR,
272
+ threshold_type=AlertThresholdAlgo.MANUAL.value,
273
+ critical_threshold=2.0,
274
+ warning_threshold=1.0,
275
+ columns=['gender', 'creditscore'],
276
+ evaluation_delay=10,
277
+ ).create()
278
+
279
+ assert isinstance(alert_rule_1, AlertRule)
280
+ assert alert_rule_1.id == UUID(ALERT_RULE_ID)
281
+ assert alert_rule_1.model.id == UUID(MODEL_ID)
282
+ assert alert_rule_1.project_id == UUID(PROJECT_ID)
283
+ assert alert_rule_1.evaluation_delay == 10
284
+ assert alert_rule_1.threshold_type == AlertThresholdAlgo.MANUAL.value
285
+ assert alert_rule_1.critical_threshold == 2.0
286
+ assert alert_rule_1.warning_threshold == 1.0
287
+
288
+ # create one alert rule with category field
289
+ mocker.patch.dict(
290
+ API_RESPONSE_200['data'],
291
+ {
292
+ 'metric_id': 'frequency',
293
+ 'feature_names': ['geography'],
294
+ 'category': 'France',
295
+ },
296
+ )
297
+ alert_rule_2 = AlertRule(
298
+ name='alert_name',
299
+ model_id=MODEL_ID,
300
+ metric_id='frequency',
301
+ priority=Priority.HIGH,
302
+ compare_to=CompareTo.RAW_VALUE,
303
+ condition=AlertCondition.GREATER,
304
+ bin_size=BinSize.HOUR,
305
+ threshold_type=AlertThresholdAlgo.MANUAL.value,
306
+ critical_threshold=2.0,
307
+ warning_threshold=1.0,
308
+ evaluation_delay=10,
309
+ columns=['geography'],
310
+ category='France',
311
+ ).create()
312
+
313
+ assert isinstance(alert_rule_2, AlertRule)
314
+ assert alert_rule_2.id == UUID(ALERT_RULE_ID)
315
+ assert alert_rule_2.model.id == UUID(MODEL_ID)
316
+ assert alert_rule_2.project_id == UUID(PROJECT_ID)
317
+ assert alert_rule_2.evaluation_delay == 10
318
+ assert alert_rule_2.threshold_type == AlertThresholdAlgo.MANUAL.value
319
+ assert alert_rule_2.critical_threshold == 2.0
320
+ assert alert_rule_2.warning_threshold == 1.0
321
+ assert alert_rule_2.columns == ['geography']
322
+ assert alert_rule_2.category == 'France'
323
+
324
+
325
+ @responses.activate
326
+ def test_add_alert_rule_success_auto_thresholds(mocker) -> None:
327
+ mocker.patch.dict(
328
+ API_RESPONSE_200['data'],
329
+ {
330
+ 'bin_size': BinSize.DAY,
331
+ 'threshold_type': AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value,
332
+ 'warning_threshold': None,
333
+ 'critical_threshold': None,
334
+ },
261
335
  )
262
336
  responses.post(
263
337
  url=f'{URL}/v3/alert-rules',
264
338
  json=API_RESPONSE_200,
265
339
  )
266
- alert_rule = AlertRule(
340
+ alert_rule_auto_threshold = AlertRule(
267
341
  name='alert_name',
268
342
  model_id=MODEL_ID,
269
343
  metric_id='drift',
270
344
  priority=Priority.HIGH,
271
345
  compare_to=CompareTo.RAW_VALUE,
272
346
  condition=AlertCondition.GREATER,
273
- bin_size=BinSize.HOUR,
274
- critical_threshold=0.5,
275
- warning_threshold=0.1,
347
+ bin_size=BinSize.DAY,
348
+ threshold_type=AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value,
349
+ critical_threshold=None,
350
+ warning_threshold=None,
276
351
  columns=['gender', 'creditscore'],
277
352
  evaluation_delay=10,
278
353
  ).create()
279
354
 
280
- assert isinstance(alert_rule, AlertRule)
281
- assert alert_rule.id == UUID(ALERT_RULE_ID)
282
- assert alert_rule.model.id == UUID(MODEL_ID)
283
- assert alert_rule.project_id == UUID(PROJECT_ID)
284
- assert alert_rule.evaluation_delay == 10
355
+ assert isinstance(alert_rule_auto_threshold, AlertRule)
356
+ assert alert_rule_auto_threshold.id == UUID(ALERT_RULE_ID)
357
+ assert alert_rule_auto_threshold.model.id == UUID(MODEL_ID)
358
+ assert alert_rule_auto_threshold.project_id == UUID(PROJECT_ID)
359
+ assert alert_rule_auto_threshold.evaluation_delay == 10
360
+ assert alert_rule_auto_threshold.bin_size == BinSize.DAY
361
+ assert alert_rule_auto_threshold.threshold_type == AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value
362
+ assert alert_rule_auto_threshold.critical_threshold is None
363
+ assert alert_rule_auto_threshold.warning_threshold is None
364
+
365
+
366
+ @responses.activate
367
+ def test_update_alert_rule_success(mocker) -> None:
368
+ responses.get(
369
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
370
+ json=API_RESPONSE_200,
371
+ )
372
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
373
+
374
+ mocker.patch.dict(API_RESPONSE_200['data'], {'warning_threshold': 3.0})
375
+ responses.patch(
376
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
377
+ json=API_RESPONSE_200,
378
+ )
379
+ alert_rule.warning_threshold = 3.0
380
+ alert_rule.update()
381
+ assert alert_rule.warning_threshold == 3.0
382
+
383
+ mocker.patch.dict(API_RESPONSE_200['data'], {'critical_threshold': 4.0})
384
+ responses.patch(
385
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
386
+ json=API_RESPONSE_200,
387
+ )
388
+ alert_rule.critical_threshold = 4.0
389
+ alert_rule.update()
390
+ assert alert_rule.critical_threshold == 4.0
391
+
392
+ mocker.patch.dict(API_RESPONSE_200['data'], {'evaluation_delay': 5})
393
+ responses.patch(
394
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
395
+ json=API_RESPONSE_200,
396
+ )
397
+ alert_rule.evaluation_delay = 5
398
+ alert_rule.update()
399
+ assert alert_rule.evaluation_delay == 5
400
+
401
+ # Update multiple fields
402
+ mocker.patch.dict(
403
+ API_RESPONSE_200['data'],
404
+ {
405
+ 'warning_threshold': 13.0,
406
+ 'critical_threshold': 14.0,
407
+ 'evaluation_delay': 15,
408
+ },
409
+ )
410
+ responses.patch(
411
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
412
+ json=API_RESPONSE_200,
413
+ )
414
+ alert_rule.warning_threshold = 13.0
415
+ alert_rule.critical_threshold = 14.0
416
+ alert_rule.evaluation_delay = 15
417
+ alert_rule.update()
418
+ assert alert_rule.warning_threshold == 13.0
419
+ assert alert_rule.critical_threshold == 14.0
420
+ assert alert_rule.evaluation_delay == 15
421
+
422
+
423
+ @responses.activate
424
+ def test_update_alert_rule_not_found() -> None:
425
+ responses.get(
426
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
427
+ json=API_RESPONSE_200,
428
+ )
429
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
430
+
431
+ responses.patch(
432
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
433
+ json=API_RESPONSE_404,
434
+ status=HTTPStatus.NOT_FOUND,
435
+ )
436
+ with pytest.raises(NotFound):
437
+ alert_rule.update()
285
438
 
286
439
 
287
440
  @responses.activate
@@ -205,7 +205,7 @@ def test_project_list_empty() -> None:
205
205
  @responses.activate
206
206
  def test_delete_project_success() -> None:
207
207
  responses.delete(
208
- url=f'{URL}/v2/projects/{ORG_NAME}:{PROJECT_NAME}',
208
+ url=f'{URL}/v3/projects/{PROJECT_ID}',
209
209
  json={},
210
210
  )
211
211
  project = Project(name=PROJECT_NAME)
@@ -217,7 +217,7 @@ def test_delete_project_success() -> None:
217
217
  @responses.activate
218
218
  def test_delete_project_not_found() -> None:
219
219
  responses.delete(
220
- url=f'{URL}/v2/projects/{ORG_NAME}:{PROJECT_NAME}',
220
+ url=f'{URL}/v3/projects/{PROJECT_ID}',
221
221
  json=API_RESPONSE_404,
222
222
  status=HTTPStatus.NOT_FOUND,
223
223
  )
@@ -5,7 +5,7 @@ URL = 'https://dev.fiddler.ai'
5
5
  TOKEN = 'footoken'
6
6
  ORG_ID = '5531bfd9-2ca2-4a7b-bb5a-136c8da09ca0'
7
7
  ORG_NAME = 'fiddler_dev'
8
- SERVER_VERSION = '24.12.2'
8
+ SERVER_VERSION = '25.2.0'
9
9
  PROJECT_NAME = 'bank_churn'
10
10
  PROJECT_ID = '1531bfd9-2ca2-4a7b-bb5a-136c8da09ca1'
11
11
  MODEL_NAME = 'bank_churn'
@@ -20,6 +20,7 @@ DATASET_ID = 'ba6ec4e4-7188-44c5-ba84-c2cb22b4bb00'
20
20
  DATASET_NAME = 'dataset3'
21
21
  BASELINE_ID = 'af05646f-0cef-4638-84c9-0d195df2575d'
22
22
  ALERT_RULE_ID = 'ed8f18e6-c319-4374-8884-71126a6bab85'
23
+ ALERT_RULE_REVISION = 1
23
24
  TEST_EMAILS = ['test@fiddler.ai', 'admin@fiddler.ai']
24
25
  TEST_PAGERDUTY_SERVICES = ['service1', 'service2']
25
26
  TEST_PAGERDUTY_SEVERITY = 'critical'
@@ -1,26 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.7.1
3
+ Version: 3.8.1
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
7
+ License: UNKNOWN
8
+ Platform: UNKNOWN
7
9
  Classifier: Programming Language :: Python :: 3
8
10
  Classifier: License :: OSI Approved :: Apache Software License
9
11
  Classifier: Operating System :: OS Independent
10
12
  Requires-Python: >3.8.0
11
13
  Description-Content-Type: text/markdown
12
14
  License-File: LICENSE.txt
13
- Requires-Dist: pip>=21.0
14
- Requires-Dist: requests<3
15
- Requires-Dist: requests-toolbelt
16
- Requires-Dist: pandas>=1.2.5
17
- Requires-Dist: pydantic>=1.10.17
18
- Requires-Dist: deprecated==1.2.14
19
- Requires-Dist: tqdm
20
- Requires-Dist: simplejson>=3.17.0
21
- Requires-Dist: pyarrow>=7.0.0
22
- Requires-Dist: pyyaml
23
- Requires-Dist: typing-extensions<5,>=4.6.0
24
15
 
25
16
  Fiddler Client
26
17
  =============
@@ -39,8 +30,10 @@ Installation
39
30
 
40
31
  API Example Usage
41
32
  -------------
42
- Documentation for the API can be found [here](https://docs.fiddler.ai). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
33
+ Documentation for the API can be found [here](https://docs.fiddler.ai/reference/about-the-fiddler-client). For examples of interacting with our APIs, please check out our [Quick Start Guide](https://docs.fiddler.ai/docs/quick-start) as well as the notebooks found on our [Examples Github](https://github.com/fiddler-labs/fiddler-examples).
43
34
 
44
35
  Version History
45
36
  -------------
46
37
  Version history is available on [Fiddler documentation page](https://docs.fiddler.ai/page/python-client-version-history).
38
+
39
+
@@ -1,11 +1,11 @@
1
- pip>=21.0
2
- requests<3
3
- requests-toolbelt
1
+ deprecated==1.2.15
4
2
  pandas>=1.2.5
5
- pydantic>=1.10.17
6
- deprecated==1.2.14
7
- tqdm
8
- simplejson>=3.17.0
3
+ pip>=21.0
9
4
  pyarrow>=7.0.0
5
+ pydantic>=1.10.17
10
6
  pyyaml
7
+ requests-toolbelt
8
+ requests<3
9
+ simplejson>=3.17.0
10
+ tqdm
11
11
  typing-extensions<5,>=4.6.0
@@ -29,7 +29,7 @@ setuptools.setup(
29
29
  'requests-toolbelt',
30
30
  'pandas>=1.2.5',
31
31
  'pydantic>=1.10.17',
32
- 'deprecated==1.2.14',
32
+ 'deprecated==1.2.15',
33
33
  'tqdm',
34
34
  'simplejson>=3.17.0',
35
35
  'pyarrow>=7.0.0',
@@ -1 +0,0 @@
1
- 3.7.1
File without changes
File without changes