posthoganalytics 6.7.13__tar.gz → 6.7.14__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.
- {posthoganalytics-6.7.13/posthoganalytics.egg-info → posthoganalytics-6.7.14}/PKG-INFO +1 -1
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/client.py +1 -2
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/integrations/django.py +81 -13
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/version.py +1 -1
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14/posthoganalytics.egg-info}/PKG-INFO +1 -1
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/pyproject.toml +6 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/LICENSE +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/MANIFEST.in +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/README.md +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic_async.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic_converter.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic_providers.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/gemini/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/gemini/gemini.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/gemini/gemini_converter.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/langchain/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/langchain/callbacks.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_async.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_converter.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_providers.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/sanitization.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/types.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/utils.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/args.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/consumer.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/contexts.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/exception_capture.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/exception_utils.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/feature_flags.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/integrations/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/poller.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/py.typed +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/request.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/__init__.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_before_send.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_client.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_consumer.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_contexts.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_exception_capture.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_feature_flag.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_feature_flag_result.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_feature_flags.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_module.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_request.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_size_limited_dict.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_types.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_utils.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/types.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/utils.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics.egg-info/SOURCES.txt +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics.egg-info/dependency_links.txt +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics.egg-info/requires.txt +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics.egg-info/top_level.txt +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/setup.cfg +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/setup.py +0 -0
- {posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/setup_analytics.py +0 -0
|
@@ -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,
|
|
6
|
+
from typing import Any, Dict, Optional, Union
|
|
7
7
|
from typing_extensions import Unpack
|
|
8
8
|
from uuid import uuid4
|
|
9
9
|
|
|
@@ -60,7 +60,6 @@ from posthoganalytics.utils import (
|
|
|
60
60
|
SizeLimitedDict,
|
|
61
61
|
clean,
|
|
62
62
|
guess_timezone,
|
|
63
|
-
remove_trailing_slash,
|
|
64
63
|
system_context,
|
|
65
64
|
)
|
|
66
65
|
from posthoganalytics.version import VERSION
|
|
@@ -112,9 +112,18 @@ class PosthogContextMiddleware:
|
|
|
112
112
|
|
|
113
113
|
def extract_tags(self, request):
|
|
114
114
|
# type: (HttpRequest) -> Dict[str, Any]
|
|
115
|
-
tags
|
|
115
|
+
"""Extract tags from request in sync context."""
|
|
116
|
+
user_id, user_email = self.extract_request_user(request)
|
|
117
|
+
return self._build_tags(request, user_id, user_email)
|
|
118
|
+
|
|
119
|
+
def _build_tags(self, request, user_id, user_email):
|
|
120
|
+
# type: (HttpRequest, Optional[str], Optional[str]) -> Dict[str, Any]
|
|
121
|
+
"""
|
|
122
|
+
Build tags dict from request and user info.
|
|
116
123
|
|
|
117
|
-
|
|
124
|
+
Centralized tag extraction logic used by both sync and async paths.
|
|
125
|
+
"""
|
|
126
|
+
tags = {}
|
|
118
127
|
|
|
119
128
|
# Extract session ID from X-POSTHOG-SESSION-ID header
|
|
120
129
|
session_id = request.headers.get("X-POSTHOG-SESSION-ID")
|
|
@@ -166,21 +175,78 @@ class PosthogContextMiddleware:
|
|
|
166
175
|
return tags
|
|
167
176
|
|
|
168
177
|
def extract_request_user(self, request):
|
|
169
|
-
|
|
170
|
-
email
|
|
171
|
-
|
|
178
|
+
# type: (HttpRequest) -> tuple[Optional[str], Optional[str]]
|
|
179
|
+
"""Extract user ID and email from request in sync context."""
|
|
172
180
|
user = getattr(request, "user", None)
|
|
181
|
+
return self._resolve_user_details(user)
|
|
173
182
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
async def aextract_tags(self, request):
|
|
184
|
+
# type: (HttpRequest) -> Dict[str, Any]
|
|
185
|
+
"""
|
|
186
|
+
Async version of extract_tags for use in async request handling.
|
|
187
|
+
|
|
188
|
+
Uses await request.auser() instead of request.user to avoid
|
|
189
|
+
SynchronousOnlyOperation in async context.
|
|
190
|
+
|
|
191
|
+
Follows Django's naming convention for async methods (auser, asave, etc.).
|
|
192
|
+
"""
|
|
193
|
+
user_id, user_email = await self.aextract_request_user(request)
|
|
194
|
+
return self._build_tags(request, user_id, user_email)
|
|
195
|
+
|
|
196
|
+
async def aextract_request_user(self, request):
|
|
197
|
+
# type: (HttpRequest) -> tuple[Optional[str], Optional[str]]
|
|
198
|
+
"""
|
|
199
|
+
Async version of extract_request_user for use in async request handling.
|
|
179
200
|
|
|
201
|
+
Uses await request.auser() instead of request.user to avoid
|
|
202
|
+
SynchronousOnlyOperation in async context.
|
|
203
|
+
|
|
204
|
+
Follows Django's naming convention for async methods (auser, asave, etc.).
|
|
205
|
+
"""
|
|
206
|
+
auser = getattr(request, "auser", None)
|
|
207
|
+
if callable(auser):
|
|
180
208
|
try:
|
|
181
|
-
|
|
209
|
+
user = await auser()
|
|
210
|
+
return self._resolve_user_details(user)
|
|
182
211
|
except Exception:
|
|
183
|
-
|
|
212
|
+
# If auser() fails, return empty - don't break the request
|
|
213
|
+
# Real errors (permissions, broken auth) will be logged by Django
|
|
214
|
+
return None, None
|
|
215
|
+
|
|
216
|
+
# Fallback for test requests without auser
|
|
217
|
+
return None, None
|
|
218
|
+
|
|
219
|
+
def _resolve_user_details(self, user):
|
|
220
|
+
# type: (Any) -> tuple[Optional[str], Optional[str]]
|
|
221
|
+
"""
|
|
222
|
+
Extract user ID and email from a user object.
|
|
223
|
+
|
|
224
|
+
Handles both authenticated and unauthenticated users, as well as
|
|
225
|
+
legacy Django where is_authenticated was a method.
|
|
226
|
+
"""
|
|
227
|
+
user_id = None
|
|
228
|
+
email = None
|
|
229
|
+
|
|
230
|
+
if user is None:
|
|
231
|
+
return user_id, email
|
|
232
|
+
|
|
233
|
+
# Handle is_authenticated (property in modern Django, method in legacy)
|
|
234
|
+
is_authenticated = getattr(user, "is_authenticated", False)
|
|
235
|
+
if callable(is_authenticated):
|
|
236
|
+
is_authenticated = is_authenticated()
|
|
237
|
+
|
|
238
|
+
if not is_authenticated:
|
|
239
|
+
return user_id, email
|
|
240
|
+
|
|
241
|
+
# Extract user primary key
|
|
242
|
+
user_pk = getattr(user, "pk", None)
|
|
243
|
+
if user_pk is not None:
|
|
244
|
+
user_id = str(user_pk)
|
|
245
|
+
|
|
246
|
+
# Extract user email
|
|
247
|
+
user_email = getattr(user, "email", None)
|
|
248
|
+
if user_email:
|
|
249
|
+
email = str(user_email)
|
|
184
250
|
|
|
185
251
|
return user_id, email
|
|
186
252
|
|
|
@@ -211,12 +277,14 @@ class PosthogContextMiddleware:
|
|
|
211
277
|
Asynchronous entry point for async request handling.
|
|
212
278
|
|
|
213
279
|
This method is called when the middleware chain is async.
|
|
280
|
+
Uses aextract_tags() which calls request.auser() to avoid
|
|
281
|
+
SynchronousOnlyOperation when accessing user in async context.
|
|
214
282
|
"""
|
|
215
283
|
if self.request_filter and not self.request_filter(request):
|
|
216
284
|
return await self.get_response(request)
|
|
217
285
|
|
|
218
286
|
with contexts.new_context(self.capture_exceptions, client=self.client):
|
|
219
|
-
for k, v in self.
|
|
287
|
+
for k, v in (await self.aextract_tags(request)).items():
|
|
220
288
|
contexts.tag(k, v)
|
|
221
289
|
|
|
222
290
|
return await self.get_response(request)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/__init__.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/anthropic/anthropic_async.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/gemini/gemini_converter.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/langchain/__init__.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/langchain/callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_async.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_converter.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/ai/openai/openai_providers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/integrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_before_send.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_exception_capture.py
RENAMED
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_feature_flag.py
RENAMED
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_feature_flags.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics/test/test_size_limited_dict.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{posthoganalytics-6.7.13 → posthoganalytics-6.7.14}/posthoganalytics.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|