fiddler-client 3.3.0.dev1__py3-none-any.whl → 3.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fiddler/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.0.dev1
1
+ 3.3.2
fiddler/decorators.py CHANGED
@@ -39,7 +39,7 @@ def handle_api_error(func: _WrappedFuncType) -> _WrappedFuncType:
39
39
  error_resp = ErrorResponse(**e.response.json())
40
40
  except requests.JSONDecodeError:
41
41
  raise HttpError(
42
- message=f'Invalid response content-type - {e.response.content}'
42
+ message=f"Invalid response content-type - {e.response.content}" # type: ignore
43
43
  )
44
44
 
45
45
  if status_code == HTTPStatus.CONFLICT:
@@ -5,6 +5,8 @@ from datetime import datetime
5
5
  from typing import Any, Iterator
6
6
  from uuid import UUID
7
7
 
8
+ from pydantic import ValidationError
9
+
8
10
  from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
9
11
  from fiddler.decorators import handle_api_error
10
12
  from fiddler.entities.base import BaseEntity
@@ -276,14 +278,18 @@ class AlertRule(
276
278
 
277
279
  :return: NotificationConfig object
278
280
  """
279
- payload: dict[str, Any] = {}
280
- if emails is not None:
281
- payload['emails'] = emails
282
- if pagerduty_services is not None:
283
- payload['pagerduty_services'] = pagerduty_services
284
- payload['pagerduty_severity'] = pagerduty_severity
285
- if webhooks is not None:
286
- payload['webhooks'] = webhooks
281
+
282
+ # Validating input
283
+ try:
284
+ payload: dict[str, Any] = NotificationConfig(
285
+ emails=emails,
286
+ pagerduty_services=pagerduty_services,
287
+ pagerduty_severity=pagerduty_severity,
288
+ webhooks=webhooks,
289
+ ).dict(exclude_none=True)
290
+ except ValidationError as e:
291
+ logger.exception('Invalid input: The format of input is not correct')
292
+ raise e
287
293
  response = self._client().patch(
288
294
  url=self._get_notification_url(id_=self.id),
289
295
  data=payload,
@@ -1,10 +1,13 @@
1
1
  import json
2
2
  import logging
3
+ import uuid
4
+ from copy import deepcopy
3
5
  from http import HTTPStatus
4
6
  from uuid import UUID
5
7
 
6
8
  import pytest
7
9
  import responses
10
+ from pydantic import ValidationError
8
11
 
9
12
  from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
10
13
  from fiddler.entities.alert_rule import AlertRule
@@ -23,6 +26,8 @@ from fiddler.tests.constants import (
23
26
  PROJECT_ID,
24
27
  PROJECT_NAME,
25
28
  TEST_EMAILS,
29
+ TEST_PAGERDUTY_SERVICES,
30
+ TEST_PAGERDUTY_SEVERITY,
26
31
  TEST_WEBHOOKS,
27
32
  URL,
28
33
  )
@@ -76,8 +81,8 @@ API_RESPONSE_200 = {
76
81
 
77
82
  ALERT_NOTIFICATION_API_RESPONSE_200 = {
78
83
  'data': {
79
- 'emails': TEST_EMAILS,
80
- 'webhooks': TEST_WEBHOOKS,
84
+ 'emails': [],
85
+ 'webhooks': [],
81
86
  'pagerduty_services': [],
82
87
  'pagerduty_severity': '',
83
88
  },
@@ -331,28 +336,143 @@ def test_disable_notifications(caplog) -> None:
331
336
 
332
337
 
333
338
  @responses.activate
334
- def test_set_notifications() -> None:
339
+ def test_set_notifications_email() -> None:
335
340
  responses.get(
336
341
  url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
337
342
  json=API_RESPONSE_200,
338
343
  )
339
344
 
340
345
  alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
346
+ notification_resp = deepcopy(ALERT_NOTIFICATION_API_RESPONSE_200)
347
+ notification_resp['data']['emails'] = TEST_EMAILS
341
348
  resp = responses.patch(
342
349
  url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
343
- json=ALERT_NOTIFICATION_API_RESPONSE_200,
350
+ json=notification_resp,
344
351
  )
345
352
  notifications = alert_rule.set_notification_config(
346
353
  emails=TEST_EMAILS,
347
- webhooks=TEST_WEBHOOKS,
348
354
  )
349
355
  assert json.loads(resp.calls[0].request.body) == {
350
356
  'emails': TEST_EMAILS,
357
+ }
358
+ assert notifications == notification_resp['data']
359
+
360
+ # Removing the emails from the notification config
361
+ notification_resp['data']['emails'] = []
362
+ resp = responses.patch(
363
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
364
+ json=notification_resp,
365
+ )
366
+ notifications = alert_rule.set_notification_config(
367
+ emails=[],
368
+ )
369
+ assert json.loads(resp.calls[0].request.body) == {
370
+ 'emails': [],
371
+ }
372
+ assert notifications == notification_resp['data']
373
+
374
+
375
+ @responses.activate
376
+ def test_set_notifications_pagerduty() -> None:
377
+ responses.get(
378
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
379
+ json=API_RESPONSE_200,
380
+ )
381
+
382
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
383
+ notification_resp = deepcopy(ALERT_NOTIFICATION_API_RESPONSE_200)
384
+ notification_resp['data']['pagerduty_services'] = TEST_PAGERDUTY_SERVICES
385
+ notification_resp['data']['pagerduty_severity'] = TEST_PAGERDUTY_SEVERITY
386
+ resp = responses.patch(
387
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
388
+ json=notification_resp,
389
+ )
390
+ notifications = alert_rule.set_notification_config(
391
+ pagerduty_services=TEST_PAGERDUTY_SERVICES,
392
+ pagerduty_severity=TEST_PAGERDUTY_SEVERITY,
393
+ )
394
+
395
+ assert json.loads(resp.calls[0].request.body) == {
396
+ 'pagerduty_services': TEST_PAGERDUTY_SERVICES,
397
+ 'pagerduty_severity': TEST_PAGERDUTY_SEVERITY,
398
+ }
399
+ assert notifications == notification_resp['data']
400
+
401
+ # Removing the webhooks from the notification config
402
+ notification_resp['data']['pagerduty_services'] = []
403
+ notification_resp['data']['pagerduty_severity'] = ''
404
+ resp = responses.patch(
405
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
406
+ json=notification_resp,
407
+ )
408
+ notifications = alert_rule.set_notification_config(
409
+ pagerduty_services=[],
410
+ pagerduty_severity='',
411
+ )
412
+ assert json.loads(resp.calls[0].request.body) == {
413
+ 'pagerduty_services': [],
414
+ 'pagerduty_severity': '',
415
+ }
416
+ assert notifications == notification_resp['data']
417
+
418
+
419
+ @responses.activate
420
+ def test_set_notifications_webhooks() -> None:
421
+ responses.get(
422
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
423
+ json=API_RESPONSE_200,
424
+ )
425
+
426
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
427
+ notification_resp = deepcopy(ALERT_NOTIFICATION_API_RESPONSE_200)
428
+ notification_resp['data']['webhooks'] = TEST_WEBHOOKS
429
+ resp = responses.patch(
430
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
431
+ json=notification_resp,
432
+ )
433
+ notifications = alert_rule.set_notification_config(
434
+ webhooks=TEST_WEBHOOKS,
435
+ )
436
+
437
+ notification_resp['data']['webhooks'] = [
438
+ uuid.UUID(webhook_uuid)
439
+ for webhook_uuid in notification_resp['data']['webhooks']
440
+ ]
441
+ assert json.loads(resp.calls[0].request.body) == {
351
442
  'webhooks': TEST_WEBHOOKS,
352
443
  }
353
- assert notifications == NotificationConfig(
354
- **ALERT_NOTIFICATION_API_RESPONSE_200['data']
444
+ assert notifications == notification_resp['data']
445
+
446
+ # Removing the webhooks from the notification config
447
+ notification_resp['data']['webhooks'] = []
448
+ resp = responses.patch(
449
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}/notification',
450
+ json=notification_resp,
355
451
  )
452
+ notifications = alert_rule.set_notification_config(
453
+ webhooks=[],
454
+ )
455
+ assert json.loads(resp.calls[0].request.body) == {
456
+ 'webhooks': [],
457
+ }
458
+ assert notifications == notification_resp['data']
459
+
460
+
461
+ @responses.activate
462
+ def test_set_notifications_invalid_input(caplog) -> None:
463
+ responses.get(
464
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
465
+ json=API_RESPONSE_200,
466
+ )
467
+
468
+ alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
469
+
470
+ with pytest.raises(ValidationError):
471
+ alert_rule.set_notification_config(
472
+ emails=TEST_EMAILS[0],
473
+ webhooks=TEST_WEBHOOKS,
474
+ )
475
+ assert 'Invalid input: The format of input is not correct' in caplog.messages[0]
356
476
 
357
477
 
358
478
  @responses.activate
@@ -21,6 +21,8 @@ DATASET_NAME = 'dataset3'
21
21
  BASELINE_ID = 'af05646f-0cef-4638-84c9-0d195df2575d'
22
22
  ALERT_RULE_ID = 'ed8f18e6-c319-4374-8884-71126a6bab85'
23
23
  TEST_EMAILS = ['test@fiddler.ai', 'admin@fiddler.ai']
24
+ TEST_PAGERDUTY_SERVICES = ['service1', 'service2']
25
+ TEST_PAGERDUTY_SEVERITY = 'critical'
24
26
  TEST_WEBHOOKS = [
25
27
  'e20bf4cc-d2cf-4540-baef-d96913b14f1b',
26
28
  '6e796fda-0111-4a72-82cd-f0f219e903e1',
@@ -6,7 +6,7 @@ from fiddler.utils.logger import set_logging
6
6
 
7
7
  def test_set_logging() -> None:
8
8
  app_logger = logging.getLogger(LOGGER_NAME)
9
- assert len(app_logger.handlers) == 0
9
+ assert len(app_logger.handlers) == 2
10
10
 
11
11
  set_logging(level=logging.ERROR)
12
- assert len(app_logger.handlers) == 1
12
+ assert len(app_logger.handlers) == 3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.3.0.dev1
3
+ Version: 3.3.2
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -10,17 +10,17 @@ Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >3.8.0
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE.txt
13
- Requires-Dist: pip >=21.0
14
- Requires-Dist: requests <3
13
+ Requires-Dist: pip>=21.0
14
+ Requires-Dist: requests<3
15
15
  Requires-Dist: requests-toolbelt
16
- Requires-Dist: pandas >=1.2.5
17
- Requires-Dist: pydantic <2,>=1.10.15
18
- Requires-Dist: deprecated ==1.2.14
16
+ Requires-Dist: pandas>=1.2.5
17
+ Requires-Dist: pydantic<2,>=1.10.15
18
+ Requires-Dist: deprecated==1.2.14
19
19
  Requires-Dist: tqdm
20
- Requires-Dist: simplejson >=3.17.0
21
- Requires-Dist: pyarrow >=7.0.0
20
+ Requires-Dist: simplejson>=3.17.0
21
+ Requires-Dist: pyarrow>=7.0.0
22
22
  Requires-Dist: pyyaml
23
- Requires-Dist: typing-extensions <5,>=4.6.0
23
+ Requires-Dist: typing-extensions<5,>=4.6.0
24
24
 
25
25
  Fiddler Client
26
26
  =============
@@ -1,8 +1,8 @@
1
- fiddler/VERSION,sha256=QfGRdQhPzwQNImJpp9R4Y_lPSzeteYCWJbW7LMYoRf8,11
1
+ fiddler/VERSION,sha256=q7pfzW0SddYteOCdiCdtzyZNITf4UyOrUOrd3MMa7qk,6
2
2
  fiddler/__init__.py,sha256=pBLW7thJD1HkYhH5bJJbJFXSN8FNezos-rBU3HWhb4A,3794
3
3
  fiddler/configs.py,sha256=ZimSo0Gk7j1BFkjDHdRdycrGZ8oh-7G5TBXYiOh1HvU,217
4
4
  fiddler/connection.py,sha256=fLdSXpu5dwoK-h4Vtc9nbdKENOJ7jfEmrnDhVAtChck,5677
5
- fiddler/decorators.py,sha256=tWZliQQeUGwY0rU52FO9JXuOBueQXVEJywEbrgUEw1U,1820
5
+ fiddler/decorators.py,sha256=TyM5__nxjX8tIT83YAnIWMkWlh5GIsGg6F8wdlHeq-g,1836
6
6
  fiddler/exceptions.py,sha256=T4ZpkTYPbnWvUX7y5XehnCyHqQPj3qqsIDKCZQNtaIE,2221
7
7
  fiddler/version.py,sha256=8fyg3UhFpqghMpxbtYIwNcB1lhCG6yTkPBbDS7IrwxY,140
8
8
  fiddler/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -17,7 +17,7 @@ fiddler/constants/model_deployment.py,sha256=SfagLKVD7tK1QmYQFJLDrA4-6FaSeNF6tik
17
17
  fiddler/constants/xai.py,sha256=GR8VguB6FTfMJZ291FIbfDsY4S9BGOft3VxNW5jMf90,214
18
18
  fiddler/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  fiddler/entities/alert_record.py,sha256=RcDACWDNpntkiId-JpkLQvVeIbuaZAzn6AWl2zYIh9A,3564
20
- fiddler/entities/alert_rule.py,sha256=T7MadLOcDnBBzAYDveWWmuVU0MciQtqrlHC3GFZK8ws,10371
20
+ fiddler/entities/alert_rule.py,sha256=otenqprXqODzd-pGeTDB6sFzHBCioeMrGGVYOtUw_n8,10509
21
21
  fiddler/entities/base.py,sha256=YCTLt1ta8UbD7u-5BW7v_ocA4S7LevEncI5XPS_SB60,2106
22
22
  fiddler/entities/baseline.py,sha256=k3D-K8WC5MkHDILyejRaH1v9jdCIymT96McDBOVQ9A0,7907
23
23
  fiddler/entities/custom_expression.py,sha256=SdS61JiI0gOxWwHAGxkHh1vqS5XsRtyeNSDs5E-Sg2U,6568
@@ -70,15 +70,15 @@ fiddler/schemas/xai.py,sha256=AZbjjBlTDZbQGj3U-pTM1UX_LJltjy__2t-kM2v5FuY,739
70
70
  fiddler/schemas/xai_params.py,sha256=7WbUCBojzZckjOA2NUxnk5y3M2WKKXclSzkt5HBfyUU,313
71
71
  fiddler/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  fiddler/tests/conftest.py,sha256=Dmz9FKAFHYdq1AWmcY7NES9pU4cbY9qKWQiojjaX_0E,840
73
- fiddler/tests/constants.py,sha256=XuDw_3kzQEcgum-FynCfJzp-sAuRZ0wFS_w9tACFh6s,1264
73
+ fiddler/tests/constants.py,sha256=hKIh_XoGJVL8mWhdtUiMo0niII0iCXLkGMSVNv6y7l0,1352
74
74
  fiddler/tests/test_connection.py,sha256=d8WoB0QRZEObWfeRAZRXRm1kw9wfEysmeo4Bld7x8js,1865
75
75
  fiddler/tests/test_json_encoder.py,sha256=GJeFT5tTA4RTfZn1q2xm1V5SEj5DNsW3LeHPVfFxcFw,783
76
- fiddler/tests/test_logger.py,sha256=StDWgtVoBOplRsvcH44Su-ikOWcafT29Kof-K-jiTxc,312
76
+ fiddler/tests/test_logger.py,sha256=bhpS8TLrYBUOIzuk9XAs_Inot54LOWhw0A-8oXhZ2FM,312
77
77
  fiddler/tests/test_utils.py,sha256=AF6y7UfboEkCa-nNw0aF30SdHC7yW2Hh78J4H_4s78k,3333
78
78
  fiddler/tests/utils.py,sha256=FEDbASW4pYZktdEK2FLnIDyZCwBzpb60m6EzkvOkwSc,335
79
79
  fiddler/tests/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  fiddler/tests/apis/test_alert_record.py,sha256=_0EBRDn87TqTiO1KYEHKQQVtVZjj4lYjbt8Ix-RRTSg,3118
81
- fiddler/tests/apis/test_alert_rule.py,sha256=UhAaUwuumU8-xCLhecNNtCfBIrtRtnoZ-qHLD2rp_ck,10657
81
+ fiddler/tests/apis/test_alert_rule.py,sha256=0qwyTxRdt1tW1DuMwaqFJgbAEIV9cQ9xSo9F3XS660U,14638
82
82
  fiddler/tests/apis/test_baseline.py,sha256=R_vvbZdSenpYMSydurENJrE_uNWE3sJR9sHJksfU_Jk,7494
83
83
  fiddler/tests/apis/test_custom_metric.py,sha256=QlNa80M9PxqaqzW-3nCtH5kKLRHYu2iqFDautBusbos,8208
84
84
  fiddler/tests/apis/test_dataset.py,sha256=1Xc9Ng91fLMc2C6dpKfse42fQ0anza3ZOKOD1TqCvTQ,4636
@@ -101,8 +101,8 @@ fiddler/utils/logger.py,sha256=FdJ3LkS9dbRjWsw5oJmNNsd7q0XRVEIvx5-TWys7L0k,669
101
101
  fiddler/utils/model_generator.py,sha256=TwQMQDpy-0gcq6HyL68s37N-sk_nGPq33mmppK6i7hI,2203
102
102
  fiddler/utils/validations.py,sha256=i8NtgrpCsitq6BPa5lygpKDh07oaOXu7PAlCIcMvqzY,408
103
103
  fiddler/utils/version.py,sha256=iC8Ry7UFl9EJW_xU1WbzO_l4yK6V7eQ6U5exB3xT864,531
104
- fiddler_client-3.3.0.dev1.dist-info/LICENSE.txt,sha256=w8-LUAb_VLBWSsCNmih0pAqLIicJfGu8OJXpDjkIg_o,559
105
- fiddler_client-3.3.0.dev1.dist-info/METADATA,sha256=vpMA84-iC5vW2tVn6osO6Tvskmv5AVGlfmJJCfLiNTM,1602
106
- fiddler_client-3.3.0.dev1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
107
- fiddler_client-3.3.0.dev1.dist-info/top_level.txt,sha256=ndC6LqvKmrTTs8czRlBOYdYgSqZbHuMf0zHt_HWpzzk,8
108
- fiddler_client-3.3.0.dev1.dist-info/RECORD,,
104
+ fiddler_client-3.3.2.dist-info/LICENSE.txt,sha256=w8-LUAb_VLBWSsCNmih0pAqLIicJfGu8OJXpDjkIg_o,559
105
+ fiddler_client-3.3.2.dist-info/METADATA,sha256=z2aHBHYnPpGL1sEbNL3zlfIXEECfFwXncCd1BfqRLNQ,1589
106
+ fiddler_client-3.3.2.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
107
+ fiddler_client-3.3.2.dist-info/top_level.txt,sha256=ndC6LqvKmrTTs8czRlBOYdYgSqZbHuMf0zHt_HWpzzk,8
108
+ fiddler_client-3.3.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.1)
2
+ Generator: setuptools (74.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5