posthog 6.7.2__py3-none-any.whl → 6.9.0__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.
@@ -32,3 +32,303 @@ def test_excepthook(tmpdir):
32
32
  b'"$exception_list": [{"mechanism": {"type": "generic", "handled": true}, "module": null, "type": "ZeroDivisionError", "value": "division by zero", "stacktrace": {"frames": [{"platform": "python", "filename": "app.py", "abs_path"'
33
33
  in output
34
34
  )
35
+
36
+
37
+ def test_code_variables_capture(tmpdir):
38
+ app = tmpdir.join("app.py")
39
+ app.write(
40
+ dedent(
41
+ """
42
+ import os
43
+ from posthog import Posthog
44
+
45
+ class UnserializableObject:
46
+ pass
47
+
48
+ posthog = Posthog(
49
+ 'phc_x',
50
+ host='https://eu.i.posthog.com',
51
+ debug=True,
52
+ enable_exception_autocapture=True,
53
+ capture_exception_code_variables=True,
54
+ project_root=os.path.dirname(os.path.abspath(__file__))
55
+ )
56
+
57
+ def trigger_error():
58
+ my_string = "hello world"
59
+ my_number = 42
60
+ my_bool = True
61
+ my_dict = {"name": "test", "value": 123}
62
+ my_obj = UnserializableObject()
63
+ my_password = "secret123" # Should be masked by default
64
+ __should_be_ignored = "hidden" # Should be ignored by default
65
+
66
+ 1/0 # Trigger exception
67
+
68
+ def intermediate_function():
69
+ request_id = "abc-123"
70
+ user_count = 100
71
+ is_active = True
72
+
73
+ trigger_error()
74
+
75
+ def process_data():
76
+ batch_size = 50
77
+ retry_count = 3
78
+
79
+ intermediate_function()
80
+
81
+ process_data()
82
+ """
83
+ )
84
+ )
85
+
86
+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
87
+ subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)
88
+
89
+ output = excinfo.value.output
90
+
91
+ assert b"ZeroDivisionError" in output
92
+ assert b"code_variables" in output
93
+
94
+ # Variables from trigger_error frame
95
+ assert b"'my_string': 'hello world'" in output
96
+ assert b"'my_number': 42" in output
97
+ assert b"'my_bool': 'True'" in output
98
+ assert b'"my_dict": "{\\"name\\": \\"test\\", \\"value\\": 123}"' in output
99
+ assert b'"my_obj": "<UnserializableObject>"' in output
100
+ assert b"'my_password': '$$_posthog_redacted_based_on_masking_rules_$$'" in output
101
+ assert b"'__should_be_ignored':" not in output
102
+
103
+ # Variables from intermediate_function frame
104
+ assert b"'request_id': 'abc-123'" in output
105
+ assert b"'user_count': 100" in output
106
+ assert b"'is_active': 'True'" in output
107
+
108
+ # Variables from process_data frame
109
+ assert b"'batch_size': 50" in output
110
+ assert b"'retry_count': 3" in output
111
+
112
+
113
+ def test_code_variables_context_override(tmpdir):
114
+ app = tmpdir.join("app.py")
115
+ app.write(
116
+ dedent(
117
+ """
118
+ import os
119
+ import posthog
120
+ from posthog import Posthog
121
+
122
+ posthog_client = Posthog(
123
+ 'phc_x',
124
+ host='https://eu.i.posthog.com',
125
+ debug=True,
126
+ enable_exception_autocapture=True,
127
+ capture_exception_code_variables=False,
128
+ project_root=os.path.dirname(os.path.abspath(__file__))
129
+ )
130
+
131
+ def process_data():
132
+ bank = "should_be_masked"
133
+ __dunder_var = "should_be_visible"
134
+
135
+ 1/0
136
+
137
+ with posthog.new_context(client=posthog_client):
138
+ posthog.set_capture_exception_code_variables_context(True)
139
+ posthog.set_code_variables_mask_patterns_context([r"(?i).*bank.*"])
140
+ posthog.set_code_variables_ignore_patterns_context([])
141
+
142
+ process_data()
143
+ """
144
+ )
145
+ )
146
+
147
+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
148
+ subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)
149
+
150
+ output = excinfo.value.output
151
+
152
+ assert b"ZeroDivisionError" in output
153
+ assert b"code_variables" in output
154
+ assert b"'bank': '$$_posthog_redacted_based_on_masking_rules_$$'" in output
155
+ assert b"'__dunder_var': 'should_be_visible'" in output
156
+
157
+
158
+ def test_code_variables_size_limiter(tmpdir):
159
+ app = tmpdir.join("app.py")
160
+ app.write(
161
+ dedent(
162
+ """
163
+ import os
164
+ from posthog import Posthog
165
+
166
+ posthog = Posthog(
167
+ 'phc_x',
168
+ host='https://eu.i.posthog.com',
169
+ debug=True,
170
+ enable_exception_autocapture=True,
171
+ capture_exception_code_variables=True,
172
+ project_root=os.path.dirname(os.path.abspath(__file__))
173
+ )
174
+
175
+ def trigger_error():
176
+ var_a = "a" * 2000
177
+ var_b = "b" * 2000
178
+ var_c = "c" * 2000
179
+ var_d = "d" * 2000
180
+ var_e = "e" * 2000
181
+ var_f = "f" * 2000
182
+ var_g = "g" * 2000
183
+
184
+ 1/0
185
+
186
+ def intermediate_function():
187
+ var_h = "h" * 2000
188
+ var_i = "i" * 2000
189
+ var_j = "j" * 2000
190
+ var_k = "k" * 2000
191
+ var_l = "l" * 2000
192
+ var_m = "m" * 2000
193
+ var_n = "n" * 2000
194
+
195
+ trigger_error()
196
+
197
+ def process_data():
198
+ var_o = "o" * 2000
199
+ var_p = "p" * 2000
200
+ var_q = "q" * 2000
201
+ var_r = "r" * 2000
202
+ var_s = "s" * 2000
203
+ var_t = "t" * 2000
204
+ var_u = "u" * 2000
205
+
206
+ intermediate_function()
207
+
208
+ process_data()
209
+ """
210
+ )
211
+ )
212
+
213
+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
214
+ subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)
215
+
216
+ output = excinfo.value.output.decode("utf-8")
217
+
218
+ assert "ZeroDivisionError" in output
219
+ assert "code_variables" in output
220
+
221
+ captured_vars = []
222
+ for var_name in [
223
+ "var_a",
224
+ "var_b",
225
+ "var_c",
226
+ "var_d",
227
+ "var_e",
228
+ "var_f",
229
+ "var_g",
230
+ "var_h",
231
+ "var_i",
232
+ "var_j",
233
+ "var_k",
234
+ "var_l",
235
+ "var_m",
236
+ "var_n",
237
+ "var_o",
238
+ "var_p",
239
+ "var_q",
240
+ "var_r",
241
+ "var_s",
242
+ "var_t",
243
+ "var_u",
244
+ ]:
245
+ if f"'{var_name}'" in output:
246
+ captured_vars.append(var_name)
247
+
248
+ assert len(captured_vars) > 0
249
+ assert len(captured_vars) < 21
250
+
251
+
252
+ def test_code_variables_disabled_capture(tmpdir):
253
+ app = tmpdir.join("app.py")
254
+ app.write(
255
+ dedent(
256
+ """
257
+ import os
258
+ from posthog import Posthog
259
+
260
+ posthog = Posthog(
261
+ 'phc_x',
262
+ host='https://eu.i.posthog.com',
263
+ debug=True,
264
+ enable_exception_autocapture=True,
265
+ capture_exception_code_variables=False,
266
+ project_root=os.path.dirname(os.path.abspath(__file__))
267
+ )
268
+
269
+ def trigger_error():
270
+ my_string = "hello world"
271
+ my_number = 42
272
+ my_bool = True
273
+
274
+ 1/0
275
+
276
+ trigger_error()
277
+ """
278
+ )
279
+ )
280
+
281
+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
282
+ subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)
283
+
284
+ output = excinfo.value.output.decode("utf-8")
285
+
286
+ assert "ZeroDivisionError" in output
287
+ assert "'code_variables':" not in output
288
+ assert '"code_variables":' not in output
289
+ assert "'my_string'" not in output
290
+ assert "'my_number'" not in output
291
+
292
+
293
+ def test_code_variables_enabled_then_disabled_in_context(tmpdir):
294
+ app = tmpdir.join("app.py")
295
+ app.write(
296
+ dedent(
297
+ """
298
+ import os
299
+ import posthog
300
+ from posthog import Posthog
301
+
302
+ posthog_client = Posthog(
303
+ 'phc_x',
304
+ host='https://eu.i.posthog.com',
305
+ debug=True,
306
+ enable_exception_autocapture=True,
307
+ capture_exception_code_variables=True,
308
+ project_root=os.path.dirname(os.path.abspath(__file__))
309
+ )
310
+
311
+ def process_data():
312
+ my_var = "should not be captured"
313
+ important_value = 123
314
+
315
+ 1/0
316
+
317
+ with posthog.new_context(client=posthog_client):
318
+ posthog.set_capture_exception_code_variables_context(False)
319
+
320
+ process_data()
321
+ """
322
+ )
323
+ )
324
+
325
+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
326
+ subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)
327
+
328
+ output = excinfo.value.output.decode("utf-8")
329
+
330
+ assert "ZeroDivisionError" in output
331
+ assert "'code_variables':" not in output
332
+ assert '"code_variables":' not in output
333
+ assert "'my_var'" not in output
334
+ assert "'important_value'" not in output
@@ -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 test_flag_with_multiple_variant_overrides(self, patch_flags):
2808
- patch_flags.return_value = {"featureFlags": {"beta-feature": "variant-1"}}
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": "Beta Feature",
2814
- "key": "beta-feature",
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": "test@posthog.com",
2829
- "operator": "exact",
2826
+ "value": "@vip.com",
2827
+ "operator": "icontains",
2830
2828
  }
2831
2829
  ],
2832
2830
  "rollout_percentage": 100,
2833
- "variant": "second-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": "first-variant",
2841
- "name": "First Variant",
2842
- "rollout_percentage": 50,
2843
- },
2844
- {
2845
- "key": "second-variant",
2846
- "name": "Second Variant",
2847
- "rollout_percentage": 25,
2837
+ "key": "control",
2838
+ "name": "Control",
2839
+ "rollout_percentage": 100,
2848
2840
  },
2849
2841
  {
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
- self.assertEqual(
2860
- client.get_feature_flag(
2861
- "beta-feature",
2862
- "test_id",
2863
- person_properties={"email": "test@posthog.com"},
2864
- ),
2865
- "second-variant",
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
- # decide not called because this can be evaluated locally
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")
@@ -3025,6 +3013,75 @@ class TestLocalEvaluation(unittest.TestCase):
3025
3013
  )
3026
3014
  self.assertEqual(patch_flags.call_count, 0)
3027
3015
 
3016
+ @mock.patch("posthog.client.flags")
3017
+ @mock.patch("posthog.client.get")
3018
+ def test_fallback_to_api_when_flag_has_static_cohort_in_multi_condition(
3019
+ self, patch_get, patch_flags
3020
+ ):
3021
+ """
3022
+ When a flag has multiple conditions and one contains a static cohort,
3023
+ the SDK should fallback to API for the entire flag, not just skip that
3024
+ condition and evaluate the next one locally.
3025
+
3026
+ This prevents returning wrong variants when later conditions could match
3027
+ locally but the user is actually in the static cohort.
3028
+ """
3029
+ client = Client(FAKE_TEST_API_KEY, personal_api_key=FAKE_TEST_API_KEY)
3030
+
3031
+ # Mock the local flags response - cohort 999 is NOT in cohorts map (static cohort)
3032
+ client.feature_flags = [
3033
+ {
3034
+ "id": 1,
3035
+ "key": "multi-condition-flag",
3036
+ "active": True,
3037
+ "filters": {
3038
+ "groups": [
3039
+ {
3040
+ "properties": [
3041
+ {"key": "id", "value": 999, "type": "cohort"}
3042
+ ],
3043
+ "rollout_percentage": 100,
3044
+ "variant": "set-1",
3045
+ },
3046
+ {
3047
+ "properties": [
3048
+ {
3049
+ "key": "$geoip_country_code",
3050
+ "operator": "exact",
3051
+ "value": ["DE"],
3052
+ "type": "person",
3053
+ }
3054
+ ],
3055
+ "rollout_percentage": 100,
3056
+ "variant": "set-8",
3057
+ },
3058
+ ],
3059
+ "multivariate": {
3060
+ "variants": [
3061
+ {"key": "set-1", "rollout_percentage": 50},
3062
+ {"key": "set-8", "rollout_percentage": 50},
3063
+ ]
3064
+ },
3065
+ },
3066
+ }
3067
+ ]
3068
+ client.cohorts = {} # Note: cohort 999 is NOT here - it's a static cohort
3069
+
3070
+ # Mock the API response - user is in the static cohort
3071
+ patch_flags.return_value = {"featureFlags": {"multi-condition-flag": "set-1"}}
3072
+
3073
+ result = client.get_feature_flag(
3074
+ "multi-condition-flag",
3075
+ "test-distinct-id",
3076
+ person_properties={"$geoip_country_code": "DE"},
3077
+ )
3078
+
3079
+ # Should return the API result (set-1), not local evaluation (set-8)
3080
+ self.assertEqual(result, "set-1")
3081
+
3082
+ # Verify API was called (fallback occurred)
3083
+ self.assertEqual(patch_flags.call_count, 1)
3084
+
3028
3085
 
3029
3086
  class TestMatchProperties(unittest.TestCase):
3030
3087
  def property(self, key, value, operator=None):
@@ -4018,6 +4075,60 @@ class TestCaptureCalls(unittest.TestCase):
4018
4075
 
4019
4076
  patch_capture.reset_mock()
4020
4077
 
4078
+ @mock.patch("posthog.client.flags")
4079
+ def test_fallback_to_api_in_get_feature_flag_payload_when_flag_has_static_cohort(
4080
+ self, patch_flags
4081
+ ):
4082
+ """
4083
+ Test that get_feature_flag_payload falls back to API when evaluating
4084
+ a flag with static cohorts, similar to get_feature_flag behavior.
4085
+ """
4086
+ client = Client(FAKE_TEST_API_KEY, personal_api_key=FAKE_TEST_API_KEY)
4087
+
4088
+ # Mock the local flags response - cohort 999 is NOT in cohorts map (static cohort)
4089
+ client.feature_flags = [
4090
+ {
4091
+ "id": 1,
4092
+ "name": "Multi-condition Flag",
4093
+ "key": "multi-condition-flag",
4094
+ "active": True,
4095
+ "filters": {
4096
+ "groups": [
4097
+ {
4098
+ "properties": [
4099
+ {"key": "id", "value": 999, "type": "cohort"}
4100
+ ],
4101
+ "rollout_percentage": 100,
4102
+ "variant": "variant-1",
4103
+ }
4104
+ ],
4105
+ "multivariate": {
4106
+ "variants": [{"key": "variant-1", "rollout_percentage": 100}]
4107
+ },
4108
+ "payloads": {"variant-1": '{"message": "local-payload"}'},
4109
+ },
4110
+ }
4111
+ ]
4112
+ client.cohorts = {} # Note: cohort 999 is NOT here - it's a static cohort
4113
+
4114
+ # Mock the API response - user is in the static cohort
4115
+ patch_flags.return_value = {
4116
+ "featureFlags": {"multi-condition-flag": "variant-1"},
4117
+ "featureFlagPayloads": {"multi-condition-flag": '{"message": "from-api"}'},
4118
+ }
4119
+
4120
+ # Call get_feature_flag_payload without match_value to trigger evaluation
4121
+ result = client.get_feature_flag_payload(
4122
+ "multi-condition-flag",
4123
+ "test-distinct-id",
4124
+ )
4125
+
4126
+ # Should return the API payload, not local payload
4127
+ self.assertEqual(result, {"message": "from-api"})
4128
+
4129
+ # Verify API was called (fallback occurred)
4130
+ self.assertEqual(patch_flags.call_count, 1)
4131
+
4021
4132
  @mock.patch.object(Client, "capture")
4022
4133
  @mock.patch("posthog.client.flags")
4023
4134
  def test_disable_geoip_get_flag_capture_call(self, patch_flags, patch_capture):
@@ -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)
posthog/version.py CHANGED
@@ -1,4 +1,4 @@
1
- VERSION = "6.7.2"
1
+ VERSION = "6.9.0"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  print(VERSION, end="") # noqa: T201
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: posthog
3
- Version: 6.7.2
3
+ Version: 6.9.0
4
4
  Summary: Integrate PostHog into any python application.
5
5
  Home-page: https://github.com/posthog/posthog-python
6
6
  Author: Posthog
@@ -1,54 +1,54 @@
1
- posthog/__init__.py,sha256=IQ-522ve1cw6pMIQ1DNiQkRPktx0gVTvJTTBH8hokCA,25762
1
+ posthog/__init__.py,sha256=v2NGzYdoz4GRqCMDxStesELHz3N1j9qhJcNx2FXFsq0,27022
2
2
  posthog/args.py,sha256=JUt0vbtF33IzLt3ARgsxMEYYnZo3RNS_LcK4-CjWaco,3298
3
- posthog/client.py,sha256=XgYXnJ6z6P8ZY1XTLDNipIYljaN8Bcv9yuZ96AKzL5A,71512
3
+ posthog/client.py,sha256=78sSBQiOszRwVfFVSJ46hpxJ5-mQmRoYUCLkqzz7Bmg,74535
4
4
  posthog/consumer.py,sha256=fdteMZ-deJGMpaQmHyznw_cwQG2Vvld1tmN9LUkZPrY,4608
5
- posthog/contexts.py,sha256=FWdM84ibI7jJEKpNGVnjTXi7PWBQRpDUjLOuFkLxFYI,9387
5
+ posthog/contexts.py,sha256=22z4KySFCTwPbz4OYsd_8EJpoc2H91NiLq9cscSvFfw,12600
6
6
  posthog/exception_capture.py,sha256=pmKtjQ6QY6zs4u_-ZA4H1gCyR3iI4sfqCQG_jwe_bKo,1774
7
- posthog/exception_utils.py,sha256=iutrudjJXwsAbOvMjAI6bKcIL9pzT5NaX-5cqHS9uZ8,26687
8
- posthog/feature_flags.py,sha256=Jn41jAMvHZ6dMW3bSS5emvvz5Uipc3MFm0ZKoy2KtM0,21856
7
+ posthog/exception_utils.py,sha256=nn2ue5Xmj1Rv5a6WWK1toScjv4Y2PxPRbVD41tbfKXA,31848
8
+ posthog/feature_flags.py,sha256=4xAcYEpa97b5Lv9bIo5JHbCO6lhYBnH5EmJ2MrjbU3k,22517
9
9
  posthog/poller.py,sha256=jBz5rfH_kn_bBz7wCB46Fpvso4ttx4uzqIZWvXBCFmQ,595
10
10
  posthog/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  posthog/request.py,sha256=CaONBN7a5RD8xiSShVMgHEd9XxKWM6ZQTLZypiqABhA,6168
12
12
  posthog/types.py,sha256=Dl3aFGX9XUR0wMmK12r2s5Hjan9jL4HpQ9GHpVcEq5U,10207
13
13
  posthog/utils.py,sha256=-0w-OLcCaoldkbBebPzQyBzLJSo9G9yBOg8NDVz7La8,16088
14
- posthog/version.py,sha256=5_SqKJ01JbRPG9x4t8JTHffIB0KktqfXyvL6EK2L4Vg,87
14
+ posthog/version.py,sha256=qTlEuCWb-slrdA36sMFDZPyA5fyBwCpQaHtWJmuEIgI,87
15
15
  posthog/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  posthog/ai/sanitization.py,sha256=owipZ4eJYtd4JTI-CM_klatclXaeaIec3XJBOUfsOnQ,5770
17
- posthog/ai/types.py,sha256=OsB6u855BdZNl5TyVx6Bxm80fT0dfbfnL9Yr5GsIbOQ,3755
18
- posthog/ai/utils.py,sha256=VgRdBHbe6j5Uux-Pq2KyMcHo2LrzoFp98GxAySVGEOI,20639
17
+ posthog/ai/types.py,sha256=arX98hR1PIPeJ3vFikxTlACIh1xPp6aEUw1gBLcKoB0,3273
18
+ posthog/ai/utils.py,sha256=pMqL_Aydf08EvUuSVJ1SsIpNwaom6qYIoLNOvMBNSHU,21475
19
19
  posthog/ai/anthropic/__init__.py,sha256=8nTvETZzkfW-P3zBMmp06GOHs0N-xyOGu7Oa4di_lno,669
20
- posthog/ai/anthropic/anthropic.py,sha256=aU-P06osLjwhbulVfpaqIAI0LHHsLvD_ZNXvRYWzUOA,8731
21
- posthog/ai/anthropic/anthropic_async.py,sha256=GOHBa3LvLTGRopiWKPEomU16HNkXRk97Jq5Q647UmTM,10107
22
- posthog/ai/anthropic/anthropic_converter.py,sha256=HAgD6sj0gHlmNPhNWycevE3ZVIjeD2jWgIvHSBjLVIk,11397
20
+ posthog/ai/anthropic/anthropic.py,sha256=UWyM6ryl5_VNQImaBi1RHN7tKXwkqaxy4yaXyPSkDp8,8669
21
+ posthog/ai/anthropic/anthropic_async.py,sha256=ppWHiVp4hTl62Zr3jIwXXidOsqhrwx6iHM3ukG7WiPM,8789
22
+ posthog/ai/anthropic/anthropic_converter.py,sha256=prvaxt_R9kn9IbkxG_mLrw4kexT4i6T80U-6yhaZCNk,13053
23
23
  posthog/ai/anthropic/anthropic_providers.py,sha256=Q_v7U4wgieIkvii-Bqh4pLx5pEgbrHmgsCG8lUkKb_0,2103
24
24
  posthog/ai/gemini/__init__.py,sha256=JV_9-gBR87leHgZW4XAYZP7LSl4YaXeuhqDUpA8HygA,383
25
- posthog/ai/gemini/gemini.py,sha256=O3THgdoMWghlQXgnP-fSQbscXxzSiL5FTyE_JKH4tUg,14897
26
- posthog/ai/gemini/gemini_converter.py,sha256=fB1hedKInKXQAV0XpBxB8edznDI8_LNnJWYHqms5CEU,13486
25
+ posthog/ai/gemini/gemini.py,sha256=-c2MnBeask6SrAbFZ7XXZ_OMcuglTBRdnFe_ROVgXWQ,14972
26
+ posthog/ai/gemini/gemini_converter.py,sha256=WFF1gzLGk1DId-1yrA9nDYMd9PXgbVsyhU3wgKjAJTE,18731
27
27
  posthog/ai/langchain/__init__.py,sha256=9CqAwLynTGj3ASAR80C3PmdTdrYGmu99tz0JL-HPFgI,70
28
- posthog/ai/langchain/callbacks.py,sha256=vkcOUch82N6BJPDTZTmTHVrRu0ZpLdFZqgt_LEqwGPg,29491
28
+ posthog/ai/langchain/callbacks.py,sha256=5cjBFTNmHYhWxDWSAjIRfHvTebO8M6D5D37CR9vvoAg,30261
29
29
  posthog/ai/openai/__init__.py,sha256=u4OuUT7k1NgFj0TrxjuyegOg7a_UA8nAU6a-Hszr0OM,490
30
- posthog/ai/openai/openai.py,sha256=0kIPmQuc2Y1d5AoWSbJfF3tJSvDLak1ha1E5eUOPnns,20231
31
- posthog/ai/openai/openai_async.py,sha256=Ix-3KNOCEhSs1BcBPNF2Is2wA-zOHAlHxIKIbihof4Y,21687
32
- posthog/ai/openai/openai_converter.py,sha256=AgF0VX6-I9UtS5fRby3XNAIIwV-o2000KaW6QVIcPtk,19543
30
+ posthog/ai/openai/openai.py,sha256=ts95vdvWH7h0TX4FpLLK_wU_7H0MP3eZBEg0S-lsCKw,20127
31
+ posthog/ai/openai/openai_async.py,sha256=Ebd6_H3Zf3wGPycVJd_vOd3ZVoO3Mf3ZV339BExQd6Q,22436
32
+ posthog/ai/openai/openai_converter.py,sha256=_T7Nx5gzGlklbu0iZjj8qaBB4W_IrnSFNUkUOav3TBE,25466
33
33
  posthog/ai/openai/openai_providers.py,sha256=zQIFTXHS2-dBKQX7FZxTFo7rIj5iiN7VHm9_2RzuDs8,3941
34
34
  posthog/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- posthog/integrations/django.py,sha256=opHfViMcWTKFh_qQTavrNJ6qI0cc7-35UFA7dz0Lhfo,6777
35
+ posthog/integrations/django.py,sha256=9X37yCF-T-MXUsxqkqjBWG3kdgOCyQYYNJQG_ZlwbRg,12633
36
36
  posthog/test/__init__.py,sha256=VYgM6xPbJbvS-xhIcDiBRs0MFC9V_jT65uNeerCz_rM,299
37
37
  posthog/test/test_before_send.py,sha256=3546WKlk8rF6bhvqhwcxAsjJovDw0Hf8yTvcYGbrhyI,7912
38
- posthog/test/test_client.py,sha256=LVkwR0EcqjlSXcAwTPliqKiJQ5Pq4Dw-_JoFeviizDo,94405
38
+ posthog/test/test_client.py,sha256=F-jUA0uKgHpVLOdnen2j6WSTp6whlJcpZdSecLoREFg,96273
39
39
  posthog/test/test_consumer.py,sha256=HRDXSH0IPpCfo5yHs23n-0VzFyGSjWBKLEa8XNtU3_Y,7080
40
40
  posthog/test/test_contexts.py,sha256=GDYpQNGhdzyA3--ia3WPao_4dqyLUpkWm1NMVm2L-So,7004
41
- posthog/test/test_exception_capture.py,sha256=Zs6PP6xAZpHaHB1FDHSqgkPNlhC7iOhmj1kqwui4Xe8,1054
41
+ posthog/test/test_exception_capture.py,sha256=tit980vqCvAq8W2UGJN-Mcz_BIKI4XZzmEU4y1Y4YaI,8939
42
42
  posthog/test/test_feature_flag.py,sha256=yIMJkoRtdJr91Y6Rb0PPlpZWBIR394TgWhccnlf-vYE,6815
43
43
  posthog/test/test_feature_flag_result.py,sha256=jbdTgqlFbgvUlAoRWjguk3IvuzXgN2qbfn77gF_SqJU,15871
44
- posthog/test/test_feature_flags.py,sha256=SuE5Yame9sWd7lgt7LFdAPskUVRT0RXA5mnSMHkVHEI,213004
45
- posthog/test/test_module.py,sha256=DGuD1O5czaEPICQBX1B--x_pHG6vdSfwgWZTqH2D9tM,1061
44
+ posthog/test/test_feature_flags.py,sha256=JCSFtHhh60WoClmmuBMctSAOchFNqnZPlpfdi37zTMw,217298
45
+ posthog/test/test_module.py,sha256=CERR0dTPGsAmd7YBxK0yKeB2Zr2b_Lv7hNQoeJauc9I,813
46
46
  posthog/test/test_request.py,sha256=l19WVyZQc4Iqmh_bpnAFOj4nGRpDK1iO-o5aJDQfFdo,4449
47
47
  posthog/test/test_size_limited_dict.py,sha256=Wom7BkzpHmusHilZy0SV3PNzhw7ucuQgqrx86jf8euo,765
48
48
  posthog/test/test_types.py,sha256=csLuBiz6RMV36cpg9LVIor4Khq6MfjjGxYXodx5VttY,7586
49
49
  posthog/test/test_utils.py,sha256=NUs2bgqrVuMdnKRq52syizgglt5_7wxxZl3dDMun-Tg,9602
50
- posthog-6.7.2.dist-info/licenses/LICENSE,sha256=wGf9JBotDkSygFj43m49oiKlFnpMnn97keiZKF-40vE,2450
51
- posthog-6.7.2.dist-info/METADATA,sha256=TAvQSB8e14DishVRV6jzbwqa_imXk4L4FPpwxChsrQg,6015
52
- posthog-6.7.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
- posthog-6.7.2.dist-info/top_level.txt,sha256=7FBLsRjIUHVKQsXIhozuI3k-mun1tapp8iZO9EmUPEw,8
54
- posthog-6.7.2.dist-info/RECORD,,
50
+ posthog-6.9.0.dist-info/licenses/LICENSE,sha256=wGf9JBotDkSygFj43m49oiKlFnpMnn97keiZKF-40vE,2450
51
+ posthog-6.9.0.dist-info/METADATA,sha256=1YBEEJBiVFhOm-4GFjBTC-oWjJH2NOMqpGqWOSUXO5s,6015
52
+ posthog-6.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
+ posthog-6.9.0.dist-info/top_level.txt,sha256=7FBLsRjIUHVKQsXIhozuI3k-mun1tapp8iZO9EmUPEw,8
54
+ posthog-6.9.0.dist-info/RECORD,,