posthoganalytics 6.7.4__py3-none-any.whl → 6.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- posthoganalytics/client.py +42 -1
- posthoganalytics/feature_flags.py +1 -8
- posthoganalytics/integrations/django.py +53 -14
- posthoganalytics/test/test_client.py +43 -0
- posthoganalytics/test/test_feature_flags.py +23 -35
- posthoganalytics/test/test_module.py +0 -8
- posthoganalytics/version.py +1 -1
- {posthoganalytics-6.7.4.dist-info → posthoganalytics-6.7.6.dist-info}/METADATA +1 -1
- {posthoganalytics-6.7.4.dist-info → posthoganalytics-6.7.6.dist-info}/RECORD +12 -12
- {posthoganalytics-6.7.4.dist-info → posthoganalytics-6.7.6.dist-info}/WHEEL +0 -0
- {posthoganalytics-6.7.4.dist-info → posthoganalytics-6.7.6.dist-info}/licenses/LICENSE +0 -0
- {posthoganalytics-6.7.4.dist-info → posthoganalytics-6.7.6.dist-info}/top_level.txt +0 -0
posthoganalytics/client.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
from datetime import datetime, timedelta
|
|
6
|
-
from typing import Any, Dict, Optional, Union
|
|
6
|
+
from typing import Any, Callable, Dict, Optional, Union
|
|
7
7
|
from typing_extensions import Unpack
|
|
8
8
|
from uuid import uuid4
|
|
9
9
|
|
|
@@ -99,6 +99,34 @@ def add_context_tags(properties):
|
|
|
99
99
|
return properties
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
def no_throw(default_return=None):
|
|
103
|
+
"""
|
|
104
|
+
Decorator to prevent raising exceptions from public API methods.
|
|
105
|
+
Note that this doesn't prevent errors from propagating via `on_error`.
|
|
106
|
+
Exceptions will still be raised if the debug flag is enabled.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
default_return: Value to return on exception (default: None)
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def decorator(func):
|
|
113
|
+
from functools import wraps
|
|
114
|
+
|
|
115
|
+
@wraps(func)
|
|
116
|
+
def wrapper(self, *args, **kwargs):
|
|
117
|
+
try:
|
|
118
|
+
return func(self, *args, **kwargs)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
if self.debug:
|
|
121
|
+
raise e
|
|
122
|
+
self.log.exception(f"Error in {func.__name__}: {e}")
|
|
123
|
+
return default_return
|
|
124
|
+
|
|
125
|
+
return wrapper
|
|
126
|
+
|
|
127
|
+
return decorator
|
|
128
|
+
|
|
129
|
+
|
|
102
130
|
class Client(object):
|
|
103
131
|
"""
|
|
104
132
|
This is the SDK reference for the PostHog Python SDK.
|
|
@@ -481,6 +509,7 @@ class Client(object):
|
|
|
481
509
|
|
|
482
510
|
return normalize_flags_response(resp_data)
|
|
483
511
|
|
|
512
|
+
@no_throw()
|
|
484
513
|
def capture(
|
|
485
514
|
self, event: str, **kwargs: Unpack[OptionalCaptureArgs]
|
|
486
515
|
) -> Optional[str]:
|
|
@@ -657,6 +686,7 @@ class Client(object):
|
|
|
657
686
|
f"Expected bool or dict."
|
|
658
687
|
)
|
|
659
688
|
|
|
689
|
+
@no_throw()
|
|
660
690
|
def set(self, **kwargs: Unpack[OptionalSetArgs]) -> Optional[str]:
|
|
661
691
|
"""
|
|
662
692
|
Set properties on a person profile.
|
|
@@ -690,6 +720,8 @@ class Client(object):
|
|
|
690
720
|
|
|
691
721
|
Category:
|
|
692
722
|
Identification
|
|
723
|
+
|
|
724
|
+
Note: This method will not raise exceptions. Errors are logged.
|
|
693
725
|
"""
|
|
694
726
|
distinct_id = kwargs.get("distinct_id", None)
|
|
695
727
|
properties = kwargs.get("properties", None)
|
|
@@ -716,6 +748,7 @@ class Client(object):
|
|
|
716
748
|
|
|
717
749
|
return self._enqueue(msg, disable_geoip)
|
|
718
750
|
|
|
751
|
+
@no_throw()
|
|
719
752
|
def set_once(self, **kwargs: Unpack[OptionalSetArgs]) -> Optional[str]:
|
|
720
753
|
"""
|
|
721
754
|
Set properties on a person profile only if they haven't been set before.
|
|
@@ -734,6 +767,8 @@ class Client(object):
|
|
|
734
767
|
|
|
735
768
|
Category:
|
|
736
769
|
Identification
|
|
770
|
+
|
|
771
|
+
Note: This method will not raise exceptions. Errors are logged.
|
|
737
772
|
"""
|
|
738
773
|
distinct_id = kwargs.get("distinct_id", None)
|
|
739
774
|
properties = kwargs.get("properties", None)
|
|
@@ -759,6 +794,7 @@ class Client(object):
|
|
|
759
794
|
|
|
760
795
|
return self._enqueue(msg, disable_geoip)
|
|
761
796
|
|
|
797
|
+
@no_throw()
|
|
762
798
|
def group_identify(
|
|
763
799
|
self,
|
|
764
800
|
group_type: str,
|
|
@@ -791,6 +827,8 @@ class Client(object):
|
|
|
791
827
|
|
|
792
828
|
Category:
|
|
793
829
|
Identification
|
|
830
|
+
|
|
831
|
+
Note: This method will not raise exceptions. Errors are logged.
|
|
794
832
|
"""
|
|
795
833
|
properties = properties or {}
|
|
796
834
|
|
|
@@ -815,6 +853,7 @@ class Client(object):
|
|
|
815
853
|
|
|
816
854
|
return self._enqueue(msg, disable_geoip)
|
|
817
855
|
|
|
856
|
+
@no_throw()
|
|
818
857
|
def alias(
|
|
819
858
|
self,
|
|
820
859
|
previous_id: str,
|
|
@@ -840,6 +879,8 @@ class Client(object):
|
|
|
840
879
|
|
|
841
880
|
Category:
|
|
842
881
|
Identification
|
|
882
|
+
|
|
883
|
+
Note: This method will not raise exceptions. Errors are logged.
|
|
843
884
|
"""
|
|
844
885
|
(distinct_id, personless) = get_identity_state(distinct_id)
|
|
845
886
|
|
|
@@ -220,14 +220,7 @@ def match_feature_flag_properties(
|
|
|
220
220
|
) or []
|
|
221
221
|
valid_variant_keys = [variant["key"] for variant in flag_variants]
|
|
222
222
|
|
|
223
|
-
|
|
224
|
-
# evaluated first, and the variant override is applied to the first matching condition.
|
|
225
|
-
sorted_flag_conditions = sorted(
|
|
226
|
-
flag_conditions,
|
|
227
|
-
key=lambda condition: 0 if condition.get("variant") else 1,
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
for condition in sorted_flag_conditions:
|
|
223
|
+
for condition in flag_conditions:
|
|
231
224
|
try:
|
|
232
225
|
# if any one condition resolves to True, we can shortcircuit and return
|
|
233
226
|
# the matching variant
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, cast
|
|
2
|
-
from posthoganalytics import contexts
|
|
2
|
+
from posthoganalytics import contexts
|
|
3
3
|
from posthoganalytics.client import Client
|
|
4
4
|
|
|
5
|
+
try:
|
|
6
|
+
from asgiref.sync import iscoroutinefunction
|
|
7
|
+
except ImportError:
|
|
8
|
+
# Fallback for older Django versions
|
|
9
|
+
import asyncio
|
|
10
|
+
|
|
11
|
+
iscoroutinefunction = asyncio.iscoroutinefunction
|
|
12
|
+
|
|
5
13
|
if TYPE_CHECKING:
|
|
6
14
|
from django.http import HttpRequest, HttpResponse # noqa: F401
|
|
7
|
-
from typing import Callable, Dict, Any, Optional # noqa: F401
|
|
15
|
+
from typing import Callable, Dict, Any, Optional, Union, Awaitable # noqa: F401
|
|
8
16
|
|
|
9
17
|
|
|
10
18
|
class PosthogContextMiddleware:
|
|
@@ -33,9 +41,24 @@ class PosthogContextMiddleware:
|
|
|
33
41
|
frontend. See the documentation for `set_context_session` and `identify_context` for more details.
|
|
34
42
|
"""
|
|
35
43
|
|
|
44
|
+
# Django middleware capability flags
|
|
45
|
+
sync_capable = True
|
|
46
|
+
async_capable = True
|
|
47
|
+
|
|
36
48
|
def __init__(self, get_response):
|
|
37
|
-
# type: (Callable[[HttpRequest], HttpResponse]) -> None
|
|
38
|
-
self.
|
|
49
|
+
# type: (Union[Callable[[HttpRequest], HttpResponse], Callable[[HttpRequest], Awaitable[HttpResponse]]]) -> None
|
|
50
|
+
self._is_coroutine = iscoroutinefunction(get_response)
|
|
51
|
+
self._async_get_response = None # type: Optional[Callable[[HttpRequest], Awaitable[HttpResponse]]]
|
|
52
|
+
self._sync_get_response = None # type: Optional[Callable[[HttpRequest], HttpResponse]]
|
|
53
|
+
|
|
54
|
+
if self._is_coroutine:
|
|
55
|
+
self._async_get_response = cast(
|
|
56
|
+
"Callable[[HttpRequest], Awaitable[HttpResponse]]", get_response
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
self._sync_get_response = cast(
|
|
60
|
+
"Callable[[HttpRequest], HttpResponse]", get_response
|
|
61
|
+
)
|
|
39
62
|
|
|
40
63
|
from django.conf import settings
|
|
41
64
|
|
|
@@ -159,23 +182,39 @@ class PosthogContextMiddleware:
|
|
|
159
182
|
|
|
160
183
|
def __call__(self, request):
|
|
161
184
|
# type: (HttpRequest) -> HttpResponse
|
|
185
|
+
# Purely defensive around django's internal sync/async handling - this should be unreachable, but if it's reached, we may
|
|
186
|
+
# as well return something semi-meaningful
|
|
187
|
+
if self._is_coroutine:
|
|
188
|
+
raise RuntimeError(
|
|
189
|
+
"PosthogContextMiddleware received sync call but get_response is async"
|
|
190
|
+
)
|
|
191
|
+
|
|
162
192
|
if self.request_filter and not self.request_filter(request):
|
|
163
|
-
|
|
193
|
+
assert self._sync_get_response is not None
|
|
194
|
+
return self._sync_get_response(request)
|
|
164
195
|
|
|
165
196
|
with contexts.new_context(self.capture_exceptions, client=self.client):
|
|
166
197
|
for k, v in self.extract_tags(request).items():
|
|
167
198
|
contexts.tag(k, v)
|
|
168
199
|
|
|
169
|
-
|
|
200
|
+
assert self._sync_get_response is not None
|
|
201
|
+
return self._sync_get_response(request)
|
|
170
202
|
|
|
171
|
-
def
|
|
203
|
+
async def __acall__(self, request):
|
|
204
|
+
# type: (HttpRequest) -> HttpResponse
|
|
172
205
|
if self.request_filter and not self.request_filter(request):
|
|
173
|
-
|
|
206
|
+
if self._async_get_response is not None:
|
|
207
|
+
return await self._async_get_response(request)
|
|
208
|
+
else:
|
|
209
|
+
assert self._sync_get_response is not None
|
|
210
|
+
return self._sync_get_response(request)
|
|
174
211
|
|
|
175
|
-
|
|
176
|
-
|
|
212
|
+
with contexts.new_context(self.capture_exceptions, client=self.client):
|
|
213
|
+
for k, v in self.extract_tags(request).items():
|
|
214
|
+
contexts.tag(k, v)
|
|
177
215
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
216
|
+
if self._async_get_response is not None:
|
|
217
|
+
return await self._async_get_response(request)
|
|
218
|
+
else:
|
|
219
|
+
assert self._sync_get_response is not None
|
|
220
|
+
return self._sync_get_response(request)
|
|
@@ -2423,3 +2423,46 @@ class TestClient(unittest.TestCase):
|
|
|
2423
2423
|
batch_data = mock_post.call_args[1]["batch"]
|
|
2424
2424
|
msg = batch_data[0]
|
|
2425
2425
|
self.assertEqual(msg["properties"]["$context_tags"], ["random_tag"])
|
|
2426
|
+
|
|
2427
|
+
@mock.patch(
|
|
2428
|
+
"posthog.client.Client._enqueue", side_effect=Exception("Unexpected error")
|
|
2429
|
+
)
|
|
2430
|
+
def test_methods_handle_exceptions(self, mock_enqueue):
|
|
2431
|
+
"""Test that all decorated methods handle exceptions gracefully."""
|
|
2432
|
+
client = Client("test-key")
|
|
2433
|
+
|
|
2434
|
+
test_cases = [
|
|
2435
|
+
("capture", ["test_event"], {}),
|
|
2436
|
+
("set", [], {"distinct_id": "some-id", "properties": {"a": "b"}}),
|
|
2437
|
+
("set_once", [], {"distinct_id": "some-id", "properties": {"a": "b"}}),
|
|
2438
|
+
("group_identify", ["group-type", "group-key"], {}),
|
|
2439
|
+
("alias", ["some-id", "new-id"], {}),
|
|
2440
|
+
]
|
|
2441
|
+
|
|
2442
|
+
for method_name, args, kwargs in test_cases:
|
|
2443
|
+
with self.subTest(method=method_name):
|
|
2444
|
+
method = getattr(client, method_name)
|
|
2445
|
+
result = method(*args, **kwargs)
|
|
2446
|
+
self.assertEqual(result, None)
|
|
2447
|
+
|
|
2448
|
+
@mock.patch(
|
|
2449
|
+
"posthog.client.Client._enqueue", side_effect=Exception("Expected error")
|
|
2450
|
+
)
|
|
2451
|
+
def test_debug_flag_re_raises_exceptions(self, mock_enqueue):
|
|
2452
|
+
"""Test that methods re-raise exceptions when debug=True."""
|
|
2453
|
+
client = Client("test-key", debug=True)
|
|
2454
|
+
|
|
2455
|
+
test_cases = [
|
|
2456
|
+
("capture", ["test_event"], {}),
|
|
2457
|
+
("set", [], {"distinct_id": "some-id", "properties": {"a": "b"}}),
|
|
2458
|
+
("set_once", [], {"distinct_id": "some-id", "properties": {"a": "b"}}),
|
|
2459
|
+
("group_identify", ["group-type", "group-key"], {}),
|
|
2460
|
+
("alias", ["some-id", "new-id"], {}),
|
|
2461
|
+
]
|
|
2462
|
+
|
|
2463
|
+
for method_name, args, kwargs in test_cases:
|
|
2464
|
+
with self.subTest(method=method_name):
|
|
2465
|
+
method = getattr(client, method_name)
|
|
2466
|
+
with self.assertRaises(Exception) as cm:
|
|
2467
|
+
method(*args, **kwargs)
|
|
2468
|
+
self.assertEqual(str(cm.exception), "Expected error")
|
|
@@ -2804,73 +2804,61 @@ class TestLocalEvaluation(unittest.TestCase):
|
|
|
2804
2804
|
self.assertEqual(patch_flags.call_count, 0)
|
|
2805
2805
|
|
|
2806
2806
|
@mock.patch("posthog.client.flags")
|
|
2807
|
-
def
|
|
2808
|
-
patch_flags.return_value = {"featureFlags": {"
|
|
2807
|
+
def test_conditions_evaluated_in_order(self, patch_flags):
|
|
2808
|
+
patch_flags.return_value = {"featureFlags": {"order-test": "server-variant"}}
|
|
2809
2809
|
client = Client(FAKE_TEST_API_KEY, personal_api_key="test")
|
|
2810
2810
|
client.feature_flags = [
|
|
2811
2811
|
{
|
|
2812
2812
|
"id": 1,
|
|
2813
|
-
"name": "
|
|
2814
|
-
"key": "
|
|
2813
|
+
"name": "Order Test Flag",
|
|
2814
|
+
"key": "order-test",
|
|
2815
2815
|
"active": True,
|
|
2816
|
-
"rollout_percentage": 100,
|
|
2817
2816
|
"filters": {
|
|
2818
2817
|
"groups": [
|
|
2819
2818
|
{
|
|
2820
2819
|
"rollout_percentage": 100,
|
|
2821
|
-
# The override applies even if the first condition matches all and gives everyone their default group
|
|
2822
2820
|
},
|
|
2823
2821
|
{
|
|
2824
2822
|
"properties": [
|
|
2825
2823
|
{
|
|
2826
2824
|
"key": "email",
|
|
2827
2825
|
"type": "person",
|
|
2828
|
-
"value": "
|
|
2829
|
-
"operator": "
|
|
2826
|
+
"value": "@vip.com",
|
|
2827
|
+
"operator": "icontains",
|
|
2830
2828
|
}
|
|
2831
2829
|
],
|
|
2832
2830
|
"rollout_percentage": 100,
|
|
2833
|
-
"variant": "
|
|
2831
|
+
"variant": "vip-variant",
|
|
2834
2832
|
},
|
|
2835
|
-
{"rollout_percentage": 50, "variant": "third-variant"},
|
|
2836
2833
|
],
|
|
2837
2834
|
"multivariate": {
|
|
2838
2835
|
"variants": [
|
|
2839
2836
|
{
|
|
2840
|
-
"key": "
|
|
2841
|
-
"name": "
|
|
2842
|
-
"rollout_percentage":
|
|
2837
|
+
"key": "control",
|
|
2838
|
+
"name": "Control",
|
|
2839
|
+
"rollout_percentage": 100,
|
|
2843
2840
|
},
|
|
2844
2841
|
{
|
|
2845
|
-
"key": "
|
|
2846
|
-
"name": "
|
|
2847
|
-
"rollout_percentage":
|
|
2848
|
-
},
|
|
2849
|
-
{
|
|
2850
|
-
"key": "third-variant",
|
|
2851
|
-
"name": "Third Variant",
|
|
2852
|
-
"rollout_percentage": 25,
|
|
2842
|
+
"key": "vip-variant",
|
|
2843
|
+
"name": "VIP Variant",
|
|
2844
|
+
"rollout_percentage": 0,
|
|
2853
2845
|
},
|
|
2854
2846
|
]
|
|
2855
2847
|
},
|
|
2856
2848
|
},
|
|
2857
2849
|
}
|
|
2858
2850
|
]
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
"
|
|
2866
|
-
)
|
|
2867
|
-
self.assertEqual(
|
|
2868
|
-
client.get_feature_flag("beta-feature", "example_id"), "third-variant"
|
|
2869
|
-
)
|
|
2870
|
-
self.assertEqual(
|
|
2871
|
-
client.get_feature_flag("beta-feature", "another_id"), "second-variant"
|
|
2851
|
+
|
|
2852
|
+
# Even though user@vip.com would match the second condition with variant override,
|
|
2853
|
+
# they should match the first condition and get control
|
|
2854
|
+
result = client.get_feature_flag(
|
|
2855
|
+
"order-test",
|
|
2856
|
+
"user123",
|
|
2857
|
+
person_properties={"email": "user@vip.com"},
|
|
2872
2858
|
)
|
|
2873
|
-
|
|
2859
|
+
self.assertEqual(result, "control")
|
|
2860
|
+
|
|
2861
|
+
# server not called because this can be evaluated locally
|
|
2874
2862
|
self.assertEqual(patch_flags.call_count, 0)
|
|
2875
2863
|
|
|
2876
2864
|
@mock.patch("posthog.client.flags")
|
|
@@ -18,14 +18,6 @@ class TestModule(unittest.TestCase):
|
|
|
18
18
|
"testsecret", host="http://localhost:8000", on_error=self.failed
|
|
19
19
|
)
|
|
20
20
|
|
|
21
|
-
def test_no_api_key(self):
|
|
22
|
-
self.posthog.api_key = None
|
|
23
|
-
self.assertRaises(Exception, self.posthog.capture)
|
|
24
|
-
|
|
25
|
-
def test_no_host(self):
|
|
26
|
-
self.posthog.host = None
|
|
27
|
-
self.assertRaises(Exception, self.posthog.capture)
|
|
28
|
-
|
|
29
21
|
def test_track(self):
|
|
30
22
|
res = self.posthog.capture("python module event", distinct_id="distinct_id")
|
|
31
23
|
self._assert_enqueue_result(res)
|
posthoganalytics/version.py
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
posthoganalytics/__init__.py,sha256=66HkeJ1fkzbKC2ggl3F164oajFeiGm8v84kJR0Yf5BI,25987
|
|
2
2
|
posthoganalytics/args.py,sha256=iZ2JWeANiAREJKhS-Qls9tIngjJOSfAVR8C4xFT5sHw,3307
|
|
3
|
-
posthoganalytics/client.py,sha256=
|
|
3
|
+
posthoganalytics/client.py,sha256=hldwOubstgRJQ7ZYF1sLamYYPpy7IQcmgSMXT2IREyI,72815
|
|
4
4
|
posthoganalytics/consumer.py,sha256=CiNbJBdyW9jER3ZYCKbX-JFmEDXlE1lbDy1MSl43-a0,4617
|
|
5
5
|
posthoganalytics/contexts.py,sha256=LFSFIYpUFWKTBnGMjV9n1aYHWbAzz5zLJGr2qG34PoE,9405
|
|
6
6
|
posthoganalytics/exception_capture.py,sha256=1VHBfffrXXrkK0PT8iVgKPpj_R1pGAzG5f3Qw0WF79w,1783
|
|
7
7
|
posthoganalytics/exception_utils.py,sha256=P_75873Y2jayqlLiIkbxCNE7Bc8cM6J9kfrdZ5ZSnA0,26696
|
|
8
|
-
posthoganalytics/feature_flags.py,sha256=
|
|
8
|
+
posthoganalytics/feature_flags.py,sha256=e2DOE0LOj6yk3ySf5oGkdNe5wXLoGtxvsFemFo8SK7A,21530
|
|
9
9
|
posthoganalytics/poller.py,sha256=jBz5rfH_kn_bBz7wCB46Fpvso4ttx4uzqIZWvXBCFmQ,595
|
|
10
10
|
posthoganalytics/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
posthoganalytics/request.py,sha256=Bsl2c5WwONKPQzwWMmKPX5VgOlwSiIcSNfhXgoz62Y8,6186
|
|
12
12
|
posthoganalytics/types.py,sha256=Dl3aFGX9XUR0wMmK12r2s5Hjan9jL4HpQ9GHpVcEq5U,10207
|
|
13
13
|
posthoganalytics/utils.py,sha256=-0w-OLcCaoldkbBebPzQyBzLJSo9G9yBOg8NDVz7La8,16088
|
|
14
|
-
posthoganalytics/version.py,sha256=
|
|
14
|
+
posthoganalytics/version.py,sha256=ugiK6MZjVnC7xaQRiFY_ZQ1afbQILvn45RjDa3shE3o,87
|
|
15
15
|
posthoganalytics/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
posthoganalytics/ai/sanitization.py,sha256=owipZ4eJYtd4JTI-CM_klatclXaeaIec3XJBOUfsOnQ,5770
|
|
17
17
|
posthoganalytics/ai/types.py,sha256=ceubs4K9xf8vQx7wokq1NL9hPtxyS7D7sUOuT7Lx1lM,3237
|
|
@@ -32,23 +32,23 @@ posthoganalytics/ai/openai/openai_async.py,sha256=k6bo3LfJ_CAPBZCxAzyM2uLz4BpW2Y
|
|
|
32
32
|
posthoganalytics/ai/openai/openai_converter.py,sha256=VBaAGdXPSVNgfvCnSAojslWkTRO2luUxpjafR-WMEbs,20469
|
|
33
33
|
posthoganalytics/ai/openai/openai_providers.py,sha256=RPVmj2V0_lAdno_ax5Ul2kwhBA9_rRgAdl_sCqrQc6M,4004
|
|
34
34
|
posthoganalytics/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
posthoganalytics/integrations/django.py,sha256=
|
|
35
|
+
posthoganalytics/integrations/django.py,sha256=DJ5qz_vWspJX2MK3rnE3_HCydwa0PSKMK8ItIpRGUYU,8637
|
|
36
36
|
posthoganalytics/test/__init__.py,sha256=VYgM6xPbJbvS-xhIcDiBRs0MFC9V_jT65uNeerCz_rM,299
|
|
37
37
|
posthoganalytics/test/test_before_send.py,sha256=A1_UVMewhHAvO39rZDWfS606vG_X-q0KNXvh5DAKiB8,7930
|
|
38
|
-
posthoganalytics/test/test_client.py,sha256=
|
|
38
|
+
posthoganalytics/test/test_client.py,sha256=e1dD9bFplZWROiP35fuyBDguGXC6ZmG5j79Iw2t_NBw,96363
|
|
39
39
|
posthoganalytics/test/test_consumer.py,sha256=HGMfU9PzQ5ZAe_R3kHnZNsMvD7jUjHL-gie0isrvMMk,7107
|
|
40
40
|
posthoganalytics/test/test_contexts.py,sha256=c--hNUIEf6SHQ7H9vdPhU1oLCN0SnD4wDbFr-eLPHDo,7013
|
|
41
41
|
posthoganalytics/test/test_exception_capture.py,sha256=al37Kg6wjzL_IBCFUUXRvkP6nVrqS6IZRCOKSo29Nh8,1063
|
|
42
42
|
posthoganalytics/test/test_feature_flag.py,sha256=9RQwB5eCvVAGrrO7UnR3Z1OidP_YoL4iBl3A83fuAig,6824
|
|
43
43
|
posthoganalytics/test/test_feature_flag_result.py,sha256=z2OgD97r85LKMqCnoCqAs74WjUMucayAtC3qWaITGCA,15898
|
|
44
|
-
posthoganalytics/test/test_feature_flags.py,sha256=
|
|
45
|
-
posthoganalytics/test/test_module.py,sha256=
|
|
44
|
+
posthoganalytics/test/test_feature_flags.py,sha256=H7DmRSs0ggl7E6DzBGy1aXfCQwf2nDQ0I_xh-kQyXQ0,212423
|
|
45
|
+
posthoganalytics/test/test_module.py,sha256=M772XKYO30XluqBTumZFFnYGqVxDmKKly4eUjhLIjZU,822
|
|
46
46
|
posthoganalytics/test/test_request.py,sha256=Zc0VbkjpVmj8mKokQm9rzdgTr0b1U44vvMYSkB_IQLs,4467
|
|
47
47
|
posthoganalytics/test/test_size_limited_dict.py,sha256=-5IQjIEr_-Dql24M0HusdR_XroOMrtgiT0v6ZQCRvzo,774
|
|
48
48
|
posthoganalytics/test/test_types.py,sha256=bRPHdwVpP7hu7emsplU8UVyzSQptv6PaG5lAoOD_BtM,7595
|
|
49
49
|
posthoganalytics/test/test_utils.py,sha256=sqUTbfweVcxxFRd3WDMFXqPMyU6DvzOBeAOc68Py9aw,9620
|
|
50
|
-
posthoganalytics-6.7.
|
|
51
|
-
posthoganalytics-6.7.
|
|
52
|
-
posthoganalytics-6.7.
|
|
53
|
-
posthoganalytics-6.7.
|
|
54
|
-
posthoganalytics-6.7.
|
|
50
|
+
posthoganalytics-6.7.6.dist-info/licenses/LICENSE,sha256=wGf9JBotDkSygFj43m49oiKlFnpMnn97keiZKF-40vE,2450
|
|
51
|
+
posthoganalytics-6.7.6.dist-info/METADATA,sha256=kRW594Umk3sBUSlV9KaCAWJoim0AHERR8ktpMsHhbHs,6024
|
|
52
|
+
posthoganalytics-6.7.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
53
|
+
posthoganalytics-6.7.6.dist-info/top_level.txt,sha256=8QsNIqIkBh1p2TXvKp0Em9ZLZKwe3uIqCETyW4s1GOE,17
|
|
54
|
+
posthoganalytics-6.7.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|