fiddler-client 3.6.0__tar.gz → 3.7.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 (125) hide show
  1. {fiddler_client-3.6.0/fiddler_client.egg-info → fiddler_client-3.7.0}/PKG-INFO +3 -3
  2. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/PUBLIC.md +2 -2
  3. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/README.md +76 -3
  4. fiddler_client-3.7.0/fiddler/VERSION +1 -0
  5. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/__init__.py +1 -1
  6. fiddler_client-3.7.0/fiddler/configs.py +13 -0
  7. fiddler_client-3.7.0/fiddler/connection.py +262 -0
  8. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/common.py +0 -2
  9. fiddler_client-3.7.0/fiddler/decorators.py +85 -0
  10. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/alert_rule.py +8 -5
  11. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/baseline.py +4 -3
  12. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/custom_expression.py +1 -0
  13. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/events.py +19 -4
  14. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/file.py +15 -8
  15. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/job.py +9 -9
  16. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/model.py +31 -4
  17. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/model_artifact.py +3 -2
  18. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/model_deployment.py +6 -6
  19. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/project.py +19 -1
  20. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/surrogate.py +9 -3
  21. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/webhook.py +6 -1
  22. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/xai.py +19 -7
  23. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/exceptions.py +4 -2
  24. fiddler_client-3.7.0/fiddler/libs/aws.py +95 -0
  25. fiddler_client-3.7.0/fiddler/libs/http_client.py +587 -0
  26. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/libs/semver.py +2 -0
  27. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/packtools/project_attributions_helpers.py +10 -8
  28. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/custom_features.py +1 -0
  29. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/model_spec.py +18 -3
  30. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_alert_record.py +2 -1
  31. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_alert_rule.py +3 -18
  32. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_baseline.py +3 -2
  33. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_dataset.py +3 -2
  34. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_events.py +64 -0
  35. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_files.py +11 -1
  36. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_generate_model.py +3 -2
  37. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model.py +40 -3
  38. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_project.py +58 -2
  39. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_webhook.py +2 -1
  40. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/test_connection.py +0 -2
  41. fiddler_client-3.7.0/fiddler/tests/test_logger.py +61 -0
  42. fiddler_client-3.7.0/fiddler/tests/test_sagemaker_auth.py +73 -0
  43. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/decorators.py +2 -2
  44. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/helpers.py +2 -2
  45. fiddler_client-3.7.0/fiddler/utils/logger.py +76 -0
  46. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/model_generator.py +1 -0
  47. {fiddler_client-3.6.0 → fiddler_client-3.7.0/fiddler_client.egg-info}/PKG-INFO +3 -3
  48. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler_client.egg-info/SOURCES.txt +2 -0
  49. fiddler_client-3.6.0/fiddler/VERSION +0 -1
  50. fiddler_client-3.6.0/fiddler/configs.py +0 -8
  51. fiddler_client-3.6.0/fiddler/connection.py +0 -191
  52. fiddler_client-3.6.0/fiddler/decorators.py +0 -52
  53. fiddler_client-3.6.0/fiddler/libs/http_client.py +0 -221
  54. fiddler_client-3.6.0/fiddler/tests/test_logger.py +0 -12
  55. fiddler_client-3.6.0/fiddler/utils/logger.py +0 -23
  56. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/LICENSE.txt +0 -0
  57. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/MANIFEST.in +0 -0
  58. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/__init__.py +0 -0
  59. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/alert_rule.py +0 -0
  60. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/baseline.py +0 -0
  61. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/dataset.py +0 -0
  62. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/events.py +0 -0
  63. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/job.py +0 -0
  64. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/model.py +0 -0
  65. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/model_deployment.py +0 -0
  66. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/constants/xai.py +0 -0
  67. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/__init__.py +0 -0
  68. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/alert_record.py +0 -0
  69. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/base.py +0 -0
  70. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/dataset.py +0 -0
  71. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/organization.py +0 -0
  72. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/entities/user.py +0 -0
  73. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/libs/__init__.py +0 -0
  74. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/libs/json_encoder.py +0 -0
  75. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/packtools/__init__.py +0 -0
  76. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/packtools/gem.py +0 -0
  77. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/packtools/keras_ig_helpers.py +0 -0
  78. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/packtools/template_model.py +0 -0
  79. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/__init__.py +0 -0
  80. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/alert_record.py +0 -0
  81. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/alert_rule.py +0 -0
  82. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/base.py +0 -0
  83. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/baseline.py +0 -0
  84. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/custom_expression.py +0 -0
  85. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/dataset.py +0 -0
  86. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/events.py +0 -0
  87. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/file.py +0 -0
  88. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/filter_query.py +0 -0
  89. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/job.py +0 -0
  90. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/model.py +0 -0
  91. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/model_deployment.py +0 -0
  92. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/model_schema.py +0 -0
  93. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/model_task_params.py +0 -0
  94. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/organization.py +0 -0
  95. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/project.py +0 -0
  96. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/response.py +0 -0
  97. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/server_info.py +0 -0
  98. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/user.py +0 -0
  99. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/webhook.py +0 -0
  100. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/xai.py +0 -0
  101. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/schemas/xai_params.py +0 -0
  102. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/__init__.py +0 -0
  103. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/__init__.py +0 -0
  104. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_custom_metric.py +0 -0
  105. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_job.py +0 -0
  106. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_mixin.py +0 -0
  107. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_artifact.py +0 -0
  108. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_deployment.py +0 -0
  109. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  110. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_segment.py +0 -0
  111. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/apis/test_xai.py +0 -0
  112. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/conftest.py +0 -0
  113. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/constants.py +0 -0
  114. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/test_json_encoder.py +0 -0
  115. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/test_utils.py +0 -0
  116. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/tests/utils.py +0 -0
  117. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/__init__.py +0 -0
  118. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/validations.py +0 -0
  119. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/utils/version.py +0 -0
  120. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler/version.py +0 -0
  121. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler_client.egg-info/dependency_links.txt +0 -0
  122. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler_client.egg-info/requires.txt +0 -0
  123. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/fiddler_client.egg-info/top_level.txt +0 -0
  124. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/setup.cfg +0 -0
  125. {fiddler_client-3.6.0 → fiddler_client-3.7.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.6.0
3
+ Version: 3.7.0
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -30,7 +30,7 @@ publishing for use with our monitoring features.
30
30
 
31
31
  Requirements
32
32
  ------------
33
- Requires Python >= Python-3.6.3 and pip >= 19.0
33
+ Requires Python >= Python-3.9 and pip >= 19.0
34
34
 
35
35
  Installation
36
36
  ------------
@@ -39,7 +39,7 @@ Installation
39
39
 
40
40
  API Example Usage
41
41
  -------------
42
- 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).
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).
43
43
 
44
44
  Version History
45
45
  -------------
@@ -6,7 +6,7 @@ publishing for use with our monitoring features.
6
6
 
7
7
  Requirements
8
8
  ------------
9
- Requires Python >= Python-3.6.3 and pip >= 19.0
9
+ Requires Python >= Python-3.9 and pip >= 19.0
10
10
 
11
11
  Installation
12
12
  ------------
@@ -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/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).
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).
19
19
 
20
20
  Version History
21
21
  -------------
@@ -2,7 +2,80 @@
2
2
 
3
3
  A Python library for interacting with the Fiddler HTTP API.
4
4
 
5
- ## Pre Release
5
+ ## Development
6
+
7
+ Run unit tests:
8
+
9
+ ```
10
+ $ make test
11
+ ...
12
+ 156 passed, 1 skipped in 0.59s
13
+ ```
14
+
15
+
16
+ Run mypy, pylint, ruff, flake8:
17
+
18
+ ```
19
+ $ make lint
20
+ mypy fiddler
21
+ Success: no issues found in 77 source files
22
+ ruff check .
23
+ All checks passed!
24
+ pylint fiddler
25
+ ...
26
+ flake8 fiddler
27
+ ```
28
+
29
+
30
+ ## Logging
31
+
32
+ ### Automatic log handler setup for ad-hoc scripts
33
+
34
+ Consider this minimal Python program:
35
+
36
+ ```python
37
+ import fiddler
38
+
39
+ # The call to `init()` below detects that there is no root logger configured.
40
+ # It automatically configures an outlet for log messages generated by this
41
+ # library: they end up being written to stderr with a meaningful default log
42
+ # format.
43
+ fiddler.init(url="https://f.bar", token="x")
44
+ ```
45
+
46
+ This feature can be disabled by passing `auto_attach_log_handler=False` to `init()`.
47
+
48
+ ### Full control in calling code: configure a root logger
49
+
50
+ Any more complex Python program that uses this client library typically sets up the logging machinery in a custom way. Example:
51
+
52
+ ```python
53
+ import logging
54
+ import os
55
+
56
+ import fiddler
57
+
58
+ # Example for configuring a root logger, with a stream handler attached for
59
+ # emission to stderr:
60
+ logging.basicConfig(
61
+ level=logging.INFO,
62
+ format="%(asctime)s.%(msecs)03d %(levelname)s: %(message)s",
63
+ datefmt="%y%m%d-%H:%M:%S",
64
+ )
65
+
66
+ # Now, the call to init() below does not attach any additional log handlers.
67
+ # Log messages emitted by this client library are simply propagated into the
68
+ # root logger (and adhere to custom filtering and formatting rules).
69
+ fiddler.init(url="https://f.bar", token="x")
70
+
71
+ # Example for custom verbosity control: do not forward DEBUG+INFO level
72
+ # messages from the 'fiddler' logger into the root logger.
73
+ logging.getLogger('fiddler').setLevel(logging.WARNING)
74
+ ```
75
+
76
+ ## Releasing
77
+
78
+ ### Pre Release
6
79
 
7
80
  As we get ready for distribution of the updated python client we need to ensure that all the associated downstream artifacts are updated.
8
81
 
@@ -16,7 +89,7 @@ As we get ready for distribution of the updated python client we need to ensure
16
89
  - If it's a new feature appropriate care has to be taken to
17
90
  - Customer Success needs to sign off on the changes and they need to plan for customer update
18
91
 
19
- ## Distribution
92
+ ### PyPI
20
93
 
21
94
  The Fiddler Python client is published as
22
95
  [`fiddler-client`](https://pypi.org/project/fiddler-client/) in the Python
@@ -42,7 +115,7 @@ Note: dev versions may be published from any branch at any time by using a
42
115
  `.devN` affix, as described in [PEP-440](https://peps.python.org/pep-0440/). For
43
116
  example: `1.4.3.dev5`.
44
117
 
45
- ## Post Release
118
+ ### Post Release
46
119
 
47
120
  1. Inform on `#releases` slack channel of the python client release with release notes.
48
121
  1. Verify:
@@ -0,0 +1 @@
1
+ 3.7.0
@@ -67,7 +67,7 @@ from fiddler.version import __version__ # noqa
67
67
  conn: Connection | None = None
68
68
 
69
69
 
70
- def set_conn(conn_: Connection) -> None:
70
+ def _set_conn(conn_: Connection) -> None:
71
71
  """Set global conn variable"""
72
72
  global conn
73
73
  conn = conn_
@@ -0,0 +1,13 @@
1
+ MIN_SERVER_VERSION = '24.4.0'
2
+ DEFAULT_PAGE_SIZE = 50
3
+
4
+ # In seconds. For example, this generates a log message every N seconds. Was
5
+ # once set to 3, and I think that was too frequent. If this needs to be
6
+ # snappier and apply to both, short-running jobs as well as long-running jobs:
7
+ # we can grow the interval between polls.
8
+ JOB_POLL_INTERVAL = 6
9
+ JOB_WAIT_TIMEOUT = 1800
10
+
11
+ STREAM_EVENT_LIMIT = 1000
12
+ DEFAULT_NUM_CLUSTERS = 5
13
+ DEFAULT_NUM_TAGS = 5
@@ -0,0 +1,262 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from functools import cached_property
5
+ from uuid import UUID
6
+
7
+ import fiddler.utils.logger
8
+ from fiddler.configs import MIN_SERVER_VERSION
9
+ from fiddler.constants.common import (
10
+ CLIENT_NAME,
11
+ FIDDLER_CLIENT_NAME_HEADER,
12
+ FIDDLER_CLIENT_VERSION_HEADER,
13
+ )
14
+ from fiddler.decorators import handle_api_error
15
+ from fiddler.exceptions import IncompatibleClient
16
+ from fiddler.libs.http_client import RequestClient
17
+ from fiddler.schemas.server_info import ServerInfo, Version
18
+ from fiddler.utils.version import match_semver
19
+ from fiddler.version import __version__
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+
24
+ class Connection:
25
+ def __init__( # pylint: disable=too-many-arguments
26
+ self,
27
+ url: str,
28
+ token: str,
29
+ proxies: dict | None = None,
30
+ timeout: float | tuple[float, float] | None = None,
31
+ verify: bool = True,
32
+ validate: bool = True,
33
+ ) -> None:
34
+ """
35
+ Initiate connection.
36
+
37
+ :param url:
38
+ The base URL to your Fiddler platform.
39
+ :param token:
40
+ An authentication token, obtained via the Fiddler UI.
41
+ :param proxies:
42
+ A dictionary mapping protocol to the URL of the proxy.
43
+ :param timeout:
44
+ Allows for overriding default HTTP request timeout settings.
45
+ Applies to all HTTP requests emitted with this connection object.
46
+ Can be a float or two floats, also see
47
+ https://requests.readthedocs.io/en/latest/user/advanced/#timeouts
48
+ :param verify:
49
+ Can be used to disable server's TLS certificate verification.
50
+ Certificate verification is enabled by default.
51
+ :param validate:
52
+ Whether to validate the server/client version compatibility. Some
53
+ features might not work as expected if this is turned off.
54
+ """
55
+
56
+ self.url = url
57
+ self.token = token
58
+ self.proxies = proxies
59
+ self.timeout = timeout
60
+ self.verify = verify
61
+
62
+ if not url:
63
+ raise ValueError('`url` is empty')
64
+
65
+ if not token:
66
+ raise ValueError('`token` is empty')
67
+
68
+ self.request_headers = {
69
+ 'Authorization': f'Bearer {token}',
70
+ FIDDLER_CLIENT_NAME_HEADER: CLIENT_NAME,
71
+ FIDDLER_CLIENT_VERSION_HEADER: __version__,
72
+ }
73
+
74
+ if validate:
75
+ self._check_server_version()
76
+ self._check_version_compatibility()
77
+
78
+ @cached_property
79
+ def client(self) -> RequestClient:
80
+ """Request client instance"""
81
+ return RequestClient(
82
+ base_url=self.url,
83
+ headers=self.request_headers,
84
+ proxies=self.proxies,
85
+ verify=self.verify,
86
+ )
87
+
88
+ @cached_property
89
+ def server_info(self) -> ServerInfo:
90
+ """Server info instance"""
91
+ return self._get_server_info()
92
+
93
+ @cached_property
94
+ def server_version(self) -> Version:
95
+ """Server semver version"""
96
+ return self.server_info.server_version
97
+
98
+ @cached_property
99
+ def organization_name(self) -> str:
100
+ """Organization name"""
101
+ return self.server_info.organization.name
102
+
103
+ @cached_property
104
+ def organization_id(self) -> UUID:
105
+ """Organization id"""
106
+ return self.server_info.organization.id
107
+
108
+ @handle_api_error
109
+ def _get_server_info(self) -> ServerInfo:
110
+ """Get server info"""
111
+
112
+ # Tight-ish timeout.
113
+ response = self.client.get(url='/v3/server-info', timeout=(5, 15))
114
+
115
+ return ServerInfo(**response.json().get('data'))
116
+
117
+ @handle_api_error
118
+ def _check_version_compatibility(self) -> None:
119
+ """Check whether Client version is compatible with Fiddler Platform version"""
120
+
121
+ self.client.get(
122
+ url='/v3/version-compatibility',
123
+ params={
124
+ 'client_version': __version__,
125
+ 'client_name': CLIENT_NAME,
126
+ },
127
+ timeout=(5, 15),
128
+ )
129
+
130
+ def _check_server_version(self) -> None:
131
+ """Check whether Fiddler Platform version is compatible with Client version"""
132
+ if match_semver(self.server_version, f'>={MIN_SERVER_VERSION}'):
133
+ return
134
+
135
+ raise IncompatibleClient(server_version=str(self.server_version))
136
+
137
+
138
+ class ConnectionMixin:
139
+ @classmethod
140
+ def _conn(cls) -> Connection:
141
+ """Fiddler connection instance"""
142
+ from fiddler import conn # pylint: disable=import-outside-toplevel
143
+
144
+ assert conn is not None
145
+ return conn
146
+
147
+ @classmethod
148
+ def _client(cls) -> RequestClient:
149
+ """Request client instance"""
150
+ return cls._conn().client
151
+
152
+ @property
153
+ def organization_name(self) -> str:
154
+ """Organization name property"""
155
+ return self._conn().server_info.organization.name
156
+
157
+ @property
158
+ def organization_id(self) -> UUID:
159
+ """Organization id property"""
160
+ return self._conn().server_info.organization.id
161
+
162
+ @classmethod
163
+ def get_organization_name(cls) -> str:
164
+ """Organization name"""
165
+ return cls._conn().server_info.organization.name
166
+
167
+ @classmethod
168
+ def get_organization_id(cls) -> UUID:
169
+ """Organization id"""
170
+ return cls._conn().server_info.organization.id
171
+
172
+
173
+ def init( # pylint: disable=too-many-arguments
174
+ url: str,
175
+ token: str,
176
+ proxies: dict | None = None,
177
+ timeout: float | tuple[float, float] | None = None,
178
+ verify: bool = True,
179
+ validate: bool = True,
180
+ auto_attach_log_handler: bool = True,
181
+ ) -> None:
182
+ """
183
+ Initialize the client.
184
+
185
+ :param url:
186
+ The base URL to your Fiddler platform.
187
+ :param token:
188
+ An authentication token, obtained via the Fiddler UI (can be found on
189
+ the Credentials tab of the Settings page).
190
+ :param proxies:
191
+ A dictionary mapping protocol to the URL of the proxy.
192
+ :param timeout:
193
+ Allows for overriding default HTTP request timeout settings. Applies to
194
+ all HTTP requests emitted by this client. Can be a float or two floats,
195
+ also see
196
+ https://requests.readthedocs.io/en/latest/user/advanced/#timeouts. This
197
+ client library tries to implement meaningful default timeout settings.
198
+ If you find yourself having to set this parameter to address a problem
199
+ please also contact the Fiddler customer support.
200
+ :param verify:
201
+ Can be used to disable server's TLS certificate verification.
202
+ Certificate verification is enabled by default.
203
+ :param validate:
204
+ Whether to validate the server/client version compatibility. Some
205
+ features might not work as expected if this is turned off.
206
+ :param auto_attach_log_handler:
207
+ Defaults to `True`. Can be used to disable the mechanism by which this
208
+ library may attach a stream handler for emitting log messages to stderr
209
+ (see below for further details).
210
+
211
+
212
+ The Fiddler client library will see HTTP API calls fail due to for example
213
+ transient networking issues, temporary backend problems, or as of rate
214
+ limiting errors. These kinds of failures are retryable. It is a sensible
215
+ choice to retry any affected API call after a short waiting period.
216
+ Therefore, this client library implements an automatic retry strategy. Most
217
+ HTTP requests are retried for up to certain amount of time.
218
+
219
+ You can take control of this maximum retry duration by setting the
220
+ environment variable `FIDDLER_CLIENT_RETRY_MAX_DURATION_SECONDS` to a
221
+ numeric value. It currently defaults to 300 seconds which allows for
222
+ auto-healing smaller outages.
223
+
224
+ Note that this client library logs HTTP interaction (and retrying details)
225
+ on INFO level via Python's standard library logging module under the
226
+ 'fiddler' namespace.
227
+
228
+ If you do not configure a root logger in your Python interpreter context
229
+ (done via e.g. `logging.basicConfig()`) then this library automatically
230
+ attaches a handler for its log messages to be emitted on `stderr`. This
231
+ behavior can be disabled by setting `auto_attach_log_handler=False`. For
232
+ fine-grained control, consider configuring handlers and formatters
233
+ yourself.
234
+
235
+ The Fiddler client library has AWS SageMaker partner application
236
+ authentication support. To enable that, install the SageMaker Python SDK
237
+ (`sagemaker` on PyPI). Then, before calling `fiddler.init()` set the
238
+ environment variable AWS_PARTNER_APP_AUTH to 'true' and also set
239
+ AWS_PARTNER_APP_ARN/AWS_PARTNER_APP_URL to meaningful values.
240
+ """
241
+ from fiddler import _set_conn # pylint: disable=import-outside-toplevel
242
+
243
+ # If this library is imported into an interpreter that has a root logger
244
+ # configured (with handler(s) attached) then just propagate log messages
245
+ # into that hierarchy, and do not attach a handler to the 'fiddler' logger.
246
+ if not logging.getLogger().handlers and auto_attach_log_handler:
247
+ fiddler.utils.logger._attach_handler()
248
+ log.info(
249
+ 'attached stderr handler to logger: auto_attach_log_handler=True, and root logger not configured'
250
+ )
251
+
252
+ # Singleton object in Python interpreter.
253
+ conn = Connection(
254
+ url=url,
255
+ token=token,
256
+ proxies=proxies,
257
+ timeout=timeout,
258
+ verify=verify,
259
+ validate=validate,
260
+ )
261
+
262
+ _set_conn(conn_=conn)
@@ -1,6 +1,4 @@
1
1
  CLIENT_NAME = 'python-sdk'
2
- LOGGER_NAME = 'fiddler'
3
- LOG_FORMAT = '%(asctime)s [%(name)s:%(lineno)d] %(levelname)s: %(message)s'
4
2
  TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S.%f'
5
3
 
6
4
  # Headers
@@ -0,0 +1,85 @@
1
+ from functools import wraps
2
+ from http import HTTPStatus
3
+ import logging
4
+ from typing import Any, Callable, TypeVar, cast
5
+
6
+ import requests
7
+ import pydantic.v1
8
+
9
+ from fiddler.exceptions import ApiError, Conflict, HttpError, NotFound, Unsupported
10
+ from fiddler.schemas.response import ErrorResponse
11
+
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ _WrappedFuncType = TypeVar( # pylint: disable=invalid-name
16
+ '_WrappedFuncType', bound=Callable[..., Any]
17
+ )
18
+
19
+
20
+ # ignore: fiddler/decorators.py:19:1: C901 'handle_api_error' is too complex (11)
21
+ def handle_api_error(func: _WrappedFuncType) -> _WrappedFuncType: # noqa: C901
22
+ @wraps(func)
23
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
24
+ try:
25
+ return func(*args, **kwargs)
26
+ except requests.JSONDecodeError as e:
27
+ # This often is premature use of `json()`. Calling code should
28
+ # first check the response for the expected status code, and only
29
+ # then attempt JSON-deserialization.
30
+ raise HttpError(message=f'Invalid JSON response - {e.doc}') # type: ignore
31
+ except requests.HTTPError as http_exc:
32
+ # Note(JP): when we're here it means we got an HTTP response.
33
+ # That's how this exception is documented.
34
+
35
+ status = http_exc.response.status_code
36
+ # The logging levels 'critical' and 'error' are generally meant to
37
+ # be used for terminal / fatal errors. Here, we handle many
38
+ # transient (retryable) errors, and it's fair to log them not as
39
+ # serious as actual errors. Therefore level WARNING and not ERROR.
40
+ # Even INFO might make sense.
41
+ logger.warning(
42
+ '%s HTTP request to %s failed with %s - %s',
43
+ http_exc.request.method,
44
+ getattr(http_exc.request, 'url', 'unknown'),
45
+ status,
46
+ # Not entire response body in case we have a megabyte response.
47
+ getattr(http_exc.response, 'content', 'missing')[:200],
48
+ )
49
+
50
+ # Now, map the error at hand to an exception to be thrown towards
51
+ # the caller.
52
+
53
+ if status == HTTPStatus.METHOD_NOT_ALLOWED:
54
+ raise Unsupported()
55
+
56
+ # Did we get structured error information? This might even
57
+ # be wrapped in a 501 response for example.
58
+ try:
59
+ # https://github.com/fiddler-labs/fiddler/issues/9314
60
+ error_resp = ErrorResponse(**http_exc.response.json())
61
+ except pydantic.v1.ValidationError:
62
+ # We couldn't turn the HTTP error response into an object
63
+ # satisfying model='ErrorResponse'. Now, instead of exposing
64
+ # this to users as a pydantic.ValidationError (which is kinda
65
+ # useless to them) -- just re-raise requests.HTTPError, with
66
+ # all its useful error detail -- it is likely to show the
67
+ # actual problem.
68
+ raise http_exc
69
+ except requests.JSONDecodeError:
70
+ # Re-raise requests.HTTPError, with all its useful error
71
+ # detail.
72
+ raise http_exc
73
+
74
+ # This code path is only reachable if we could successfully
75
+ # deserialize an ErrorResponse object from the HTTP response body.
76
+
77
+ if status == HTTPStatus.CONFLICT:
78
+ raise Conflict(error_resp.error)
79
+
80
+ if status == HTTPStatus.NOT_FOUND:
81
+ raise NotFound(error_resp.error)
82
+
83
+ raise ApiError(error_resp.error)
84
+
85
+ return cast(_WrappedFuncType, wrapper)
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import builtins
4
+ import logging
4
5
  from datetime import datetime
5
6
  from typing import Any, Iterator
6
7
  from uuid import UUID
@@ -15,9 +16,9 @@ from fiddler.entities.model import ModelCompactMixin
15
16
  from fiddler.entities.project import ProjectCompactMixin
16
17
  from fiddler.schemas.alert_rule import AlertRuleResp, NotificationConfig
17
18
  from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
18
- from fiddler.utils.logger import get_logger
19
19
 
20
- logger = get_logger(__name__)
20
+
21
+ logger = logging.getLogger(__name__)
21
22
 
22
23
 
23
24
  class AlertRule(
@@ -235,6 +236,7 @@ class AlertRule(
235
236
  response = self._client().post(
236
237
  url=self._get_url(),
237
238
  data=payload,
239
+ headers={'Content-Type': 'application/json'},
238
240
  )
239
241
 
240
242
  self._refresh_from_response(response=response)
@@ -244,17 +246,17 @@ class AlertRule(
244
246
  def enable_notifications(self) -> None:
245
247
  """Enable notifications for an alert rule"""
246
248
  self._client().patch(
247
- url=self._get_url(id_=self.id), data={'enable_notification': True}
249
+ url=self._get_url(id_=self.id), json={'enable_notification': True}
248
250
  )
249
251
  logger.info(
250
- 'Notifications have been enabled for alert rule with id: %s', self.id
252
+ 'notifications have been enabled for alert rule with id: %s', self.id
251
253
  )
252
254
 
253
255
  @handle_api_error
254
256
  def disable_notifications(self) -> None:
255
257
  """Disable notifications for an alert rule"""
256
258
  self._client().patch(
257
- url=self._get_url(id_=self.id), data={'enable_notification': False}
259
+ url=self._get_url(id_=self.id), json={'enable_notification': False}
258
260
  )
259
261
  logger.info(
260
262
  'Notifications have been disabled for alert rule with id: %s', self.id
@@ -293,6 +295,7 @@ class AlertRule(
293
295
  response = self._client().patch(
294
296
  url=self._get_notification_url(id_=self.id),
295
297
  data=payload,
298
+ headers={'Content-Type': 'application/json'},
296
299
  )
297
300
 
298
301
  return NotificationConfig(**response.json()['data'])
@@ -1,3 +1,5 @@
1
+ # pylint: disable=E1101
2
+ # E1101: Instance of 'FieldInfo' has no 'type' member (no-member)
1
3
  from __future__ import annotations
2
4
 
3
5
  from dataclasses import dataclass
@@ -17,9 +19,7 @@ from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
17
19
  from fiddler.utils.helpers import raise_not_found
18
20
 
19
21
 
20
- class Baseline(
21
- BaseEntity, ModelCompactMixin, ProjectCompactMixin, DatasetCompactMixin
22
- ): # pylint: disable=too-many-instance-attributes
22
+ class Baseline(BaseEntity, ModelCompactMixin, ProjectCompactMixin, DatasetCompactMixin): # pylint: disable=too-many-instance-attributes
23
23
  def __init__( # pylint: disable=too-many-arguments
24
24
  self,
25
25
  name: str,
@@ -219,6 +219,7 @@ class Baseline(
219
219
  response = self._client().post(
220
220
  url=self._get_url(),
221
221
  data=payload,
222
+ headers={'Content-Type': 'application/json'},
222
223
  )
223
224
  self._refresh_from_response(response=response)
224
225
  return self
@@ -173,6 +173,7 @@ class CustomExpression(BaseEntity, ModelCompactMixin, ProjectCompactMixin):
173
173
  response = self._client().post(
174
174
  url=self._get_url(),
175
175
  data=payload,
176
+ headers={'Content-Type': 'application/json'},
176
177
  )
177
178
  self._refresh_from_response(response=response)
178
179
  return self