fiddler-client 3.6.0.dev1__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 (123) hide show
  1. {fiddler_client-3.6.0.dev1/fiddler_client.egg-info → fiddler_client-3.7.0}/PKG-INFO +3 -3
  2. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/PUBLIC.md +2 -2
  3. {fiddler_client-3.6.0.dev1 → 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.dev1 → fiddler_client-3.7.0}/fiddler/__init__.py +1 -1
  6. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/configs.py +4 -4
  7. fiddler_client-3.7.0/fiddler/connection.py +262 -0
  8. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/common.py +0 -2
  9. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/decorators.py +5 -4
  10. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/alert_rule.py +7 -4
  11. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/baseline.py +4 -3
  12. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/custom_expression.py +1 -0
  13. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/events.py +19 -4
  14. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/file.py +15 -8
  15. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/job.py +4 -4
  16. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/model.py +31 -4
  17. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/model_artifact.py +3 -2
  18. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/model_deployment.py +6 -6
  19. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/project.py +19 -1
  20. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/surrogate.py +9 -3
  21. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/webhook.py +6 -1
  22. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/xai.py +19 -7
  23. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/exceptions.py +2 -2
  24. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/libs/aws.py +16 -16
  25. fiddler_client-3.7.0/fiddler/libs/http_client.py +587 -0
  26. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/libs/semver.py +2 -0
  27. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/custom_features.py +1 -0
  28. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/model_spec.py +18 -3
  29. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_alert_record.py +2 -1
  30. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_alert_rule.py +0 -6
  31. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_baseline.py +3 -2
  32. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_dataset.py +3 -2
  33. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_events.py +64 -0
  34. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_files.py +11 -1
  35. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_generate_model.py +3 -2
  36. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model.py +40 -3
  37. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_project.py +58 -2
  38. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_webhook.py +2 -1
  39. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/test_connection.py +0 -2
  40. fiddler_client-3.7.0/fiddler/tests/test_logger.py +61 -0
  41. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/test_sagemaker_auth.py +3 -5
  42. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/decorators.py +2 -2
  43. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/helpers.py +2 -2
  44. fiddler_client-3.7.0/fiddler/utils/logger.py +76 -0
  45. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/model_generator.py +1 -0
  46. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0/fiddler_client.egg-info}/PKG-INFO +3 -3
  47. fiddler_client-3.6.0.dev1/fiddler/VERSION +0 -1
  48. fiddler_client-3.6.0.dev1/fiddler/connection.py +0 -191
  49. fiddler_client-3.6.0.dev1/fiddler/libs/http_client.py +0 -420
  50. fiddler_client-3.6.0.dev1/fiddler/tests/test_logger.py +0 -12
  51. fiddler_client-3.6.0.dev1/fiddler/utils/logger.py +0 -30
  52. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/LICENSE.txt +0 -0
  53. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/MANIFEST.in +0 -0
  54. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/__init__.py +0 -0
  55. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/alert_rule.py +0 -0
  56. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/baseline.py +0 -0
  57. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/dataset.py +0 -0
  58. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/events.py +0 -0
  59. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/job.py +0 -0
  60. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/model.py +0 -0
  61. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/model_deployment.py +0 -0
  62. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/constants/xai.py +0 -0
  63. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/__init__.py +0 -0
  64. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/alert_record.py +0 -0
  65. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/base.py +0 -0
  66. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/dataset.py +0 -0
  67. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/organization.py +0 -0
  68. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/entities/user.py +0 -0
  69. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/libs/__init__.py +0 -0
  70. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/libs/json_encoder.py +0 -0
  71. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/packtools/__init__.py +0 -0
  72. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/packtools/gem.py +0 -0
  73. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/packtools/keras_ig_helpers.py +0 -0
  74. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/packtools/project_attributions_helpers.py +0 -0
  75. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/packtools/template_model.py +0 -0
  76. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/__init__.py +0 -0
  77. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/alert_record.py +0 -0
  78. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/alert_rule.py +0 -0
  79. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/base.py +0 -0
  80. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/baseline.py +0 -0
  81. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/custom_expression.py +0 -0
  82. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/dataset.py +0 -0
  83. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/events.py +0 -0
  84. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/file.py +0 -0
  85. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/filter_query.py +0 -0
  86. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/job.py +0 -0
  87. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/model.py +0 -0
  88. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/model_deployment.py +0 -0
  89. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/model_schema.py +0 -0
  90. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/model_task_params.py +0 -0
  91. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/organization.py +0 -0
  92. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/project.py +0 -0
  93. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/response.py +0 -0
  94. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/server_info.py +0 -0
  95. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/user.py +0 -0
  96. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/webhook.py +0 -0
  97. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/xai.py +0 -0
  98. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/schemas/xai_params.py +0 -0
  99. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/__init__.py +0 -0
  100. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/__init__.py +0 -0
  101. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_custom_metric.py +0 -0
  102. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_job.py +0 -0
  103. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_mixin.py +0 -0
  104. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_artifact.py +0 -0
  105. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_deployment.py +0 -0
  106. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  107. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_segment.py +0 -0
  108. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/apis/test_xai.py +0 -0
  109. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/conftest.py +0 -0
  110. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/constants.py +0 -0
  111. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/test_json_encoder.py +0 -0
  112. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/test_utils.py +0 -0
  113. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/tests/utils.py +0 -0
  114. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/__init__.py +0 -0
  115. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/validations.py +0 -0
  116. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/utils/version.py +0 -0
  117. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler/version.py +0 -0
  118. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler_client.egg-info/SOURCES.txt +0 -0
  119. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler_client.egg-info/dependency_links.txt +0 -0
  120. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler_client.egg-info/requires.txt +0 -0
  121. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/fiddler_client.egg-info/top_level.txt +0 -0
  122. {fiddler_client-3.6.0.dev1 → fiddler_client-3.7.0}/setup.cfg +0 -0
  123. {fiddler_client-3.6.0.dev1 → 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.dev1
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_
@@ -1,10 +1,10 @@
1
- DEFAULT_CONNECTION_TIMEOUT = 60 # In seconds
2
1
  MIN_SERVER_VERSION = '24.4.0'
3
2
  DEFAULT_PAGE_SIZE = 50
4
3
 
5
- # In seconds. For example, this generates a log message every N seconds.
6
- # Was once set to 3, and I think that was too frequent. If this needs to
7
- # be snappier, we can grow the interval.
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
8
  JOB_POLL_INTERVAL = 6
9
9
  JOB_WAIT_TIMEOUT = 1800
10
10
 
@@ -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
@@ -1,15 +1,16 @@
1
1
  from functools import wraps
2
2
  from http import HTTPStatus
3
+ import logging
3
4
  from typing import Any, Callable, TypeVar, cast
4
5
 
5
6
  import requests
6
- import pydantic
7
+ import pydantic.v1
7
8
 
8
9
  from fiddler.exceptions import ApiError, Conflict, HttpError, NotFound, Unsupported
9
10
  from fiddler.schemas.response import ErrorResponse
10
- from fiddler.utils.logger import get_logger
11
11
 
12
- logger = get_logger(__name__)
12
+
13
+ logger = logging.getLogger(__name__)
13
14
 
14
15
  _WrappedFuncType = TypeVar( # pylint: disable=invalid-name
15
16
  '_WrappedFuncType', bound=Callable[..., Any]
@@ -57,7 +58,7 @@ def handle_api_error(func: _WrappedFuncType) -> _WrappedFuncType: # noqa: C901
57
58
  try:
58
59
  # https://github.com/fiddler-labs/fiddler/issues/9314
59
60
  error_resp = ErrorResponse(**http_exc.response.json())
60
- except pydantic.ValidationError:
61
+ except pydantic.v1.ValidationError:
61
62
  # We couldn't turn the HTTP error response into an object
62
63
  # satisfying model='ErrorResponse'. Now, instead of exposing
63
64
  # this to users as a pydantic.ValidationError (which is kinda
@@ -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,7 +246,7 @@ 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
252
  'notifications have been enabled for alert rule with id: %s', self.id
@@ -254,7 +256,7 @@ class AlertRule(
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
@@ -5,6 +5,7 @@ import tempfile
5
5
  from pathlib import Path
6
6
  from typing import Any, Callable
7
7
  from uuid import UUID
8
+ import logging
8
9
 
9
10
  import pandas as pd
10
11
  from requests import Response
@@ -18,9 +19,8 @@ from fiddler.entities.job import Job
18
19
  from fiddler.schemas.dataset import EnvType
19
20
  from fiddler.schemas.events import EventsSource, FileSource
20
21
  from fiddler.schemas.job import JobCompactResp
21
- from fiddler.utils.logger import get_logger
22
22
 
23
- logger = get_logger(__name__)
23
+ logger = logging.getLogger(__name__)
24
24
 
25
25
 
26
26
  class EventPublisher(ConnectionMixin):
@@ -98,9 +98,10 @@ class EventPublisher(ConnectionMixin):
98
98
  temp_file.close()
99
99
  return job
100
100
 
101
- except Exception:
101
+ except Exception as exc: # pylint: disable=broad-exception-caught
102
102
  logger.warning(
103
- 'Failed to convert input dataframe to parquet format. Retrying as a CSV file.'
103
+ 'Failed to convert input dataframe to parquet format. Retrying as a CSV file. Errors was: %s',
104
+ exc,
104
105
  )
105
106
 
106
107
  finally:
@@ -147,8 +148,12 @@ class EventPublisher(ConnectionMixin):
147
148
  dataset_name: str | None = None,
148
149
  update: bool = False,
149
150
  ) -> Job:
151
+ # This is meant to perform internal HTTP request retrying (is
152
+ # retry-safe).
150
153
  file = File(path=Path(source)).upload()
151
154
 
155
+ # What does it mean for `file.id` to be None? Note that sometimes a
156
+ # Python program is executed 'optimized' with assertions removed.
152
157
  assert file.id is not None
153
158
 
154
159
  response = self._publish_call(
@@ -157,6 +162,7 @@ class EventPublisher(ConnectionMixin):
157
162
  dataset_name=dataset_name,
158
163
  update=update,
159
164
  )
165
+
160
166
  job_compact = JobCompactResp(**response.json()['data']['job'])
161
167
  return Job.get(id_=job_compact.id)
162
168
 
@@ -171,6 +177,14 @@ class EventPublisher(ConnectionMixin):
171
177
  method = self._client().patch
172
178
  else:
173
179
  method = self._client().post
180
+
181
+ # TODO: Note(JP): we have to make this retry-safer in the backend by
182
+ # deduplicating on request body contents/hash. So that in the rare case
183
+ # when a retry is performed accidentally (non-authoritative error, such
184
+ # as a timeout error waiting for a resp) the backend does detect the
185
+ # duplication, and rejects the request with a conflict error (and the
186
+ # retry logic in the client must expect a conflict error upon attempts
187
+ # 2+, and should interpret such error as success).
174
188
  return method(
175
189
  url='/v3/events',
176
190
  data={
@@ -179,4 +193,5 @@ class EventPublisher(ConnectionMixin):
179
193
  'env_type': environment,
180
194
  'env_name': dataset_name,
181
195
  },
196
+ headers={'Content-Type': 'application/json'},
182
197
  )