fiddler-client 3.1.0.dev2__tar.gz → 3.1.0.dev3__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 (116) hide show
  1. {fiddler-client-3.1.0.dev2/fiddler_client.egg-info → fiddler-client-3.1.0.dev3}/PKG-INFO +2 -1
  2. fiddler-client-3.1.0.dev3/fiddler/VERSION +1 -0
  3. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/__init__.py +2 -0
  4. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/alert_rule.py +5 -1
  5. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/events.py +51 -16
  6. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/model.py +23 -10
  7. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/webhook.py +18 -0
  8. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/alert_rule.py +3 -2
  9. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/custom_expression.py +7 -0
  10. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_alert_rule.py +44 -37
  11. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_model.py +7 -0
  12. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_webhook.py +57 -0
  13. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3/fiddler_client.egg-info}/PKG-INFO +2 -1
  14. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler_client.egg-info/requires.txt +1 -0
  15. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/setup.py +1 -0
  16. fiddler-client-3.1.0.dev2/fiddler/VERSION +0 -1
  17. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/LICENSE.txt +0 -0
  18. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/MANIFEST.in +0 -0
  19. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/PUBLIC.md +0 -0
  20. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/README.md +0 -0
  21. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/configs.py +0 -0
  22. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/connection.py +0 -0
  23. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/__init__.py +0 -0
  24. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/alert_rule.py +0 -0
  25. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/baseline.py +0 -0
  26. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/common.py +0 -0
  27. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/dataset.py +0 -0
  28. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/events.py +0 -0
  29. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/job.py +0 -0
  30. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/model.py +0 -0
  31. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/model_deployment.py +0 -0
  32. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/constants/xai.py +0 -0
  33. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/decorators.py +0 -0
  34. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/__init__.py +0 -0
  35. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/alert_record.py +0 -0
  36. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/base.py +0 -0
  37. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/baseline.py +0 -0
  38. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/custom_expression.py +0 -0
  39. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/dataset.py +0 -0
  40. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/file.py +0 -0
  41. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/job.py +0 -0
  42. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/model_artifact.py +0 -0
  43. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/model_deployment.py +0 -0
  44. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/organization.py +0 -0
  45. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/project.py +0 -0
  46. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/surrogate.py +0 -0
  47. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/user.py +0 -0
  48. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/entities/xai.py +0 -0
  49. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/exceptions.py +0 -0
  50. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/libs/__init__.py +0 -0
  51. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/libs/http_client.py +0 -0
  52. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/libs/json_encoder.py +0 -0
  53. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/libs/semver.py +0 -0
  54. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/packtools/__init__.py +0 -0
  55. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/packtools/gem.py +0 -0
  56. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/packtools/keras_ig_helpers.py +0 -0
  57. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/packtools/project_attributions_helpers.py +0 -0
  58. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/packtools/template_model.py +0 -0
  59. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/__init__.py +0 -0
  60. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/alert_record.py +0 -0
  61. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/base.py +0 -0
  62. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/baseline.py +0 -0
  63. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/custom_features.py +0 -0
  64. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/dataset.py +0 -0
  65. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/events.py +0 -0
  66. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/file.py +0 -0
  67. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/filter_query.py +0 -0
  68. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/job.py +0 -0
  69. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/model.py +0 -0
  70. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/model_deployment.py +0 -0
  71. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/model_schema.py +0 -0
  72. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/model_spec.py +0 -0
  73. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/model_task_params.py +0 -0
  74. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/organization.py +0 -0
  75. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/project.py +0 -0
  76. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/response.py +0 -0
  77. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/server_info.py +0 -0
  78. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/user.py +0 -0
  79. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/webhook.py +0 -0
  80. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/xai.py +0 -0
  81. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/schemas/xai_params.py +0 -0
  82. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/__init__.py +0 -0
  83. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/__init__.py +0 -0
  84. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_alert_record.py +0 -0
  85. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_baseline.py +0 -0
  86. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_custom_metric.py +0 -0
  87. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_dataset.py +0 -0
  88. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_events.py +0 -0
  89. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_files.py +0 -0
  90. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_generate_model.py +0 -0
  91. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_job.py +0 -0
  92. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_mixin.py +0 -0
  93. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_model_artifact.py +0 -0
  94. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_model_deployment.py +0 -0
  95. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  96. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_project.py +0 -0
  97. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_segment.py +0 -0
  98. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/apis/test_xai.py +0 -0
  99. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/conftest.py +0 -0
  100. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/constants.py +0 -0
  101. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/test_connection.py +0 -0
  102. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/test_json_encoder.py +0 -0
  103. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/test_logger.py +0 -0
  104. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/test_utils.py +0 -0
  105. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/tests/utils.py +0 -0
  106. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/__init__.py +0 -0
  107. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/helpers.py +0 -0
  108. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/logger.py +0 -0
  109. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/model_generator.py +0 -0
  110. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/validations.py +0 -0
  111. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/utils/version.py +0 -0
  112. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler/version.py +0 -0
  113. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler_client.egg-info/SOURCES.txt +0 -0
  114. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler_client.egg-info/dependency_links.txt +0 -0
  115. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/fiddler_client.egg-info/top_level.txt +0 -0
  116. {fiddler-client-3.1.0.dev2 → fiddler-client-3.1.0.dev3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.1.0.dev2
3
+ Version: 3.1.0.dev3
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -20,6 +20,7 @@ Requires-Dist: tqdm
20
20
  Requires-Dist: simplejson>=3.17.0
21
21
  Requires-Dist: pyarrow>=7.0.0
22
22
  Requires-Dist: pyyaml
23
+ Requires-Dist: typing-extensions<=4.5.0
23
24
 
24
25
  Fiddler Client
25
26
  =============
@@ -0,0 +1 @@
1
+ 3.1.0.dev3
@@ -61,6 +61,7 @@ from fiddler.schemas.xai import ( # noqa
61
61
  SqlSliceQueryDataSource,
62
62
  )
63
63
  from fiddler.schemas.xai_params import XaiParams # noqa
64
+ from fiddler.utils.helpers import group_by # noqa
64
65
  from fiddler.utils.logger import set_logging # noqa
65
66
  from fiddler.version import __version__ # noqa
66
67
 
@@ -141,4 +142,5 @@ __all__ = [
141
142
  'ApiError',
142
143
  # Utilities
143
144
  'set_logging',
145
+ 'group_by',
144
146
  ]
@@ -34,6 +34,7 @@ class AlertRule(
34
34
  warning_threshold: float | None = None,
35
35
  columns: list[str] | None = None,
36
36
  baseline_id: UUID | str | None = None,
37
+ segment_id: UUID | str | None = None,
37
38
  compare_bin_delta: int | None = None,
38
39
  ) -> None:
39
40
  """Construct a alert rule instance."""
@@ -49,6 +50,7 @@ class AlertRule(
49
50
  self.critical_threshold = critical_threshold
50
51
  self.condition = condition
51
52
  self.bin_size = bin_size
53
+ self.segment_id = segment_id
52
54
 
53
55
  self.id: UUID | None = None
54
56
  self.project_id: UUID | None = None
@@ -84,7 +86,8 @@ class AlertRule(
84
86
  critical_threshold=resp_obj.critical_threshold,
85
87
  warning_threshold=resp_obj.warning_threshold,
86
88
  columns=resp_obj.columns,
87
- baseline_id=resp_obj.baseline_id,
89
+ baseline_id=resp_obj.baseline.id if resp_obj.baseline else None,
90
+ segment_id=resp_obj.segment.id if resp_obj.segment else None,
88
91
  compare_bin_delta=resp_obj.compare_bin_delta,
89
92
  )
90
93
 
@@ -210,6 +213,7 @@ class AlertRule(
210
213
  'compare_to': self.compare_to,
211
214
  'condition': self.condition,
212
215
  'bin_size': self.bin_size,
216
+ 'segment_id': self.segment_id,
213
217
  'critical_threshold': self.critical_threshold,
214
218
  'warning_threshold': self.warning_threshold,
215
219
  'feature_names': self.columns,
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import tempfile
4
4
  from pathlib import Path
5
- from typing import Any
5
+ from typing import Any, Callable
6
6
  from uuid import UUID
7
7
 
8
8
  import pandas as pd
@@ -17,6 +17,9 @@ from fiddler.entities.job import Job
17
17
  from fiddler.schemas.dataset import EnvType
18
18
  from fiddler.schemas.events import EventsSource, FileSource
19
19
  from fiddler.schemas.job import JobCompactResp
20
+ from fiddler.utils.logger import get_logger
21
+
22
+ logger = get_logger(__name__)
20
23
 
21
24
 
22
25
  class EventPublisher(ConnectionMixin):
@@ -51,40 +54,72 @@ class EventPublisher(ConnectionMixin):
51
54
 
52
55
  :return: list[UUID] for list of dicts source and Job object for file path or dataframe source.
53
56
  """
57
+
58
+ publish_method = self._get_publish_method(source=source)
59
+
60
+ return publish_method(
61
+ source=source,
62
+ environment=environment,
63
+ dataset_name=dataset_name,
64
+ update=update,
65
+ )
66
+
67
+ def _get_publish_method(
68
+ self, source: list[dict[str, Any]] | str | Path | pd.DataFrame
69
+ ) -> Callable:
54
70
  if isinstance(source, (str, Path)):
55
- return self._publish_file(
56
- source=source,
57
- environment=environment,
58
- dataset_name=dataset_name,
59
- update=update,
60
- )
71
+ return self._publish_file
61
72
 
62
73
  if isinstance(source, pd.DataFrame):
63
- with tempfile.NamedTemporaryFile(suffix='.csv') as temp_file:
64
- source.to_csv(temp_file.name, index=False)
74
+ return self._publish_df
75
+
76
+ if isinstance(source, list):
77
+ return self._publish_stream
78
+
79
+ raise ValueError(f'Unsupported source - {type(source)}')
80
+
81
+ def _publish_df(
82
+ self,
83
+ source: pd.DataFrame,
84
+ environment: EnvType,
85
+ dataset_name: str | None = None,
86
+ update: bool = False,
87
+ ) -> Job:
88
+ with tempfile.NamedTemporaryFile(suffix='.parquet') as temp_file:
89
+ try:
90
+ source.to_parquet(temp_file.name, index=False)
65
91
  return self._publish_file(
66
92
  source=temp_file.name,
67
93
  environment=environment,
68
94
  dataset_name=dataset_name,
69
95
  update=update,
70
96
  )
71
-
72
- elif isinstance(source, list):
73
- return self._publish_stream(source=source, update=update)
74
-
75
- raise ValueError(f'Unsupported source - {type(source)}')
97
+ except Exception:
98
+ logger.warning(
99
+ 'Failed to convert input dataframe to parquet format. Retrying as a CSV file.'
100
+ )
101
+ with tempfile.NamedTemporaryFile(suffix='.csv') as temp_file:
102
+ source.to_csv(temp_file.name, index=False)
103
+ return self._publish_file(
104
+ source=temp_file.name,
105
+ environment=environment,
106
+ dataset_name=dataset_name,
107
+ update=update,
108
+ )
76
109
 
77
110
  def _publish_stream(
78
111
  self,
79
112
  source: list[dict[str, Any]],
113
+ environment: EnvType = EnvType.PRODUCTION,
114
+ dataset_name: str | None = None,
80
115
  update: bool = False,
81
116
  ) -> list[UUID]:
82
117
  event_ids = []
83
118
  for i in tqdm(range(0, len(source), self.STREAM_LIMIT)):
84
119
  response = self._publish_call(
85
120
  source=EventsSource(events=source[i : i + self.STREAM_LIMIT]),
86
- environment=EnvType.PRODUCTION,
87
- dataset_name=None,
121
+ environment=environment,
122
+ dataset_name=dataset_name,
88
123
  update=update,
89
124
  )
90
125
  event_ids.extend(response.json()['data']['event_ids'])
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import builtins
4
- import copy
5
4
  import typing
6
5
  from dataclasses import dataclass
7
6
  from datetime import datetime
@@ -33,6 +32,7 @@ from fiddler.schemas.model_spec import ModelSpec
33
32
  from fiddler.schemas.model_task_params import ModelTaskParams
34
33
  from fiddler.schemas.xai_params import XaiParams
35
34
  from fiddler.utils.helpers import raise_not_found
35
+ from fiddler.utils.logger import get_logger
36
36
  from fiddler.utils.model_generator import ModelGenerator
37
37
 
38
38
  if typing.TYPE_CHECKING:
@@ -40,6 +40,9 @@ if typing.TYPE_CHECKING:
40
40
  from fiddler.entities.dataset import Dataset
41
41
 
42
42
 
43
+ logger = get_logger(__name__)
44
+
45
+
43
46
  class Model(
44
47
  BaseEntity,
45
48
  CreatedByMixin,
@@ -307,7 +310,9 @@ class Model(
307
310
  params = {'filter': _filter.json()}
308
311
 
309
312
  for model in cls._paginate(url=cls._get_url(), params=params):
310
- yield ModelCompact(id=model['id'], name=model['name'])
313
+ yield ModelCompact(
314
+ id=model['id'], name=model['name'], version=model['version']
315
+ )
311
316
 
312
317
  def duplicate(self, version: str | None = None) -> Model:
313
318
  """
@@ -319,13 +324,21 @@ class Model(
319
324
  :param version: Version name for the new instance
320
325
  :return: Model instance
321
326
  """
322
- self_copy = copy.deepcopy(self)
323
- self_copy.id = None
324
-
325
- if version:
326
- self_copy.version = version
327
-
328
- return self_copy
327
+ return Model(
328
+ name=self.name,
329
+ project_id=self.project_id,
330
+ schema=self.schema,
331
+ spec=self.spec,
332
+ version=version if version else self.version,
333
+ input_type=self.input_type,
334
+ task=self.task,
335
+ task_params=self.task_params,
336
+ description=self.description,
337
+ event_id_col=self.event_id_col,
338
+ event_ts_col=self.event_ts_col,
339
+ event_ts_format=self.event_ts_format,
340
+ xai_params=self.xai_params,
341
+ )
329
342
 
330
343
  @property
331
344
  def datasets(self) -> Iterator[Dataset]:
@@ -456,7 +469,7 @@ class Model(
456
469
  :return: list[UUID] for list of dicts or dataframe source and Job object for
457
470
  file path source.
458
471
  """
459
-
472
+ logger.info('Model[%s/%s] - Publishing events', self.name, self.version)
460
473
  return self._event_publisher.publish(
461
474
  source=source,
462
475
  environment=environment,
@@ -6,7 +6,9 @@ from uuid import UUID
6
6
 
7
7
  from fiddler.decorators import handle_api_error
8
8
  from fiddler.entities.base import BaseEntity
9
+ from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
9
10
  from fiddler.schemas.webhook import WebhookProvider, WebhookResp
11
+ from fiddler.utils.helpers import raise_not_found
10
12
 
11
13
 
12
14
  class Webhook(BaseEntity):
@@ -81,6 +83,22 @@ class Webhook(BaseEntity):
81
83
  response = cls._client().get(url=cls._get_url(id_))
82
84
  return cls._from_response(response=response)
83
85
 
86
+ @classmethod
87
+ @handle_api_error
88
+ def from_name(cls, name: str) -> Webhook:
89
+ """Get the webhook instance using webhook name"""
90
+ _filter = QueryCondition(
91
+ rules=[QueryRule(field='name', operator=OperatorType.EQUAL, value=name)]
92
+ )
93
+
94
+ response = cls._client().get(
95
+ url=cls._get_url(), params={'filter': _filter.json()}
96
+ )
97
+ if response.json()['data']['total'] == 0:
98
+ raise_not_found('Webhook not found for the given identifier')
99
+
100
+ return cls._from_dict(data=response.json()['data']['items'][0])
101
+
84
102
  @classmethod
85
103
  @handle_api_error
86
104
  def list(cls) -> Iterator[Webhook]:
@@ -7,6 +7,7 @@ from pydantic import Field
7
7
  from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
8
8
  from fiddler.schemas.base import BaseModel
9
9
  from fiddler.schemas.baseline import BaselineCompactResp
10
+ from fiddler.schemas.custom_expression import SegmentCompactResp
10
11
  from fiddler.schemas.model import ModelCompactResp
11
12
  from fiddler.schemas.project import ProjectCompactResp
12
13
 
@@ -17,14 +18,14 @@ class AlertRuleResp(BaseModel):
17
18
  model: ModelCompactResp
18
19
  project: ProjectCompactResp
19
20
  baseline: Optional[BaselineCompactResp]
21
+ segment: Optional[SegmentCompactResp]
20
22
  priority: Union[str, Priority]
21
23
  compare_to: Union[str, CompareTo]
22
24
  metric_id: Union[str, UUID]
23
25
  critical_threshold: float
24
26
  condition: Union[str, AlertCondition]
25
27
  bin_size: Union[str, BinSize]
26
- columns: Optional[List[str]]
27
- baseline_id: Optional[UUID]
28
+ columns: Optional[List[str]] = Field(alias='feature_names')
28
29
  compare_bin_delta: Optional[int]
29
30
  warning_threshold: Optional[float]
30
31
 
@@ -29,3 +29,10 @@ class CustomMetricResp(CustomExpressionResp):
29
29
 
30
30
  class SegmentResp(CustomExpressionResp):
31
31
  """Segment response object"""
32
+
33
+
34
+ class SegmentCompactResp(BaseModel):
35
+ """Segment compact response object"""
36
+
37
+ id: UUID
38
+ name: str
@@ -28,54 +28,61 @@ from fiddler.utils.logger import set_logging
28
28
 
29
29
  API_RESPONSE_200 = {
30
30
  'data': {
31
- 'feature_names': ['age'],
32
- 'id': 620,
33
- 'created_at': '2023-11-28T08:04:12.651937+00:00',
31
+ 'id': 794,
34
32
  'organization_name': 'mainbuild',
35
- 'compare_period': None,
36
- 'time_bucket': 3600000,
37
- 'alert_type': 'data_integrity',
38
- 'metric_display_name': 'Missing Value Violation',
39
- 'enable_notification': True,
40
- 'last_updated': '2023-11-28T08:04:12.653346+00:00',
41
- 'alert_type_display_name': 'Data Integrity',
42
- 'critical_threshold': 0.0,
33
+ 'project_name': PROJECT_NAME,
34
+ 'model_id': 285,
35
+ 'name': 'test_rule',
36
+ 'metric': 'jsd',
37
+ 'metric_id': 'jsd',
38
+ 'metric_display_name': 'Jensen-Shannon Distance',
39
+ 'alert_type': 'drift',
40
+ 'alert_type_display_name': 'Data Drift',
41
+ 'priority': 'MEDIUM',
43
42
  'baseline_name': BASELINE_NAME,
44
- 'baseline': {
45
- 'id': BASELINE_ID,
46
- 'name': BASELINE_NAME,
47
- },
43
+ 'feature_names': ['creditscore'],
44
+ 'time_bucket': 3600000,
45
+ 'category': None,
46
+ 'bin_size': 'Hour',
47
+ 'compare_to': 'raw_value',
48
48
  'condition': 'greater',
49
- 'uuid': ALERT_RULE_ID,
50
- 'segment': None,
51
- 'warning_threshold': None,
52
- 'name': 'Age Missing 1 Hr',
53
- 'model_name': MODEL_NAME,
54
- 'model': {
55
- 'id': MODEL_ID,
56
- 'name': MODEL_NAME,
57
- },
49
+ 'compare_period': None,
50
+ 'warning_threshold': 1.0,
51
+ 'critical_threshold': 2.3,
58
52
  'is_active': True,
59
53
  'created_by': 'admin@fiddler.ai',
60
- 'bin_size': 'Hour',
61
- 'category': None,
62
- 'project_name': PROJECT_NAME,
63
- 'project': {
64
- 'id': PROJECT_ID,
65
- 'name': PROJECT_NAME,
54
+ 'created_at': '2024-04-23T10:34:14.321895+00:00',
55
+ 'last_updated': '2024-04-23T10:34:14.323554+00:00',
56
+ 'model_name': 'bank_churn',
57
+ 'enable_notification': True,
58
+ 'segment': {
59
+ 'id': '1c9b551a-808b-4ef0-b67b-e788eaf1e6de',
60
+ 'organization_name': 'mainbuild',
61
+ 'project_name': 'nick_test_project_11',
62
+ 'model_name': 'bank_churn',
63
+ 'name': 'xyzab',
64
+ 'definition': 'Age > 10',
65
+ 'description': 'meh',
66
+ 'created_at': '2024-04-23T10:31:52.181550+00:00',
67
+ 'created_by': {
68
+ 'id': 1,
69
+ 'full_name': 'Fiddler Administrator',
70
+ 'email': 'admin@fiddler.ai',
71
+ },
66
72
  },
67
- 'metric': 'null_violation_count',
68
- 'metric_id': 'null_violation_count',
69
- 'compare_to': 'raw_value',
70
- 'priority': 'HIGH',
73
+ 'project': {'id': PROJECT_ID, 'name': PROJECT_NAME},
74
+ 'model': {'id': MODEL_ID, 'name': MODEL_NAME, 'version': 'v1'},
75
+ 'baseline': {'id': BASELINE_ID, 'name': BASELINE_NAME},
76
+ 'compare_bin_delta': None,
77
+ 'uuid': ALERT_RULE_ID,
71
78
  'notifications': {
72
- 'emails': {'alert_config_uuid': ALERT_RULE_ID, 'email': 'admin@fiddler.ai'},
73
79
  'pagerduty': {
74
- 'severity': '',
75
80
  'alert_config_uuid': ALERT_RULE_ID,
76
81
  'service': '',
82
+ 'severity': '',
77
83
  },
78
- 'webhooks': [{'uuid': 'e20bf4cc-d2cf-4540-baef-d96913b14f1b'}],
84
+ 'emails': {'email': ''},
85
+ 'webhooks': [],
79
86
  },
80
87
  },
81
88
  'api_version': '2.0',
@@ -471,6 +471,7 @@ def test_model_list_success() -> None:
471
471
  models = Model.list(project_id=PROJECT_ID)
472
472
  for model in models:
473
473
  assert isinstance(model, ModelCompact)
474
+ assert model.version is not None
474
475
 
475
476
 
476
477
  @responses.activate
@@ -654,12 +655,18 @@ def test_model_duplicate() -> None:
654
655
  model = Model.get(id_=MODEL_ID)
655
656
 
656
657
  assert model.id == UUID(MODEL_ID)
658
+ assert model._event_publisher.model_id == model.id
657
659
 
658
660
  # Without version parameter
659
661
  model_copy = model.duplicate()
662
+
660
663
  assert model_copy.id is None
661
664
  assert model_copy.version == model.version
662
665
 
666
+ with pytest.raises(AssertionError):
667
+ # since id is None
668
+ _ = model_copy._event_publisher
669
+
663
670
  # With version parameter
664
671
  new_version = 'v2'
665
672
  model_copy = model.duplicate(version=new_version)
@@ -48,6 +48,29 @@ API_RESPONSE_404 = {
48
48
  'kind': 'ERROR',
49
49
  }
50
50
 
51
+ API_RESPONSE_FROM_NAME = {
52
+ 'data': {
53
+ 'page_size': 100,
54
+ 'total': 1,
55
+ 'item_count': 1,
56
+ 'page_count': 1,
57
+ 'page_index': 1,
58
+ 'offset': 0,
59
+ 'items': [
60
+ {
61
+ 'id': 1,
62
+ 'uuid': WEBHOOK_ID,
63
+ 'name': WEBHOOK_NAME,
64
+ 'url': WEBHOOK_URL,
65
+ 'provider': WEBHOOK_PROVIDER,
66
+ 'created_at': '2024-04-30T13:38:08.408013+00:00',
67
+ 'updated_at': '2024-04-30T13:38:08.408013+00:00',
68
+ 'organization_name': ORG_NAME,
69
+ }
70
+ ],
71
+ }
72
+ }
73
+
51
74
  LIST_API_RESPONSE = {
52
75
  'data': {
53
76
  'page_size': 100,
@@ -124,6 +147,40 @@ def test_get_webhook_not_found() -> None:
124
147
  Webhook.get(id_=webhook_id)
125
148
 
126
149
 
150
+ @responses.activate
151
+ def test_webhook_from_name_success() -> None:
152
+ params = {
153
+ 'filter': '{"condition": "AND", "rules": [{"field": "name", "operator": "equal", "value": "test_webhook_config_name"}]}'
154
+ }
155
+ responses.get(
156
+ url=f'{URL}/v2/webhooks',
157
+ json=API_RESPONSE_FROM_NAME,
158
+ match=[responses.matchers.query_param_matcher(params)],
159
+ )
160
+ webhook = Webhook.from_name(name=WEBHOOK_NAME)
161
+ assert isinstance(webhook, Webhook)
162
+
163
+
164
+ @responses.activate
165
+ def test_webhook_from_name_not_found() -> None:
166
+ resp = API_RESPONSE_FROM_NAME.copy()
167
+ resp['data']['total'] = 0
168
+ resp['data']['item_count'] = 0
169
+ resp['data']['items'] = []
170
+
171
+ params = {
172
+ 'filter': '{"condition": "AND", "rules": [{"field": "name", "operator": "equal", "value": "test_webhook_config_name"}]}'
173
+ }
174
+ responses.get(
175
+ url=f'{URL}/v2/webhooks',
176
+ json=resp,
177
+ match=[responses.matchers.query_param_matcher(params)],
178
+ )
179
+
180
+ with pytest.raises(NotFound):
181
+ Webhook.from_name(name=WEBHOOK_NAME)
182
+
183
+
127
184
  @responses.activate
128
185
  def test_webhook_list_success() -> None:
129
186
  responses.get(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.1.0.dev2
3
+ Version: 3.1.0.dev3
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -20,6 +20,7 @@ Requires-Dist: tqdm
20
20
  Requires-Dist: simplejson>=3.17.0
21
21
  Requires-Dist: pyarrow>=7.0.0
22
22
  Requires-Dist: pyyaml
23
+ Requires-Dist: typing-extensions<=4.5.0
23
24
 
24
25
  Fiddler Client
25
26
  =============
@@ -8,3 +8,4 @@ tqdm
8
8
  simplejson>=3.17.0
9
9
  pyarrow>=7.0.0
10
10
  pyyaml
11
+ typing-extensions<=4.5.0
@@ -31,6 +31,7 @@ setuptools.setup(
31
31
  'simplejson>=3.17.0',
32
32
  'pyarrow>=7.0.0',
33
33
  'pyyaml',
34
+ 'typing-extensions<=4.5.0',
34
35
  ],
35
36
  classifiers=[
36
37
  'Programming Language :: Python :: 3',
@@ -1 +0,0 @@
1
- 3.1.0.dev2