posthoganalytics 6.0.4__py3-none-any.whl → 6.1.1__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/__init__.py +364 -129
- posthoganalytics/client.py +451 -44
- posthoganalytics/contexts.py +33 -3
- posthoganalytics/feature_flags.py +15 -0
- posthoganalytics/integrations/django.py +13 -1
- posthoganalytics/test/test_client.py +90 -0
- posthoganalytics/test/test_feature_flags.py +71 -0
- posthoganalytics/version.py +1 -1
- {posthoganalytics-6.0.4.dist-info → posthoganalytics-6.1.1.dist-info}/METADATA +1 -1
- {posthoganalytics-6.0.4.dist-info → posthoganalytics-6.1.1.dist-info}/RECORD +13 -13
- {posthoganalytics-6.0.4.dist-info → posthoganalytics-6.1.1.dist-info}/WHEEL +0 -0
- {posthoganalytics-6.0.4.dist-info → posthoganalytics-6.1.1.dist-info}/licenses/LICENSE +0 -0
- {posthoganalytics-6.0.4.dist-info → posthoganalytics-6.1.1.dist-info}/top_level.txt +0 -0
posthoganalytics/contexts.py
CHANGED
|
@@ -71,7 +71,9 @@ def _get_current_context() -> Optional[ContextScope]:
|
|
|
71
71
|
|
|
72
72
|
@contextmanager
|
|
73
73
|
def new_context(
|
|
74
|
-
fresh
|
|
74
|
+
fresh: bool = False,
|
|
75
|
+
capture_exceptions: bool = True,
|
|
76
|
+
client: Optional["Client"] = None,
|
|
75
77
|
):
|
|
76
78
|
"""
|
|
77
79
|
Create a new context scope that will be active for the duration of the with block.
|
|
@@ -94,20 +96,25 @@ def new_context(
|
|
|
94
96
|
the global one, in the case of `posthog.capture`)
|
|
95
97
|
|
|
96
98
|
Examples:
|
|
99
|
+
```python
|
|
97
100
|
# Inherit parent context tags
|
|
98
101
|
with posthog.new_context():
|
|
99
102
|
posthog.tag("request_id", "123")
|
|
100
103
|
# Both this event and the exception will be tagged with the context tags
|
|
101
104
|
posthog.capture("event_name", {"property": "value"})
|
|
102
105
|
raise ValueError("Something went wrong")
|
|
103
|
-
|
|
106
|
+
```
|
|
107
|
+
```python
|
|
104
108
|
# Start with fresh context (no inherited tags)
|
|
105
109
|
with posthog.new_context(fresh=True):
|
|
106
110
|
posthog.tag("request_id", "123")
|
|
107
111
|
# Both this event and the exception will be tagged with the context tags
|
|
108
112
|
posthog.capture("event_name", {"property": "value"})
|
|
109
113
|
raise ValueError("Something went wrong")
|
|
114
|
+
```
|
|
110
115
|
|
|
116
|
+
Category:
|
|
117
|
+
Contexts
|
|
111
118
|
"""
|
|
112
119
|
from posthoganalytics import capture_exception
|
|
113
120
|
|
|
@@ -138,7 +145,12 @@ def tag(key: str, value: Any) -> None:
|
|
|
138
145
|
value: The tag value
|
|
139
146
|
|
|
140
147
|
Example:
|
|
148
|
+
```python
|
|
141
149
|
posthog.tag("user_id", "123")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Category:
|
|
153
|
+
Contexts
|
|
142
154
|
"""
|
|
143
155
|
current_context = _get_current_context()
|
|
144
156
|
if current_context:
|
|
@@ -152,6 +164,9 @@ def get_tags() -> Dict[str, Any]:
|
|
|
152
164
|
|
|
153
165
|
Returns:
|
|
154
166
|
Dict of all tags in the current context
|
|
167
|
+
|
|
168
|
+
Category:
|
|
169
|
+
Contexts
|
|
155
170
|
"""
|
|
156
171
|
current_context = _get_current_context()
|
|
157
172
|
if current_context:
|
|
@@ -170,6 +185,9 @@ def identify_context(distinct_id: str) -> None:
|
|
|
170
185
|
|
|
171
186
|
Args:
|
|
172
187
|
distinct_id: The distinct ID to associate with the current context and its children.
|
|
188
|
+
|
|
189
|
+
Category:
|
|
190
|
+
Contexts
|
|
173
191
|
"""
|
|
174
192
|
current_context = _get_current_context()
|
|
175
193
|
if current_context:
|
|
@@ -184,6 +202,9 @@ def set_context_session(session_id: str) -> None:
|
|
|
184
202
|
|
|
185
203
|
Args:
|
|
186
204
|
session_id: The session ID to associate with the current context and its children. See https://posthog.com/docs/data/sessions
|
|
205
|
+
|
|
206
|
+
Category:
|
|
207
|
+
Contexts
|
|
187
208
|
"""
|
|
188
209
|
current_context = _get_current_context()
|
|
189
210
|
if current_context:
|
|
@@ -196,6 +217,9 @@ def get_context_session_id() -> Optional[str]:
|
|
|
196
217
|
|
|
197
218
|
Returns:
|
|
198
219
|
The session ID if set, None otherwise
|
|
220
|
+
|
|
221
|
+
Category:
|
|
222
|
+
Contexts
|
|
199
223
|
"""
|
|
200
224
|
current_context = _get_current_context()
|
|
201
225
|
if current_context:
|
|
@@ -209,6 +233,9 @@ def get_context_distinct_id() -> Optional[str]:
|
|
|
209
233
|
|
|
210
234
|
Returns:
|
|
211
235
|
The distinct ID if set, None otherwise
|
|
236
|
+
|
|
237
|
+
Category:
|
|
238
|
+
Contexts
|
|
212
239
|
"""
|
|
213
240
|
current_context = _get_current_context()
|
|
214
241
|
if current_context:
|
|
@@ -219,7 +246,7 @@ def get_context_distinct_id() -> Optional[str]:
|
|
|
219
246
|
F = TypeVar("F", bound=Callable[..., Any])
|
|
220
247
|
|
|
221
248
|
|
|
222
|
-
def scoped(fresh=False, capture_exceptions=True):
|
|
249
|
+
def scoped(fresh: bool = False, capture_exceptions: bool = True):
|
|
223
250
|
"""
|
|
224
251
|
Decorator that creates a new context for the function. Simply wraps
|
|
225
252
|
the function in a with posthog.new_context(): block.
|
|
@@ -239,6 +266,9 @@ def scoped(fresh=False, capture_exceptions=True):
|
|
|
239
266
|
# If this raises an exception, it will be captured with tags
|
|
240
267
|
# and then re-raised
|
|
241
268
|
some_risky_function()
|
|
269
|
+
|
|
270
|
+
Category:
|
|
271
|
+
Contexts
|
|
242
272
|
"""
|
|
243
273
|
|
|
244
274
|
def decorator(func: F) -> F:
|
|
@@ -109,6 +109,14 @@ def is_condition_match(
|
|
|
109
109
|
property_type = prop.get("type")
|
|
110
110
|
if property_type == "cohort":
|
|
111
111
|
matches = match_cohort(prop, properties, cohort_properties)
|
|
112
|
+
elif property_type == "flag":
|
|
113
|
+
log.warning(
|
|
114
|
+
"Flag dependency filters are not supported in local evaluation. "
|
|
115
|
+
"Skipping condition for flag '%s' with dependency on flag '%s'",
|
|
116
|
+
feature_flag.get("key", "unknown"),
|
|
117
|
+
prop.get("key", "unknown"),
|
|
118
|
+
)
|
|
119
|
+
continue
|
|
112
120
|
else:
|
|
113
121
|
matches = match_property(prop, properties)
|
|
114
122
|
if not matches:
|
|
@@ -317,6 +325,13 @@ def match_property_group(property_group, property_values, cohort_properties) ->
|
|
|
317
325
|
try:
|
|
318
326
|
if prop.get("type") == "cohort":
|
|
319
327
|
matches = match_cohort(prop, property_values, cohort_properties)
|
|
328
|
+
elif prop.get("type") == "flag":
|
|
329
|
+
log.warning(
|
|
330
|
+
"Flag dependency filters are not supported in local evaluation. "
|
|
331
|
+
"Skipping condition with dependency on flag '%s'",
|
|
332
|
+
prop.get("key", "unknown"),
|
|
333
|
+
)
|
|
334
|
+
continue
|
|
320
335
|
else:
|
|
321
336
|
matches = match_property(prop, property_values)
|
|
322
337
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, cast
|
|
2
|
-
from posthoganalytics import contexts
|
|
2
|
+
from posthoganalytics import contexts, capture_exception
|
|
3
3
|
from posthoganalytics.client import Client
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
@@ -167,3 +167,15 @@ class PosthogContextMiddleware:
|
|
|
167
167
|
contexts.tag(k, v)
|
|
168
168
|
|
|
169
169
|
return self.get_response(request)
|
|
170
|
+
|
|
171
|
+
def process_exception(self, request, exception):
|
|
172
|
+
if self.request_filter and not self.request_filter(request):
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
if not self.capture_exceptions:
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
if self.client:
|
|
179
|
+
self.client.capture_exception(exception)
|
|
180
|
+
else:
|
|
181
|
+
capture_exception(exception)
|
|
@@ -1903,3 +1903,93 @@ class TestClient(unittest.TestCase):
|
|
|
1903
1903
|
self.assertEqual(
|
|
1904
1904
|
msg["properties"]["$session_id"], "explicit-session-override"
|
|
1905
1905
|
)
|
|
1906
|
+
|
|
1907
|
+
@mock.patch("posthog.client.Poller")
|
|
1908
|
+
@mock.patch("posthog.client.get")
|
|
1909
|
+
def test_enable_local_evaluation_false_disables_poller(
|
|
1910
|
+
self, patch_get, patch_poller
|
|
1911
|
+
):
|
|
1912
|
+
"""Test that when enable_local_evaluation=False, the poller is not started"""
|
|
1913
|
+
patch_get.return_value = {
|
|
1914
|
+
"flags": [
|
|
1915
|
+
{"id": 1, "name": "Beta Feature", "key": "beta-feature", "active": True}
|
|
1916
|
+
],
|
|
1917
|
+
"group_type_mapping": {},
|
|
1918
|
+
"cohorts": {},
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
client = Client(
|
|
1922
|
+
FAKE_TEST_API_KEY,
|
|
1923
|
+
personal_api_key="test-personal-key",
|
|
1924
|
+
enable_local_evaluation=False,
|
|
1925
|
+
)
|
|
1926
|
+
|
|
1927
|
+
# Load feature flags should not start the poller
|
|
1928
|
+
client.load_feature_flags()
|
|
1929
|
+
|
|
1930
|
+
# Assert that the poller was not created/started
|
|
1931
|
+
patch_poller.assert_not_called()
|
|
1932
|
+
# But the feature flags should still be loaded
|
|
1933
|
+
patch_get.assert_called_once()
|
|
1934
|
+
self.assertEqual(len(client.feature_flags), 1)
|
|
1935
|
+
self.assertEqual(client.feature_flags[0]["key"], "beta-feature")
|
|
1936
|
+
|
|
1937
|
+
@mock.patch("posthog.client.Poller")
|
|
1938
|
+
@mock.patch("posthog.client.get")
|
|
1939
|
+
def test_enable_local_evaluation_true_starts_poller(self, patch_get, patch_poller):
|
|
1940
|
+
"""Test that when enable_local_evaluation=True (default), the poller is started"""
|
|
1941
|
+
patch_get.return_value = {
|
|
1942
|
+
"flags": [
|
|
1943
|
+
{"id": 1, "name": "Beta Feature", "key": "beta-feature", "active": True}
|
|
1944
|
+
],
|
|
1945
|
+
"group_type_mapping": {},
|
|
1946
|
+
"cohorts": {},
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
client = Client(
|
|
1950
|
+
FAKE_TEST_API_KEY,
|
|
1951
|
+
personal_api_key="test-personal-key",
|
|
1952
|
+
enable_local_evaluation=True,
|
|
1953
|
+
)
|
|
1954
|
+
|
|
1955
|
+
# Load feature flags should start the poller
|
|
1956
|
+
client.load_feature_flags()
|
|
1957
|
+
|
|
1958
|
+
# Assert that the poller was created and started
|
|
1959
|
+
patch_poller.assert_called_once()
|
|
1960
|
+
patch_get.assert_called_once()
|
|
1961
|
+
self.assertEqual(len(client.feature_flags), 1)
|
|
1962
|
+
self.assertEqual(client.feature_flags[0]["key"], "beta-feature")
|
|
1963
|
+
|
|
1964
|
+
@mock.patch("posthog.client.remote_config")
|
|
1965
|
+
def test_get_remote_config_payload_works_without_poller(self, patch_remote_config):
|
|
1966
|
+
"""Test that get_remote_config_payload works without local evaluation enabled"""
|
|
1967
|
+
patch_remote_config.return_value = {"test": "payload"}
|
|
1968
|
+
|
|
1969
|
+
client = Client(
|
|
1970
|
+
FAKE_TEST_API_KEY,
|
|
1971
|
+
personal_api_key="test-personal-key",
|
|
1972
|
+
enable_local_evaluation=False,
|
|
1973
|
+
)
|
|
1974
|
+
|
|
1975
|
+
# Should work without poller
|
|
1976
|
+
result = client.get_remote_config_payload("test-flag")
|
|
1977
|
+
|
|
1978
|
+
self.assertEqual(result, {"test": "payload"})
|
|
1979
|
+
patch_remote_config.assert_called_once_with(
|
|
1980
|
+
"test-personal-key",
|
|
1981
|
+
client.host,
|
|
1982
|
+
"test-flag",
|
|
1983
|
+
timeout=client.feature_flags_request_timeout_seconds,
|
|
1984
|
+
)
|
|
1985
|
+
|
|
1986
|
+
def test_get_remote_config_payload_requires_personal_api_key(self):
|
|
1987
|
+
"""Test that get_remote_config_payload requires personal API key"""
|
|
1988
|
+
client = Client(
|
|
1989
|
+
FAKE_TEST_API_KEY,
|
|
1990
|
+
enable_local_evaluation=False,
|
|
1991
|
+
)
|
|
1992
|
+
|
|
1993
|
+
result = client.get_remote_config_payload("test-flag")
|
|
1994
|
+
|
|
1995
|
+
self.assertIsNone(result)
|
|
@@ -1355,6 +1355,77 @@ class TestLocalEvaluation(unittest.TestCase):
|
|
|
1355
1355
|
self.assertEqual(patch_flags.call_count, 0)
|
|
1356
1356
|
self.assertEqual(patch_get.call_count, 0)
|
|
1357
1357
|
|
|
1358
|
+
@mock.patch("posthog.feature_flags.log")
|
|
1359
|
+
@mock.patch("posthog.client.flags")
|
|
1360
|
+
@mock.patch("posthog.client.get")
|
|
1361
|
+
def test_feature_flags_with_flag_dependencies(
|
|
1362
|
+
self, patch_get, patch_flags, mock_log
|
|
1363
|
+
):
|
|
1364
|
+
client = Client(FAKE_TEST_API_KEY, personal_api_key=FAKE_TEST_API_KEY)
|
|
1365
|
+
client.feature_flags = [
|
|
1366
|
+
{
|
|
1367
|
+
"id": 1,
|
|
1368
|
+
"name": "Flag with Dependencies",
|
|
1369
|
+
"key": "flag-with-dependencies",
|
|
1370
|
+
"active": True,
|
|
1371
|
+
"filters": {
|
|
1372
|
+
"groups": [
|
|
1373
|
+
{
|
|
1374
|
+
"properties": [
|
|
1375
|
+
{
|
|
1376
|
+
"key": "beta-feature",
|
|
1377
|
+
"operator": "exact",
|
|
1378
|
+
"value": True,
|
|
1379
|
+
"type": "flag",
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
"key": "email",
|
|
1383
|
+
"operator": "icontains",
|
|
1384
|
+
"value": "@example.com",
|
|
1385
|
+
"type": "person",
|
|
1386
|
+
},
|
|
1387
|
+
],
|
|
1388
|
+
"rollout_percentage": 100,
|
|
1389
|
+
}
|
|
1390
|
+
],
|
|
1391
|
+
},
|
|
1392
|
+
}
|
|
1393
|
+
]
|
|
1394
|
+
|
|
1395
|
+
# Test that flag evaluation doesn't fail when encountering a flag dependency
|
|
1396
|
+
# The flag should evaluate based on other conditions (email contains @example.com)
|
|
1397
|
+
# Since flag dependencies aren't implemented, it should skip the flag condition
|
|
1398
|
+
# and evaluate based on the email condition only
|
|
1399
|
+
feature_flag_match = client.get_feature_flag(
|
|
1400
|
+
"flag-with-dependencies",
|
|
1401
|
+
"test-user",
|
|
1402
|
+
person_properties={"email": "test@example.com"},
|
|
1403
|
+
)
|
|
1404
|
+
self.assertEqual(feature_flag_match, True)
|
|
1405
|
+
self.assertEqual(patch_flags.call_count, 0)
|
|
1406
|
+
self.assertEqual(patch_get.call_count, 0)
|
|
1407
|
+
|
|
1408
|
+
# Verify warning was logged for flag dependency
|
|
1409
|
+
mock_log.warning.assert_called_with(
|
|
1410
|
+
"Flag dependency filters are not supported in local evaluation. "
|
|
1411
|
+
"Skipping condition for flag '%s' with dependency on flag '%s'",
|
|
1412
|
+
"flag-with-dependencies",
|
|
1413
|
+
"beta-feature",
|
|
1414
|
+
)
|
|
1415
|
+
|
|
1416
|
+
# Test with email that doesn't match
|
|
1417
|
+
feature_flag_match = client.get_feature_flag(
|
|
1418
|
+
"flag-with-dependencies",
|
|
1419
|
+
"test-user-2",
|
|
1420
|
+
person_properties={"email": "test@other.com"},
|
|
1421
|
+
)
|
|
1422
|
+
self.assertEqual(feature_flag_match, False)
|
|
1423
|
+
self.assertEqual(patch_flags.call_count, 0)
|
|
1424
|
+
self.assertEqual(patch_get.call_count, 0)
|
|
1425
|
+
|
|
1426
|
+
# Verify warning was logged again for the second evaluation
|
|
1427
|
+
self.assertEqual(mock_log.warning.call_count, 2)
|
|
1428
|
+
|
|
1358
1429
|
@mock.patch("posthog.client.Poller")
|
|
1359
1430
|
@mock.patch("posthog.client.get")
|
|
1360
1431
|
def test_load_feature_flags(self, patch_get, patch_poll):
|
posthoganalytics/version.py
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
posthoganalytics/__init__.py,sha256=
|
|
1
|
+
posthoganalytics/__init__.py,sha256=TSi-Hq6mKCAiq6VAjaHPG5g8Pb8FTkK8De_l69O7G74,24096
|
|
2
2
|
posthoganalytics/args.py,sha256=hRKPQ3cPGyDn4S7Ay9t2NlgoZg1cJ0GeN_Mb6OKtmfo,3145
|
|
3
|
-
posthoganalytics/client.py,sha256=
|
|
3
|
+
posthoganalytics/client.py,sha256=L_Ive-qlIvflqjLrote0TP2r9jBqbNsQE_Xs7gDEe4Y,65265
|
|
4
4
|
posthoganalytics/consumer.py,sha256=CiNbJBdyW9jER3ZYCKbX-JFmEDXlE1lbDy1MSl43-a0,4617
|
|
5
|
-
posthoganalytics/contexts.py,sha256=
|
|
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=O_kXmw3goB2E9XMBosdPeBAuo9MsnsH8PyNWq95a0qo,14391
|
|
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=TaeySYpcvHMf5Ftf5KqqlO0VPJpirKBCRrThlS04Kew,6124
|
|
12
12
|
posthoganalytics/types.py,sha256=INxWBOEQc0xgPcap6FdQNSU7zuQBmKShYaGzyuHKql8,9128
|
|
13
13
|
posthoganalytics/utils.py,sha256=-0w-OLcCaoldkbBebPzQyBzLJSo9G9yBOg8NDVz7La8,16088
|
|
14
|
-
posthoganalytics/version.py,sha256=
|
|
14
|
+
posthoganalytics/version.py,sha256=xZhcgW3hzlFW0J_tV0DpBWXhz8E1uxHP1x46lky-cjo,87
|
|
15
15
|
posthoganalytics/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
posthoganalytics/ai/utils.py,sha256=5-2XfmetCs0v9otBoux7-IEG933wAnKLSGS6oYLqCkw,19529
|
|
17
17
|
posthoganalytics/ai/anthropic/__init__.py,sha256=fFhDOiRzTXzGQlgnrRDL-4yKC8EYIl8NW4a2QNR6xRU,368
|
|
@@ -27,23 +27,23 @@ posthoganalytics/ai/openai/openai.py,sha256=iL_cwctaAhPdXNo4EpIZooOWGyjNj0W-OUEo
|
|
|
27
27
|
posthoganalytics/ai/openai/openai_async.py,sha256=KxPCd5imF5iZ9VkJ12HjCO2skaF1tHsHveAknIqV93g,23769
|
|
28
28
|
posthoganalytics/ai/openai/openai_providers.py,sha256=EMuEvdHSOFbrhmfuU0is7pBVWS3ReAUT0PZqgMXdyjk,3884
|
|
29
29
|
posthoganalytics/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
posthoganalytics/integrations/django.py,sha256=
|
|
30
|
+
posthoganalytics/integrations/django.py,sha256=KYtBr7CkiZQynRc2TCWWYHe-J3ie8iSUa42WPshYZdc,6795
|
|
31
31
|
posthoganalytics/test/__init__.py,sha256=VYgM6xPbJbvS-xhIcDiBRs0MFC9V_jT65uNeerCz_rM,299
|
|
32
32
|
posthoganalytics/test/test_before_send.py,sha256=A1_UVMewhHAvO39rZDWfS606vG_X-q0KNXvh5DAKiB8,7930
|
|
33
|
-
posthoganalytics/test/test_client.py,sha256=
|
|
33
|
+
posthoganalytics/test/test_client.py,sha256=fghypNGUqOY9OmycsdNK5SsyCoimxYVisFfFq2nkTCU,77840
|
|
34
34
|
posthoganalytics/test/test_consumer.py,sha256=HGMfU9PzQ5ZAe_R3kHnZNsMvD7jUjHL-gie0isrvMMk,7107
|
|
35
35
|
posthoganalytics/test/test_contexts.py,sha256=c--hNUIEf6SHQ7H9vdPhU1oLCN0SnD4wDbFr-eLPHDo,7013
|
|
36
36
|
posthoganalytics/test/test_exception_capture.py,sha256=al37Kg6wjzL_IBCFUUXRvkP6nVrqS6IZRCOKSo29Nh8,1063
|
|
37
37
|
posthoganalytics/test/test_feature_flag.py,sha256=9RQwB5eCvVAGrrO7UnR3Z1OidP_YoL4iBl3A83fuAig,6824
|
|
38
38
|
posthoganalytics/test/test_feature_flag_result.py,sha256=z2OgD97r85LKMqCnoCqAs74WjUMucayAtC3qWaITGCA,15898
|
|
39
|
-
posthoganalytics/test/test_feature_flags.py,sha256=
|
|
39
|
+
posthoganalytics/test/test_feature_flags.py,sha256=vx33vM_loTnlY4T7iLGO5X5htjkiTQGqT01LeocVbLo,171971
|
|
40
40
|
posthoganalytics/test/test_module.py,sha256=viqaAWA_uHt8r20fHIeME6IQkeXmQ8ZyrJTtPGQAb1E,1070
|
|
41
41
|
posthoganalytics/test/test_request.py,sha256=Zc0VbkjpVmj8mKokQm9rzdgTr0b1U44vvMYSkB_IQLs,4467
|
|
42
42
|
posthoganalytics/test/test_size_limited_dict.py,sha256=-5IQjIEr_-Dql24M0HusdR_XroOMrtgiT0v6ZQCRvzo,774
|
|
43
43
|
posthoganalytics/test/test_types.py,sha256=bRPHdwVpP7hu7emsplU8UVyzSQptv6PaG5lAoOD_BtM,7595
|
|
44
44
|
posthoganalytics/test/test_utils.py,sha256=sqUTbfweVcxxFRd3WDMFXqPMyU6DvzOBeAOc68Py9aw,9620
|
|
45
|
-
posthoganalytics-6.
|
|
46
|
-
posthoganalytics-6.
|
|
47
|
-
posthoganalytics-6.
|
|
48
|
-
posthoganalytics-6.
|
|
49
|
-
posthoganalytics-6.
|
|
45
|
+
posthoganalytics-6.1.1.dist-info/licenses/LICENSE,sha256=wGf9JBotDkSygFj43m49oiKlFnpMnn97keiZKF-40vE,2450
|
|
46
|
+
posthoganalytics-6.1.1.dist-info/METADATA,sha256=xrhfLBXcqwgMm1nsVsP5UDPo3nrGC6IZitVt0Dpn5XM,6024
|
|
47
|
+
posthoganalytics-6.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
48
|
+
posthoganalytics-6.1.1.dist-info/top_level.txt,sha256=8QsNIqIkBh1p2TXvKp0Em9ZLZKwe3uIqCETyW4s1GOE,17
|
|
49
|
+
posthoganalytics-6.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|