splitio-client 10.6.0__tar.gz → 10.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 (133) hide show
  1. splitio_client-10.6.0/LICENSE.txt → splitio_client-10.7.0/LICENSE +34 -1
  2. splitio_client-10.6.0/NOTICE.txt → splitio_client-10.7.0/NOTICE +2 -2
  3. {splitio_client-10.6.0 → splitio_client-10.7.0}/PKG-INFO +4 -4
  4. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/client.py +26 -14
  5. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/splits.py +17 -11
  6. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/config.py +39 -10
  7. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/factory.py +15 -6
  8. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/evaluator.py +7 -1
  9. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/adapters.py +8 -8
  10. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/events_delivery.py +2 -2
  11. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/events_manager_config.py +2 -5
  12. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/events.py +0 -2
  13. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/manager.py +7 -4
  14. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/splitsse.py +9 -4
  15. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/sse.py +51 -13
  16. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/pluggable.py +2 -5
  17. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/redis.py +2 -2
  18. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/manager.py +7 -4
  19. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/synchronizer.py +2 -2
  20. splitio_client-10.7.0/splitio/version.py +1 -0
  21. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio_client.egg-info/PKG-INFO +4 -4
  22. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio_client.egg-info/SOURCES.txt +2 -2
  23. splitio_client-10.6.0/splitio/version.py +0 -1
  24. {splitio_client-10.6.0 → splitio_client-10.7.0}/README.md +0 -0
  25. {splitio_client-10.6.0 → splitio_client-10.7.0}/setup.cfg +0 -0
  26. {splitio_client-10.6.0 → splitio_client-10.7.0}/setup.py +0 -0
  27. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/__init__.py +0 -0
  28. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/__init__.py +0 -0
  29. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/auth.py +0 -0
  30. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/commons.py +0 -0
  31. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/events.py +0 -0
  32. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/impressions.py +0 -0
  33. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/segments.py +0 -0
  34. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/api/telemetry.py +0 -0
  35. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/__init__.py +0 -0
  36. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/client.py +0 -0
  37. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/input_validator.py +0 -0
  38. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/key.py +0 -0
  39. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/listener.py +0 -0
  40. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/localhost.py +0 -0
  41. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/manager.py +0 -0
  42. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/client/util.py +0 -0
  43. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/__init__.py +0 -0
  44. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/cache/__init__.py +0 -0
  45. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/cache/lru.py +0 -0
  46. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/filters.py +0 -0
  47. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/hashfns/__init__.py +0 -0
  48. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/hashfns/legacy.py +0 -0
  49. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/hashfns/murmur3py.py +0 -0
  50. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/__init__.py +0 -0
  51. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/impressions.py +0 -0
  52. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/manager.py +0 -0
  53. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/strategies.py +0 -0
  54. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/impressions/unique_keys_tracker.py +0 -0
  55. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/splitters.py +0 -0
  56. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/engine/telemetry.py +0 -0
  57. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/__init__.py +0 -0
  58. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/events_manager.py +0 -0
  59. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/events_metadata.py +0 -0
  60. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/events/events_task.py +0 -0
  61. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/exceptions.py +0 -0
  62. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/factories.py +0 -0
  63. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/impressions.py +0 -0
  64. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/key.py +0 -0
  65. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/__init__.py +0 -0
  66. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/datatypes.py +0 -0
  67. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/fallback_config.py +0 -0
  68. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/fallback_treatment.py +0 -0
  69. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/__init__.py +0 -0
  70. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/condition.py +0 -0
  71. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/__init__.py +0 -0
  72. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/base.py +0 -0
  73. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/keys.py +0 -0
  74. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/misc.py +0 -0
  75. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/numeric.py +0 -0
  76. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/prerequisites.py +0 -0
  77. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/rule_based_segment.py +0 -0
  78. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/semver.py +0 -0
  79. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/sets.py +0 -0
  80. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/string.py +0 -0
  81. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/utils/__init__.py +0 -0
  82. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/matchers/utils/utils.py +0 -0
  83. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/grammar/partitions.py +0 -0
  84. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/impressions.py +0 -0
  85. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/notification.py +0 -0
  86. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/rule_based_segments.py +0 -0
  87. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/segments.py +0 -0
  88. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/splits.py +0 -0
  89. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/telemetry.py +0 -0
  90. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/models/token.py +0 -0
  91. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/optional/__init__.py +0 -0
  92. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/optional/loaders.py +0 -0
  93. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/__init__.py +0 -0
  94. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/parser.py +0 -0
  95. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/processor.py +0 -0
  96. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/status_tracker.py +0 -0
  97. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/push/workers.py +0 -0
  98. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/recorder/__init__.py +0 -0
  99. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/recorder/recorder.py +0 -0
  100. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/spec.py +0 -0
  101. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/__init__.py +0 -0
  102. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/adapters/__init__.py +0 -0
  103. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/adapters/cache_trait.py +0 -0
  104. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/adapters/redis.py +0 -0
  105. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/adapters/util.py +0 -0
  106. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/storage/inmemmory.py +0 -0
  107. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/__init__.py +0 -0
  108. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/event.py +0 -0
  109. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/impression.py +0 -0
  110. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/segment.py +0 -0
  111. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/split.py +0 -0
  112. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/telemetry.py +0 -0
  113. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/unique_keys.py +0 -0
  114. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/sync/util.py +0 -0
  115. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/__init__.py +0 -0
  116. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/events_sync.py +0 -0
  117. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/impressions_sync.py +0 -0
  118. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/segment_sync.py +0 -0
  119. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/split_sync.py +0 -0
  120. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/telemetry_sync.py +0 -0
  121. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/unique_keys_sync.py +0 -0
  122. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/util/__init__.py +0 -0
  123. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/util/asynctask.py +0 -0
  124. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/tasks/util/workerpool.py +0 -0
  125. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/__init__.py +0 -0
  126. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/backoff.py +0 -0
  127. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/decorators.py +0 -0
  128. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/storage_helper.py +0 -0
  129. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/threadutil.py +0 -0
  130. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio/util/time.py +0 -0
  131. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio_client.egg-info/dependency_links.txt +0 -0
  132. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio_client.egg-info/requires.txt +0 -0
  133. {splitio_client-10.6.0 → splitio_client-10.7.0}/splitio_client.egg-info/top_level.txt +0 -0
@@ -1,12 +1,18 @@
1
- Apache License
1
+
2
+ Apache License
2
3
  Version 2.0, January 2004
3
4
  http://www.apache.org/licenses/
5
+
4
6
  TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
5
8
  1. Definitions.
9
+
6
10
  "License" shall mean the terms and conditions for use, reproduction,
7
11
  and distribution as defined by Sections 1 through 9 of this document.
12
+
8
13
  "Licensor" shall mean the copyright owner or entity authorized by
9
14
  the copyright owner that is granting the License.
15
+
10
16
  "Legal Entity" shall mean the union of the acting entity and all
11
17
  other entities that control, are controlled by, or are under common
12
18
  control with that entity. For the purposes of this definition,
@@ -14,19 +20,24 @@ Apache License
14
20
  direction or management of such entity, whether by contract or
15
21
  otherwise, or (ii) ownership of fifty percent (50%) or more of the
16
22
  outstanding shares, or (iii) beneficial ownership of such entity.
23
+
17
24
  "You" (or "Your") shall mean an individual or Legal Entity
18
25
  exercising permissions granted by this License.
26
+
19
27
  "Source" form shall mean the preferred form for making modifications,
20
28
  including but not limited to software source code, documentation
21
29
  source, and configuration files.
30
+
22
31
  "Object" form shall mean any form resulting from mechanical
23
32
  transformation or translation of a Source form, including but
24
33
  not limited to compiled object code, generated documentation,
25
34
  and conversions to other media types.
35
+
26
36
  "Work" shall mean the work of authorship, whether in Source or
27
37
  Object form, made available under the License, as indicated by a
28
38
  copyright notice that is included in or attached to the work
29
39
  (an example is provided in the Appendix below).
40
+
30
41
  "Derivative Works" shall mean any work, whether in Source or Object
31
42
  form, that is based on (or derived from) the Work and for which the
32
43
  editorial revisions, annotations, elaborations, or other modifications
@@ -34,6 +45,7 @@ Apache License
34
45
  of this License, Derivative Works shall not include works that remain
35
46
  separable from, or merely link (or bind by name) to the interfaces of,
36
47
  the Work and Derivative Works thereof.
48
+
37
49
  "Contribution" shall mean any work of authorship, including
38
50
  the original version of the Work and any modifications or additions
39
51
  to that Work or Derivative Works thereof, that is intentionally
@@ -47,15 +59,18 @@ Apache License
47
59
  Licensor for the purpose of discussing and improving the Work, but
48
60
  excluding communication that is conspicuously marked or otherwise
49
61
  designated in writing by the copyright owner as "Not a Contribution."
62
+
50
63
  "Contributor" shall mean Licensor and any individual or Legal Entity
51
64
  on behalf of whom a Contribution has been received by Licensor and
52
65
  subsequently incorporated within the Work.
66
+
53
67
  2. Grant of Copyright License. Subject to the terms and conditions of
54
68
  this License, each Contributor hereby grants to You a perpetual,
55
69
  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
56
70
  copyright license to reproduce, prepare Derivative Works of,
57
71
  publicly display, publicly perform, sublicense, and distribute the
58
72
  Work and such Derivative Works in Source or Object form.
73
+
59
74
  3. Grant of Patent License. Subject to the terms and conditions of
60
75
  this License, each Contributor hereby grants to You a perpetual,
61
76
  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
@@ -71,19 +86,24 @@ Apache License
71
86
  or contributory patent infringement, then any patent licenses
72
87
  granted to You under this License for that Work shall terminate
73
88
  as of the date such litigation is filed.
89
+
74
90
  4. Redistribution. You may reproduce and distribute copies of the
75
91
  Work or Derivative Works thereof in any medium, with or without
76
92
  modifications, and in Source or Object form, provided that You
77
93
  meet the following conditions:
94
+
78
95
  (a) You must give any other recipients of the Work or
79
96
  Derivative Works a copy of this License; and
97
+
80
98
  (b) You must cause any modified files to carry prominent notices
81
99
  stating that You changed the files; and
100
+
82
101
  (c) You must retain, in the Source form of any Derivative Works
83
102
  that You distribute, all copyright, patent, trademark, and
84
103
  attribution notices from the Source form of the Work,
85
104
  excluding those notices that do not pertain to any part of
86
105
  the Derivative Works; and
106
+
87
107
  (d) If the Work includes a "NOTICE" text file as part of its
88
108
  distribution, then any Derivative Works that You distribute must
89
109
  include a readable copy of the attribution notices contained
@@ -100,12 +120,14 @@ Apache License
100
120
  or as an addendum to the NOTICE text from the Work, provided
101
121
  that such additional attribution notices cannot be construed
102
122
  as modifying the License.
123
+
103
124
  You may add Your own copyright statement to Your modifications and
104
125
  may provide additional or different license terms and conditions
105
126
  for use, reproduction, or distribution of Your modifications, or
106
127
  for any such Derivative Works as a whole, provided Your use,
107
128
  reproduction, and distribution of the Work otherwise complies with
108
129
  the conditions stated in this License.
130
+
109
131
  5. Submission of Contributions. Unless You explicitly state otherwise,
110
132
  any Contribution intentionally submitted for inclusion in the Work
111
133
  by You to the Licensor shall be under the terms and conditions of
@@ -113,10 +135,12 @@ Apache License
113
135
  Notwithstanding the above, nothing herein shall supersede or modify
114
136
  the terms of any separate license agreement you may have executed
115
137
  with Licensor regarding such Contributions.
138
+
116
139
  6. Trademarks. This License does not grant permission to use the trade
117
140
  names, trademarks, service marks, or product names of the Licensor,
118
141
  except as required for reasonable and customary use in describing the
119
142
  origin of the Work and reproducing the content of the NOTICE file.
143
+
120
144
  7. Disclaimer of Warranty. Unless required by applicable law or
121
145
  agreed to in writing, Licensor provides the Work (and each
122
146
  Contributor provides its Contributions) on an "AS IS" BASIS,
@@ -126,6 +150,7 @@ Apache License
126
150
  PARTICULAR PURPOSE. You are solely responsible for determining the
127
151
  appropriateness of using or redistributing the Work and assume any
128
152
  risks associated with Your exercise of permissions under this License.
153
+
129
154
  8. Limitation of Liability. In no event and under no legal theory,
130
155
  whether in tort (including negligence), contract, or otherwise,
131
156
  unless required by applicable law (such as deliberate and grossly
@@ -137,6 +162,7 @@ Apache License
137
162
  work stoppage, computer failure or malfunction, or any and all
138
163
  other commercial damages or losses), even if such Contributor
139
164
  has been advised of the possibility of such damages.
165
+
140
166
  9. Accepting Warranty or Additional Liability. While redistributing
141
167
  the Work or Derivative Works thereof, You may choose to offer,
142
168
  and charge a fee for, acceptance of support, warranty, indemnity,
@@ -147,8 +173,11 @@ Apache License
147
173
  defend, and hold each Contributor harmless for any liability
148
174
  incurred by, or claims asserted against, such Contributor by reason
149
175
  of your accepting any such warranty or additional liability.
176
+
150
177
  END OF TERMS AND CONDITIONS
178
+
151
179
  APPENDIX: How to apply the Apache License to your work.
180
+
152
181
  To apply the Apache License to your work, attach the following
153
182
  boilerplate notice, with the fields enclosed by brackets "[]"
154
183
  replaced with your own identifying information. (Don't include
@@ -157,11 +186,15 @@ Apache License
157
186
  file or class name and description of purpose be included on the
158
187
  same "printed page" as the copyright notice for easier
159
188
  identification within third-party archives.
189
+
160
190
  Copyright [yyyy] [name of copyright owner]
191
+
161
192
  Licensed under the Apache License, Version 2.0 (the "License");
162
193
  you may not use this file except in compliance with the License.
163
194
  You may obtain a copy of the License at
195
+
164
196
  http://www.apache.org/licenses/LICENSE-2.0
197
+
165
198
  Unless required by applicable law or agreed to in writing, software
166
199
  distributed under the License is distributed on an "AS IS" BASIS,
167
200
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -1,5 +1,5 @@
1
- Harness Feature Management JavaScript SDK Copyright 2024-2026 Harness Inc.
1
+ Harness Feature Management Python SDK Copyright 2024-2026 Harness Inc.
2
2
 
3
3
  This product includes software developed at Harness Inc. (https://harness.io/).
4
4
 
5
- This product includes software originally developed by Split Software, Inc. (https://www.split.io/). Copyright 2015-2024 Split Software, Inc.
5
+ This product includes software originally developed by Split Software, Inc. (https://www.split.io/). Copyright 2016-2024 Split Software, Inc.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splitio_client
3
- Version: 10.6.0
3
+ Version: 10.7.0
4
4
  Summary: Split.io Python Client
5
5
  Home-page: https://github.com/splitio/python-client
6
- Download-URL: https://github.com/splitio/python-client/tarball/10.6.0
6
+ Download-URL: https://github.com/splitio/python-client/tarball/10.7.0
7
7
  Author: Patricio Echague, Sebastian Arrubia
8
8
  Author-email: pato@split.io, sebastian@split.io
9
9
  License: Apache License 2.0
@@ -20,8 +20,8 @@ Provides-Extra: uwsgi
20
20
  Provides-Extra: cpphash
21
21
  Provides-Extra: asyncio
22
22
  Provides-Extra: kerberos
23
- License-File: LICENSE.txt
24
- License-File: NOTICE.txt
23
+ License-File: LICENSE
24
+ License-File: NOTICE
25
25
 
26
26
  # Split Python SDK
27
27
  ![Build Status](https://github.com/splitio/python-client/actions/workflows/ci.yml/badge.svg?branch=master)
@@ -92,7 +92,7 @@ class HTTPAdapterWithProxyKerberosAuth(requests.adapters.HTTPAdapter):
92
92
  class HttpClientBase(object, metaclass=abc.ABCMeta):
93
93
  """HttpClient wrapper template."""
94
94
 
95
- def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None):
95
+ def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None, proxies={}):
96
96
  """
97
97
  Class constructor.
98
98
 
@@ -110,6 +110,7 @@ class HttpClientBase(object, metaclass=abc.ABCMeta):
110
110
  _LOGGER.debug("Initializing httpclient")
111
111
  self._timeout = timeout/1000 if timeout else None # Convert ms to seconds.
112
112
  self._urls = _construct_urls(sdk_url, events_url, auth_url, telemetry_url)
113
+ self._proxies = proxies
113
114
 
114
115
  @abc.abstractmethod
115
116
  def get(self, server, path, apikey):
@@ -161,7 +162,7 @@ class HttpClientBase(object, metaclass=abc.ABCMeta):
161
162
  class HttpClient(HttpClientBase):
162
163
  """HttpClient wrapper."""
163
164
 
164
- def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None):
165
+ def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None, proxies={}):
165
166
  """
166
167
  Class constructor.
167
168
 
@@ -176,8 +177,8 @@ class HttpClient(HttpClientBase):
176
177
  :param telemetry_url: Optional alternative telemetry URL.
177
178
  :type telemetry_url: str
178
179
  """
179
- HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url)
180
-
180
+ HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url, proxies)
181
+
181
182
  def get(self, server, path, sdk_key, query=None, extra_headers=None): # pylint: disable=too-many-arguments
182
183
  """
183
184
  Issue a get request.
@@ -197,21 +198,24 @@ class HttpClient(HttpClientBase):
197
198
  :rtype: HttpResponse
198
199
  """
199
200
  start = get_current_epoch_time_ms()
201
+ if self._proxies.get('https'):
202
+ _LOGGER.debug("proxy %s", urllib.parse.urlsplit(self._proxies['https']).hostname)
200
203
  try:
201
204
  response = requests.get(
202
205
  _build_url(server, path, self._urls),
203
206
  params=query,
204
207
  headers=self._get_headers(extra_headers, sdk_key),
205
- timeout=self._timeout
208
+ timeout=self._timeout,
209
+ proxies=self._proxies
206
210
  )
207
211
  self._record_telemetry(response.status_code, get_current_epoch_time_ms() - start)
208
212
  return HttpResponse(response.status_code, response.text, response.headers)
209
213
 
210
214
  except requests.exceptions.ChunkedEncodingError as exc:
211
215
  _LOGGER.error("IncompleteRead exception detected: %s", exc)
212
- return HttpResponse(400, "", {})
213
-
214
- except Exception as exc: # pylint: disable=broad-except
216
+ return HttpResponse(400, "", {})
217
+
218
+ except Exception as exc: # pylint: disable=broad-except
215
219
  raise HttpClientException(_EXC_MSG.format(source='request')) from exc
216
220
 
217
221
  def post(self, server, path, sdk_key, body, query=None, extra_headers=None): # pylint: disable=too-many-arguments
@@ -242,6 +246,7 @@ class HttpClient(HttpClientBase):
242
246
  params=query,
243
247
  headers=self._get_headers(extra_headers, sdk_key),
244
248
  timeout=self._timeout,
249
+ proxies=self._proxies
245
250
  )
246
251
  self._record_telemetry(response.status_code, get_current_epoch_time_ms() - start)
247
252
  return HttpResponse(response.status_code, response.text, response.headers)
@@ -251,7 +256,7 @@ class HttpClient(HttpClientBase):
251
256
  class HttpClientAsync(HttpClientBase):
252
257
  """HttpClientAsync wrapper."""
253
258
 
254
- def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None):
259
+ def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None, proxies={}):
255
260
  """
256
261
  Class constructor.
257
262
  :param timeout: How many milliseconds to wait until the server responds.
@@ -265,8 +270,12 @@ class HttpClientAsync(HttpClientBase):
265
270
  :param telemetry_url: Optional alternative telemetry URL.
266
271
  :type telemetry_url: str
267
272
  """
268
- HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url)
273
+ HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url, proxies)
269
274
  self._session = aiohttp.ClientSession()
275
+ self._proxy = None
276
+ if len(self._proxies) > 0:
277
+ http_key = next(iter(self._proxies))
278
+ self._proxy = self._proxies[http_key]
270
279
 
271
280
  async def get(self, server, path, apikey, query=None, extra_headers=None): # pylint: disable=too-many-arguments
272
281
  """
@@ -291,11 +300,13 @@ class HttpClientAsync(HttpClientBase):
291
300
  _LOGGER.debug("GET request: %s", url)
292
301
  _LOGGER.debug("query params: %s", query)
293
302
  _LOGGER.debug("headers: %s", headers)
303
+ _LOGGER.debug("proxy: %s", urllib.parse.urlsplit(self._proxy).hostname)
294
304
  async with self._session.get(
295
305
  url,
296
306
  params=query,
297
307
  headers=headers,
298
- timeout=self._timeout
308
+ timeout=self._timeout,
309
+ proxy=self._proxy
299
310
  ) as response:
300
311
  body = await response.text()
301
312
  _LOGGER.debug("Response:")
@@ -306,8 +317,8 @@ class HttpClientAsync(HttpClientBase):
306
317
 
307
318
  except aiohttp.ClientPayloadError as exc:
308
319
  _LOGGER.error("ContentLengthError exception detected: %s", exc)
309
- return HttpResponse(400, "", {})
310
-
320
+ return HttpResponse(400, "", {})
321
+
311
322
  except aiohttp.ClientError as exc: # pylint: disable=broad-except
312
323
  raise HttpClientException(_EXC_MSG.format(source='aiohttp')) from exc
313
324
 
@@ -343,7 +354,8 @@ class HttpClientAsync(HttpClientBase):
343
354
  params=query,
344
355
  headers=headers,
345
356
  json=body,
346
- timeout=self._timeout
357
+ timeout=self._timeout,
358
+ proxy=self._proxy
347
359
  ) as response:
348
360
  body = await response.text()
349
361
  _LOGGER.debug("Response:")
@@ -104,24 +104,27 @@ class SplitsAPI(SplitsAPIBase): # pylint: disable=too-few-public-methods
104
104
  if 200 <= response.status_code < 300:
105
105
  if self._spec_version == _SPEC_1_1:
106
106
  return util.convert_to_new_spec(json.loads(response.body))
107
-
107
+
108
108
  self.clear_storage = self._last_proxy_check_timestamp != 0
109
109
  self._last_proxy_check_timestamp = 0
110
- return json.loads(response.body)
110
+ parsed = json.loads(response.body)
111
+ if 'rbs' not in parsed:
112
+ parsed['rbs'] = {"d": [], "s": -1, "t": -1}
113
+ return parsed
111
114
 
112
115
  else:
113
116
  if response.status_code == 414:
114
117
  _LOGGER.error('Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error.')
115
-
118
+
116
119
  if self._client.is_sdk_endpoint_overridden() and response.status_code == 400 and self._spec_version == SPEC_VERSION:
117
120
  _LOGGER.warning('Detected proxy response error, changing spec version from %s to %s and re-fetching.', self._spec_version, _SPEC_1_1)
118
121
  self._spec_version = _SPEC_1_1
119
- self._last_proxy_check_timestamp = utctime_ms()
122
+ self._last_proxy_check_timestamp = utctime_ms()
120
123
  return self.fetch_splits(change_number, None, FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
121
124
  None, fetch_options.sets, self._spec_version))
122
-
125
+
123
126
  raise APIException(response.body, response.status_code)
124
-
127
+
125
128
  except HttpClientException as exc:
126
129
  _LOGGER.error('Error fetching feature flags because an exception was raised by the HTTPClient')
127
130
  _LOGGER.debug('Error: ', exc_info=True)
@@ -178,24 +181,27 @@ class SplitsAPIAsync(SplitsAPIBase): # pylint: disable=too-few-public-methods
178
181
  if 200 <= response.status_code < 300:
179
182
  if self._spec_version == _SPEC_1_1:
180
183
  return util.convert_to_new_spec(json.loads(response.body))
181
-
184
+
182
185
  self.clear_storage = self._last_proxy_check_timestamp != 0
183
186
  self._last_proxy_check_timestamp = 0
184
- return json.loads(response.body)
187
+ parsed = json.loads(response.body)
188
+ if 'rbs' not in parsed:
189
+ parsed['rbs'] = {"d": [], "s": -1, "t": -1}
190
+ return parsed
185
191
 
186
192
  else:
187
193
  if response.status_code == 414:
188
194
  _LOGGER.error('Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error.')
189
-
195
+
190
196
  if self._client.is_sdk_endpoint_overridden() and response.status_code == 400 and self._spec_version == SPEC_VERSION:
191
197
  _LOGGER.warning('Detected proxy response error, changing spec version from %s to %s and re-fetching.', self._spec_version, _SPEC_1_1)
192
198
  self._spec_version = _SPEC_1_1
193
- self._last_proxy_check_timestamp = utctime_ms()
199
+ self._last_proxy_check_timestamp = utctime_ms()
194
200
  return await self.fetch_splits(change_number, None, FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
195
201
  None, fetch_options.sets, self._spec_version))
196
202
 
197
203
  raise APIException(response.body, response.status_code)
198
-
204
+
199
205
  except HttpClientException as exc:
200
206
  _LOGGER.error('Error fetching feature flags because an exception was raised by the HTTPClient')
201
207
  _LOGGER.debug('Error: ', exc_info=True)
@@ -2,6 +2,7 @@
2
2
  import os.path
3
3
  import logging
4
4
  from enum import Enum
5
+ from urllib.parse import urlsplit
5
6
 
6
7
  from splitio.engine.impressions import ImpressionsMode
7
8
  from splitio.client.input_validator import validate_flag_sets, validate_fallback_treatment, validate_regex_name
@@ -71,7 +72,8 @@ DEFAULT_CONFIG = {
71
72
  'httpAuthenticateScheme': AuthenticateScheme.NONE,
72
73
  'kerberosPrincipalUser': None,
73
74
  'kerberosPrincipalPassword': None,
74
- 'fallbackTreatments': FallbackTreatmentsConfiguration(None)
75
+ 'fallbackTreatments': FallbackTreatmentsConfiguration(None),
76
+ 'proxyUrl': None,
75
77
  }
76
78
 
77
79
  def _parse_operation_mode(sdk_key, config):
@@ -170,38 +172,65 @@ def sanitize(sdk_key, config):
170
172
  ' Defaulting to `none` mode.')
171
173
  processed["httpAuthenticateScheme"] = authenticate_scheme
172
174
 
173
- processed = _sanitize_fallback_config(config, processed)
174
-
175
+ processed = _sanitize_fallback_config(config, processed)
176
+
175
177
  if config.get("redisErrors") is not None:
176
178
  _LOGGER.warning('Parameter `redisErrors` is deprecated as it is no longer supported in redis lib.' \
177
179
  ' Will ignore this value.')
178
-
179
180
  processed["redisErrors"] = None
181
+
182
+ processed = _sanitize_proxy(config, processed)
183
+
180
184
  return processed
181
185
 
186
+ def _sanitize_proxy(config, processed):
187
+ if config.get("proxyUrl") is None:
188
+ return processed
189
+
190
+ if not isinstance(config.get("proxyUrl"), str):
191
+ _LOGGER.warning('Config: proxyUrl parameter must be of type str.')
192
+ processed["proxyUrl"] = None
193
+ return processed
194
+
195
+ try:
196
+ parsed = urlsplit(config.get("proxyUrl"))
197
+ if parsed.hostname is None:
198
+ _LOGGER.warning('Config: could not parse hostname from proxyUrl parameter.')
199
+ processed["proxyUrl"] = None
200
+ return processed
201
+
202
+ if parsed.port is not None:
203
+ p = int(parsed.port)
204
+ except Exception:
205
+ _LOGGER.warning('Config: proxy hostname should be a valid hostname and proxy port should be of int type.')
206
+ processed["proxyUrl"] = None
207
+ return processed
208
+
209
+ return processed
210
+
182
211
  def _sanitize_fallback_config(config, processed):
183
212
  if config.get('fallbackTreatments') is None:
184
213
  return processed
185
-
214
+
186
215
  if not isinstance(config['fallbackTreatments'], FallbackTreatmentsConfiguration):
187
216
  _LOGGER.warning('Config: fallbackTreatments parameter should be of `FallbackTreatmentsConfiguration` class.')
188
217
  processed['fallbackTreatments'] = None
189
- return processed
190
-
218
+ return processed
219
+
191
220
  sanitized_global_fallback_treatment = config['fallbackTreatments'].global_fallback_treatment
192
221
  if config['fallbackTreatments'].global_fallback_treatment is not None and not validate_fallback_treatment(config['fallbackTreatments'].global_fallback_treatment):
193
222
  _LOGGER.warning('Config: global fallbacktreatment parameter is discarded.')
194
223
  sanitized_global_fallback_treatment = None
195
-
224
+
196
225
  sanitized_flag_fallback_treatments = {}
197
226
  if config['fallbackTreatments'].by_flag_fallback_treatment is not None:
198
227
  for feature_name in config['fallbackTreatments'].by_flag_fallback_treatment.keys():
199
228
  if not validate_regex_name(feature_name) or not validate_fallback_treatment(config['fallbackTreatments'].by_flag_fallback_treatment[feature_name]):
200
229
  _LOGGER.warning('Config: fallback treatment parameter for feature flag %s is discarded.', feature_name)
201
230
  continue
202
-
231
+
203
232
  sanitized_flag_fallback_treatments[feature_name] = config['fallbackTreatments'].by_flag_fallback_treatment[feature_name]
204
233
 
205
234
  processed['fallbackTreatments'] = FallbackTreatmentsConfiguration(sanitized_global_fallback_treatment, sanitized_flag_fallback_treatments)
206
235
 
207
- return processed
236
+ return processed
@@ -3,6 +3,7 @@ import logging
3
3
  import threading
4
4
  from collections import Counter
5
5
  from enum import Enum
6
+ from urllib.parse import urlparse
6
7
  import queue
7
8
 
8
9
  from splitio.optional.loaders import asyncio
@@ -284,7 +285,6 @@ class SplitFactory(SplitFactoryBase): # pylint: disable=too-many-instance-attri
284
285
 
285
286
  if not ready:
286
287
  self._telemetry_init_producer.record_bur_time_out()
287
- self._internal_events_queue.put(SdkInternalEventNotification(SdkInternalEvent.SDK_TIMED_OUT, None))
288
288
  raise TimeoutException('SDK Initialization: time of %d exceeded' % timeout)
289
289
 
290
290
  def destroy(self, destroyed_event=None):
@@ -439,7 +439,6 @@ class SplitFactoryAsync(SplitFactoryBase): # pylint: disable=too-many-instance-
439
439
  _LOGGER.error("Exception initializing SDK")
440
440
  _LOGGER.debug(str(e))
441
441
  await self._telemetry_init_producer.record_bur_time_out()
442
- await self._internal_events_queue.put(SdkInternalEventNotification(SdkInternalEvent.SDK_TIMED_OUT, None))
443
442
  raise TimeoutException('SDK Initialization: time of %d exceeded' % timeout)
444
443
 
445
444
  async def destroy(self, destroyed_event=None):
@@ -552,12 +551,18 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
552
551
  authentication_params = authentication_params
553
552
  )
554
553
  else:
554
+ proxies = {}
555
+ if cfg.get('proxyUrl'):
556
+ proxies['https'] = cfg.get("proxyUrl")
557
+ proxies['http'] = cfg.get("proxyUrl")
558
+
555
559
  http_client = HttpClient(
556
560
  sdk_url=sdk_url,
557
561
  events_url=events_url,
558
562
  auth_url=auth_api_base_url,
559
563
  telemetry_url=telemetry_api_base_url,
560
564
  timeout=cfg.get('connectionTimeout'),
565
+ proxies=proxies
561
566
  )
562
567
 
563
568
  sdk_metadata = util.get_metadata(cfg)
@@ -631,7 +636,7 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
631
636
 
632
637
  sdk_ready_flag = threading.Event() if not preforked_initialization else None
633
638
  manager = Manager(sdk_ready_flag, synchronizer, apis['auth'], cfg['streamingEnabled'],
634
- sdk_metadata, telemetry_runtime_producer, streaming_api_base_url, api_key[-4:])
639
+ sdk_metadata, telemetry_runtime_producer, streaming_api_base_url, api_key[-4:], cfg.get('proxyUrl'))
635
640
 
636
641
  storages['events'].set_queue_full_hook(tasks.events_task.flush)
637
642
  storages['impressions'].set_queue_full_hook(tasks.impressions_task.flush)
@@ -686,13 +691,17 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
686
691
  telemetry_runtime_producer = telemetry_producer.get_telemetry_runtime_producer()
687
692
  telemetry_evaluation_producer = telemetry_producer.get_telemetry_evaluation_producer()
688
693
  telemetry_init_producer = telemetry_producer.get_telemetry_init_producer()
694
+ proxies = {}
695
+ if cfg.get('proxyUrl'):
696
+ proxies['https'] = cfg.get('proxyUrl')
689
697
 
690
698
  http_client = HttpClientAsync(
691
699
  sdk_url=sdk_url,
692
700
  events_url=events_url,
693
701
  auth_url=auth_api_base_url,
694
702
  telemetry_url=telemetry_api_base_url,
695
- timeout=cfg.get('connectionTimeout')
703
+ timeout=cfg.get('connectionTimeout'),
704
+ proxies=proxies
696
705
  )
697
706
 
698
707
  sdk_metadata = util.get_metadata(cfg)
@@ -763,7 +772,7 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
763
772
  synchronizer = SynchronizerAsync(synchronizers, tasks)
764
773
 
765
774
  manager = ManagerAsync(synchronizer, apis['auth'], cfg['streamingEnabled'],
766
- sdk_metadata, telemetry_runtime_producer, streaming_api_base_url, api_key[-4:])
775
+ sdk_metadata, telemetry_runtime_producer, streaming_api_base_url, api_key[-4:], proxy=proxies.get('https'))
767
776
 
768
777
  storages['events'].set_queue_full_hook(tasks.events_task.flush)
769
778
  storages['impressions'].set_queue_full_hook(tasks.impressions_task.flush)
@@ -1413,4 +1422,4 @@ def _get_total_and_invalid_flag_sets(config_raw):
1413
1422
  total_flag_sets = len(config_raw.get('flagSetsFilter'))
1414
1423
  invalid_flag_sets = total_flag_sets - len(input_validator.validate_flag_sets(config_raw.get('flagSetsFilter'), 'Telemetry Init'))
1415
1424
 
1416
- return total_flag_sets, invalid_flag_sets
1425
+ return total_flag_sets, invalid_flag_sets
@@ -64,7 +64,13 @@ class Evaluator(object): # pylint: disable=too-few-public-methods
64
64
  else:
65
65
  label, _treatment = self._check_prerequisites(feature, bucketing, key, attrs, ctx, label, _treatment)
66
66
  label, _treatment = self._get_treatment(feature, bucketing, key, attrs, ctx, label, _treatment)
67
- config = feature.get_configurations_for(_treatment)
67
+ if _treatment == CONTROL:
68
+ fallback_treatment = self._fallback_treatment_calculator.resolve(feature_name, label)
69
+ label = fallback_treatment.label
70
+ _treatment = fallback_treatment.treatment
71
+ config = fallback_treatment.config
72
+ else:
73
+ config = feature.get_configurations_for(_treatment)
68
74
 
69
75
  return {
70
76
  'treatment': _treatment,
@@ -125,7 +125,7 @@ class RedisSenderAdapter(ImpressionsSenderAdapter):
125
125
 
126
126
  except RedisAdapterException:
127
127
  _LOGGER.error('Something went wrong when trying to add mtks to redis')
128
- _LOGGER.error('Error: ', exc_info=True)
128
+ _LOGGER.debug('Error: ', exc_info=True)
129
129
  return False
130
130
 
131
131
  def flush_counters(self, to_send):
@@ -152,7 +152,7 @@ class RedisSenderAdapter(ImpressionsSenderAdapter):
152
152
 
153
153
  except RedisAdapterException:
154
154
  _LOGGER.error('Something went wrong when trying to add counters to redis')
155
- _LOGGER.error('Error: ', exc_info=True)
155
+ _LOGGER.debug('Error: ', exc_info=True)
156
156
  return False
157
157
 
158
158
  def _expire_keys(self, queue_key, key_default_ttl, total_keys, inserted):
@@ -198,7 +198,7 @@ class RedisSenderAdapterAsync(ImpressionsSenderAdapter):
198
198
 
199
199
  except RedisAdapterException:
200
200
  _LOGGER.error('Something went wrong when trying to add mtks to redis')
201
- _LOGGER.error('Error: ', exc_info=True)
201
+ _LOGGER.debug('Error: ', exc_info=True)
202
202
  return False
203
203
 
204
204
  async def flush_counters(self, to_send):
@@ -225,7 +225,7 @@ class RedisSenderAdapterAsync(ImpressionsSenderAdapter):
225
225
 
226
226
  except RedisAdapterException:
227
227
  _LOGGER.error('Something went wrong when trying to add counters to redis')
228
- _LOGGER.error('Error: ', exc_info=True)
228
+ _LOGGER.debug('Error: ', exc_info=True)
229
229
  return False
230
230
 
231
231
  async def _expire_keys(self, queue_key, key_default_ttl, total_keys, inserted):
@@ -274,7 +274,7 @@ class PluggableSenderAdapter(ImpressionsSenderAdapter):
274
274
 
275
275
  except RedisAdapterException:
276
276
  _LOGGER.error('Something went wrong when trying to add mtks to storage adapter')
277
- _LOGGER.error('Error: ', exc_info=True)
277
+ _LOGGER.debug('Error: ', exc_info=True)
278
278
  return False
279
279
 
280
280
  def flush_counters(self, to_send):
@@ -297,7 +297,7 @@ class PluggableSenderAdapter(ImpressionsSenderAdapter):
297
297
 
298
298
  except RedisAdapterException:
299
299
  _LOGGER.error('Something went wrong when trying to add counters to storage adapter')
300
- _LOGGER.error('Error: ', exc_info=True)
300
+ _LOGGER.debug('Error: ', exc_info=True)
301
301
  return False
302
302
 
303
303
  def _expire_keys(self, queue_key, key_default_ttl, total_keys, inserted):
@@ -346,7 +346,7 @@ class PluggableSenderAdapterAsync(ImpressionsSenderAdapter):
346
346
 
347
347
  except RedisAdapterException:
348
348
  _LOGGER.error('Something went wrong when trying to add mtks to storage adapter')
349
- _LOGGER.error('Error: ', exc_info=True)
349
+ _LOGGER.debug('Error: ', exc_info=True)
350
350
  return False
351
351
 
352
352
  async def flush_counters(self, to_send):
@@ -369,7 +369,7 @@ class PluggableSenderAdapterAsync(ImpressionsSenderAdapter):
369
369
 
370
370
  except RedisAdapterException:
371
371
  _LOGGER.error('Something went wrong when trying to add counters to storage adapter')
372
- _LOGGER.error('Error: ', exc_info=True)
372
+ _LOGGER.debug('Error: ', exc_info=True)
373
373
  return False
374
374
 
375
375
  async def _expire_keys(self, queue_key, key_default_ttl, total_keys, inserted):