fiddler-client 3.7.0__tar.gz → 3.8.0__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.0/fiddler_client.egg-info → fiddler-client-3.8.0}/PKG-INFO +6 -13
  2. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/PUBLIC.md +1 -1
  3. fiddler-client-3.8.0/fiddler/VERSION +1 -0
  4. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/__init__.py +2 -0
  5. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/configs.py +1 -0
  6. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/connection.py +1 -0
  7. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/alert_rule.py +9 -0
  8. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/alert_record.py +6 -0
  9. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/alert_rule.py +31 -2
  10. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/file.py +4 -1
  11. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/project.py +5 -2
  12. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/libs/http_client.py +5 -6
  13. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/alert_record.py +3 -0
  14. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/alert_rule.py +9 -2
  15. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_alert_record.py +7 -1
  16. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_alert_rule.py +138 -11
  17. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_project.py +2 -2
  18. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/constants.py +2 -1
  19. {fiddler_client-3.7.0 → fiddler-client-3.8.0/fiddler_client.egg-info}/PKG-INFO +6 -13
  20. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler_client.egg-info/requires.txt +7 -7
  21. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/setup.py +1 -1
  22. fiddler_client-3.7.0/fiddler/VERSION +0 -1
  23. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/LICENSE.txt +0 -0
  24. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/MANIFEST.in +0 -0
  25. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/README.md +0 -0
  26. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/__init__.py +0 -0
  27. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/baseline.py +0 -0
  28. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/common.py +0 -0
  29. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/dataset.py +0 -0
  30. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/events.py +0 -0
  31. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/job.py +0 -0
  32. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/model.py +0 -0
  33. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/model_deployment.py +0 -0
  34. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/constants/xai.py +0 -0
  35. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/decorators.py +0 -0
  36. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/__init__.py +0 -0
  37. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/base.py +0 -0
  38. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/baseline.py +0 -0
  39. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/custom_expression.py +0 -0
  40. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/dataset.py +0 -0
  41. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/events.py +0 -0
  42. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/job.py +0 -0
  43. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/model.py +0 -0
  44. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/model_artifact.py +0 -0
  45. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/model_deployment.py +0 -0
  46. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/organization.py +0 -0
  47. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/surrogate.py +0 -0
  48. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/user.py +0 -0
  49. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/webhook.py +0 -0
  50. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/entities/xai.py +0 -0
  51. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/exceptions.py +0 -0
  52. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/libs/__init__.py +0 -0
  53. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/libs/aws.py +0 -0
  54. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/libs/json_encoder.py +0 -0
  55. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/libs/semver.py +0 -0
  56. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/packtools/__init__.py +0 -0
  57. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/packtools/gem.py +0 -0
  58. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/packtools/keras_ig_helpers.py +0 -0
  59. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/packtools/project_attributions_helpers.py +0 -0
  60. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/packtools/template_model.py +0 -0
  61. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/__init__.py +0 -0
  62. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/base.py +0 -0
  63. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/baseline.py +0 -0
  64. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/custom_expression.py +0 -0
  65. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/custom_features.py +0 -0
  66. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/dataset.py +0 -0
  67. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/events.py +0 -0
  68. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/file.py +0 -0
  69. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/filter_query.py +0 -0
  70. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/job.py +0 -0
  71. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/model.py +0 -0
  72. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/model_deployment.py +0 -0
  73. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/model_schema.py +0 -0
  74. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/model_spec.py +0 -0
  75. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/model_task_params.py +0 -0
  76. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/organization.py +0 -0
  77. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/project.py +0 -0
  78. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/response.py +0 -0
  79. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/server_info.py +0 -0
  80. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/user.py +0 -0
  81. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/webhook.py +0 -0
  82. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/xai.py +0 -0
  83. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/schemas/xai_params.py +0 -0
  84. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/__init__.py +0 -0
  85. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/__init__.py +0 -0
  86. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_baseline.py +0 -0
  87. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_custom_metric.py +0 -0
  88. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_dataset.py +0 -0
  89. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_events.py +0 -0
  90. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_files.py +0 -0
  91. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_generate_model.py +0 -0
  92. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_job.py +0 -0
  93. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_mixin.py +0 -0
  94. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_model.py +0 -0
  95. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_model_artifact.py +0 -0
  96. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_model_deployment.py +0 -0
  97. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  98. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_segment.py +0 -0
  99. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_webhook.py +0 -0
  100. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/apis/test_xai.py +0 -0
  101. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/conftest.py +0 -0
  102. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/test_connection.py +0 -0
  103. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/test_json_encoder.py +0 -0
  104. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/test_logger.py +0 -0
  105. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/test_sagemaker_auth.py +0 -0
  106. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/test_utils.py +0 -0
  107. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/tests/utils.py +0 -0
  108. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/__init__.py +0 -0
  109. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/decorators.py +0 -0
  110. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/helpers.py +0 -0
  111. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/logger.py +0 -0
  112. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/model_generator.py +0 -0
  113. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/validations.py +0 -0
  114. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/utils/version.py +0 -0
  115. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler/version.py +0 -0
  116. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler_client.egg-info/SOURCES.txt +0 -0
  117. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler_client.egg-info/dependency_links.txt +0 -0
  118. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/fiddler_client.egg-info/top_level.txt +0 -0
  119. {fiddler_client-3.7.0 → fiddler-client-3.8.0}/setup.cfg +0 -0
@@ -1,26 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.7.0
3
+ Version: 3.8.0
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.0
@@ -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',
@@ -11,3 +11,4 @@ JOB_WAIT_TIMEOUT = 1800
11
11
  STREAM_EVENT_LIMIT = 1000
12
12
  DEFAULT_NUM_CLUSTERS = 5
13
13
  DEFAULT_NUM_TAGS = 5
14
+ UPLOAD_REQUEST_TIMEOUT = (120, 100)
@@ -83,6 +83,7 @@ class Connection:
83
83
  headers=self.request_headers,
84
84
  proxies=self.proxies,
85
85
  verify=self.verify,
86
+ timeout_override=self.timeout,
86
87
  )
87
88
 
88
89
  @cached_property
@@ -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,7 +40,8 @@ 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,
@@ -51,6 +59,7 @@ class AlertRule(
51
59
  self.compare_to = compare_to
52
60
  self.compare_bin_delta = compare_bin_delta
53
61
  self.evaluation_delay = evaluation_delay
62
+ self.threshold_type = threshold_type
54
63
  self.warning_threshold = warning_threshold
55
64
  self.critical_threshold = critical_threshold
56
65
  self.condition = condition
@@ -93,6 +102,7 @@ class AlertRule(
93
102
  compare_to=resp_obj.compare_to,
94
103
  condition=resp_obj.condition,
95
104
  bin_size=resp_obj.bin_size,
105
+ threshold_type=resp_obj.threshold_type,
96
106
  critical_threshold=resp_obj.critical_threshold,
97
107
  warning_threshold=resp_obj.warning_threshold,
98
108
  columns=resp_obj.columns,
@@ -224,6 +234,7 @@ class AlertRule(
224
234
  'condition': self.condition,
225
235
  'bin_size': self.bin_size,
226
236
  'segment_id': self.segment_id,
237
+ 'threshold_type': self.threshold_type,
227
238
  'critical_threshold': self.critical_threshold,
228
239
  'warning_threshold': self.warning_threshold,
229
240
  'feature_names': self.columns,
@@ -242,6 +253,24 @@ class AlertRule(
242
253
  self._refresh_from_response(response=response)
243
254
  return self
244
255
 
256
+ @handle_api_error
257
+ def update(self) -> None:
258
+ """Update an existing alert rule."""
259
+ body: dict[str, Any] = {
260
+ 'critical_threshold': self.critical_threshold,
261
+ 'warning_threshold': self.warning_threshold,
262
+ 'evaluation_delay': self.evaluation_delay,
263
+ }
264
+
265
+ response = self._client().patch(
266
+ url=self._get_url(id_=self.id),
267
+ json=body,
268
+ )
269
+ self._refresh_from_response(response=response)
270
+ logger.info(
271
+ 'Alert rule has been updated with properties: %s', json.dumps(body)
272
+ )
273
+
245
274
  @handle_api_error
246
275
  def enable_notifications(self) -> None:
247
276
  """Enable notifications for an alert rule"""
@@ -1,15 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import io
4
+ import logging
4
5
  import os
5
6
  from datetime import datetime
6
- import logging
7
7
  from pathlib import Path
8
8
  from typing import Any
9
9
  from uuid import UUID
10
10
 
11
11
  from requests import Response
12
12
 
13
+ from fiddler.configs import UPLOAD_REQUEST_TIMEOUT
13
14
  from fiddler.constants.common import MULTI_PART_CHUNK_SIZE
14
15
  from fiddler.decorators import handle_api_error
15
16
  from fiddler.entities.base import BaseEntity
@@ -83,6 +84,7 @@ class File(BaseEntity, CreatedByMixin, UpdatedByMixin):
83
84
  # with: "You can set the filename, content_type and headers
84
85
  # explicitly" (this form of 'file': n-tuple)
85
86
  files={'file': (self.name, open(self.path, 'rb').read())},
87
+ timeout=self._client()._timeout_override or UPLOAD_REQUEST_TIMEOUT,
86
88
  )
87
89
 
88
90
  self._refresh_from_response(response)
@@ -142,6 +144,7 @@ class File(BaseEntity, CreatedByMixin, UpdatedByMixin):
142
144
  'file_id': (None, str(self.id)),
143
145
  'part_number': (None, part_number),
144
146
  },
147
+ timeout=self._client()._timeout_override or UPLOAD_REQUEST_TIMEOUT,
145
148
  )
146
149
 
147
150
  parts.append(
@@ -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]:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
3
  import logging
4
+ import os
5
5
  import time
6
6
  from copy import deepcopy
7
7
  from typing import Any
@@ -15,7 +15,6 @@ import fiddler.libs.aws
15
15
  from fiddler.exceptions import BaseError # pylint: disable=redefined-builtin
16
16
  from fiddler.libs.json_encoder import RequestClientJSONEncoder
17
17
 
18
-
19
18
  log = logging.getLogger(__name__)
20
19
 
21
20
  # A shortcut.
@@ -514,7 +513,7 @@ class RequestClient:
514
513
  url: str,
515
514
  params: dict | None = None,
516
515
  headers: dict | None = None,
517
- timeout: int | None = None,
516
+ timeout: float | tuple[float, float] | None = None,
518
517
  **kwargs: Any,
519
518
  ) -> requests.Response:
520
519
  return self._request_with_retry(
@@ -532,7 +531,7 @@ class RequestClient:
532
531
  url: str,
533
532
  params: dict | None = None,
534
533
  headers: dict | None = None,
535
- timeout: int | None = None,
534
+ timeout: float | tuple[float, float] | None = None,
536
535
  data: dict | bytes | None = None,
537
536
  **kwargs: Any,
538
537
  ) -> requests.Response:
@@ -552,7 +551,7 @@ class RequestClient:
552
551
  url: str,
553
552
  params: dict | None = None,
554
553
  headers: dict | None = None,
555
- timeout: int | None = None,
554
+ timeout: float | tuple[float, float] | None = None,
556
555
  data: dict | None = None,
557
556
  **kwargs: Any,
558
557
  ) -> requests.Response:
@@ -572,7 +571,7 @@ class RequestClient:
572
571
  url: str,
573
572
  params: dict | None = None,
574
573
  headers: dict | None = None,
575
- timeout: int | None = None,
574
+ timeout: float | tuple[float, float] | None = None,
576
575
  data: dict | None = None,
577
576
  **kwargs: Any,
578
577
  ) -> requests.Response:
@@ -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,7 +35,8 @@ 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]
34
41
 
35
42
  created_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,7 +8,13 @@ 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
@@ -49,8 +55,9 @@ API_RESPONSE_200 = {
49
55
  'bin_size': 'Hour',
50
56
  'compare_to': 'raw_value',
51
57
  'condition': 'greater',
52
- 'warning_threshold': 1.0,
53
58
  'evaluation_delay': 10,
59
+ 'threshold_type': AlertThresholdAlgo.MANUAL.value,
60
+ 'warning_threshold': 1.0,
54
61
  'critical_threshold': 2.0,
55
62
  'updated_at': '2024-04-17T12:42:15.672909+00:00',
56
63
  'enable_notification': True,
@@ -131,6 +138,7 @@ LIST_API_RESPONSE = {
131
138
  'bin_size': 'Hour',
132
139
  'compare_to': 'raw_value',
133
140
  'condition': 'greater',
141
+ 'threshold_type': AlertThresholdAlgo.MANUAL.value,
134
142
  'warning_threshold': 1e-05,
135
143
  'critical_threshold': 0.001,
136
144
  'updated_at': '2024-04-17T12:43:23.871997+00:00',
@@ -250,7 +258,7 @@ def test_delete_alert_rule_not_found() -> None:
250
258
 
251
259
 
252
260
  @responses.activate
253
- def test_add_alert_rule_success() -> None:
261
+ def test_add_alert_rule_success(mocker) -> None:
254
262
  responses.get(
255
263
  url=f'{URL}/v3/models/{MODEL_ID}',
256
264
  json=MODEL_API_RESPONSE_200,
@@ -263,7 +271,9 @@ def test_add_alert_rule_success() -> None:
263
271
  url=f'{URL}/v3/alert-rules',
264
272
  json=API_RESPONSE_200,
265
273
  )
266
- alert_rule = AlertRule(
274
+
275
+ # Test with manual threshold
276
+ alert_rule_manual_threshold = AlertRule(
267
277
  name='alert_name',
268
278
  model_id=MODEL_ID,
269
279
  metric_id='drift',
@@ -271,17 +281,134 @@ def test_add_alert_rule_success() -> None:
271
281
  compare_to=CompareTo.RAW_VALUE,
272
282
  condition=AlertCondition.GREATER,
273
283
  bin_size=BinSize.HOUR,
274
- critical_threshold=0.5,
275
- warning_threshold=0.1,
284
+ threshold_type=AlertThresholdAlgo.MANUAL.value,
285
+ critical_threshold=2.0,
286
+ warning_threshold=1.0,
276
287
  columns=['gender', 'creditscore'],
277
288
  evaluation_delay=10,
278
289
  ).create()
279
290
 
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
291
+ assert isinstance(alert_rule_manual_threshold, AlertRule)
292
+ assert alert_rule_manual_threshold.id == UUID(ALERT_RULE_ID)
293
+ assert alert_rule_manual_threshold.model.id == UUID(MODEL_ID)
294
+ assert alert_rule_manual_threshold.project_id == UUID(PROJECT_ID)
295
+ assert alert_rule_manual_threshold.evaluation_delay == 10
296
+ assert alert_rule_manual_threshold.threshold_type == AlertThresholdAlgo.MANUAL.value
297
+ assert alert_rule_manual_threshold.critical_threshold == 2.0
298
+ assert alert_rule_manual_threshold.warning_threshold == 1.0
299
+
300
+ # Test with auto threshold
301
+ mocker.patch.dict(
302
+ API_RESPONSE_200['data'],
303
+ {
304
+ 'bin_size': BinSize.DAY,
305
+ 'threshold_type': AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value,
306
+ 'warning_threshold': None,
307
+ 'critical_threshold': None,
308
+ },
309
+ )
310
+ responses.post(
311
+ url=f'{URL}/v3/alert-rules',
312
+ json=API_RESPONSE_200,
313
+ )
314
+ alert_rule_auto_threshold = AlertRule(
315
+ name='alert_name',
316
+ model_id=MODEL_ID,
317
+ metric_id='drift',
318
+ priority=Priority.HIGH,
319
+ compare_to=CompareTo.RAW_VALUE,
320
+ condition=AlertCondition.GREATER,
321
+ bin_size=BinSize.DAY,
322
+ threshold_type=AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value,
323
+ critical_threshold=None,
324
+ warning_threshold=None,
325
+ columns=['gender', 'creditscore'],
326
+ evaluation_delay=10,
327
+ ).create()
328
+
329
+ assert isinstance(alert_rule_auto_threshold, AlertRule)
330
+ assert alert_rule_auto_threshold.id == UUID(ALERT_RULE_ID)
331
+ assert alert_rule_auto_threshold.model.id == UUID(MODEL_ID)
332
+ assert alert_rule_auto_threshold.project_id == UUID(PROJECT_ID)
333
+ assert alert_rule_auto_threshold.evaluation_delay == 10
334
+ assert alert_rule_auto_threshold.bin_size == BinSize.DAY
335
+ assert alert_rule_auto_threshold.threshold_type == AlertThresholdAlgo.STD_DEV_AUTO_THRESHOLD.value
336
+ assert alert_rule_auto_threshold.critical_threshold is None
337
+ assert alert_rule_auto_threshold.warning_threshold is None
338
+
339
+
340
+ @responses.activate
341
+ def test_update_alert_rule_success(mocker) -> None:
342
+ responses.get(
343
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
344
+ json=API_RESPONSE_200,
345
+ )
346
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
347
+
348
+ mocker.patch.dict(API_RESPONSE_200['data'], {'warning_threshold': 3.0})
349
+ responses.patch(
350
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
351
+ json=API_RESPONSE_200,
352
+ )
353
+ alert_rule.warning_threshold = 3.0
354
+ alert_rule.update()
355
+ assert alert_rule.warning_threshold == 3.0
356
+
357
+ mocker.patch.dict(API_RESPONSE_200['data'], {'critical_threshold': 4.0})
358
+ responses.patch(
359
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
360
+ json=API_RESPONSE_200,
361
+ )
362
+ alert_rule.critical_threshold = 4.0
363
+ alert_rule.update()
364
+ assert alert_rule.critical_threshold == 4.0
365
+
366
+ mocker.patch.dict(API_RESPONSE_200['data'], {'evaluation_delay': 5})
367
+ responses.patch(
368
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
369
+ json=API_RESPONSE_200,
370
+ )
371
+ alert_rule.evaluation_delay = 5
372
+ alert_rule.update()
373
+ assert alert_rule.evaluation_delay == 5
374
+
375
+ # Update multiple fields
376
+ mocker.patch.dict(
377
+ API_RESPONSE_200['data'],
378
+ {
379
+ 'warning_threshold': 13.0,
380
+ 'critical_threshold': 14.0,
381
+ 'evaluation_delay': 15,
382
+ },
383
+ )
384
+ responses.patch(
385
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
386
+ json=API_RESPONSE_200,
387
+ )
388
+ alert_rule.warning_threshold = 13.0
389
+ alert_rule.critical_threshold = 14.0
390
+ alert_rule.evaluation_delay = 15
391
+ alert_rule.update()
392
+ assert alert_rule.warning_threshold == 13.0
393
+ assert alert_rule.critical_threshold == 14.0
394
+ assert alert_rule.evaluation_delay == 15
395
+
396
+
397
+ @responses.activate
398
+ def test_update_alert_rule_not_found() -> None:
399
+ responses.get(
400
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
401
+ json=API_RESPONSE_200,
402
+ )
403
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
404
+
405
+ responses.patch(
406
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
407
+ json=API_RESPONSE_404,
408
+ status=HTTPStatus.NOT_FOUND,
409
+ )
410
+ with pytest.raises(NotFound):
411
+ alert_rule.update()
285
412
 
286
413
 
287
414
  @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.0
3
+ Version: 3.8.0
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.0
File without changes
File without changes