Skip to content

Commit 501a111

Browse files
committed
Merge branch 'master' of https://github.com/PostHog/posthog-python into feat/encrypted-flag-payloads
2 parents 0df99ea + 1b57a96 commit 501a111

18 files changed

+530
-131
lines changed

.github/workflows/ci.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ jobs:
1313
with:
1414
fetch-depth: 1
1515

16-
- name: Set up Python 3.8
16+
- name: Set up Python 3.11
1717
uses: actions/setup-python@v2
1818
with:
19-
python-version: 3.8
19+
python-version: 3.11.11
2020

2121
- uses: actions/cache@v3
2222
with:
@@ -42,19 +42,26 @@ jobs:
4242
run: |
4343
isort --check-only .
4444
45+
- name: Check types with mypy
46+
run: |
47+
mypy --no-site-packages --config-file mypy.ini . | mypy-baseline filter
48+
4549
tests:
46-
name: Python tests
50+
name: Python ${{ matrix.python-version }} tests
4751
runs-on: ubuntu-latest
52+
strategy:
53+
matrix:
54+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
4855

4956
steps:
5057
- uses: actions/checkout@v2
5158
with:
5259
fetch-depth: 1
5360

54-
- name: Set up Python 3.9
61+
- name: Set up Python ${{ matrix.python-version }}
5562
uses: actions/setup-python@v2
5663
with:
57-
python-version: 3.9
64+
python-version: ${{ matrix.python-version }}
5865

5966
- name: Install requirements.txt dependencies with pip
6067
run: |

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1+
## 3.13.0 - 2025-02-12
2+
3+
1. Automatically retry connection errors
4+
5+
## 3.12.1 - 2025-02-11
6+
7+
1. Fix mypy support for 3.12.0
8+
2. Deprecate `is_simple_flag`
9+
10+
## 3.12.0 - 2025-02-11
11+
12+
1. Add support for OpenAI beta parse API.
13+
2. Deprecate `context` parameter
14+
115
## 3.11.1 - 2025-02-06
216

317
1. Fix LangChain callback handler to capture parent run ID.
418

519
## 3.11.0 - 2025-01-28
620

721
1. Add the `$ai_span` event to the LangChain callback handler to capture the input and output of intermediary chains.
22+
823
> LLM observability naming change: event property `$ai_trace_name` is now `$ai_span_name`.
924
1025
2. Fix serialiazation of Pydantic models in methods.

llm_observability_examples.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import os
22
import uuid
33

4+
from pydantic import BaseModel
5+
46
import posthog
57
from posthog.ai.openai import AsyncOpenAI, OpenAI
68

79
# Example credentials - replace these with your own or use environment variables
810
posthog.project_api_key = os.getenv("POSTHOG_PROJECT_API_KEY", "your-project-api-key")
9-
posthog.personal_api_key = os.getenv("POSTHOG_PERSONAL_API_KEY", "your-personal-api-key")
1011
posthog.host = os.getenv("POSTHOG_HOST", "http://localhost:8000") # Or https://app.posthog.com
1112
posthog.debug = True
1213
# change this to False to see usage events
@@ -31,10 +32,11 @@ def main_sync():
3132
groups = {"company": "test_company"}
3233

3334
try:
34-
basic_openai_call(distinct_id, trace_id, properties, groups)
35-
streaming_openai_call(distinct_id, trace_id, properties, groups)
36-
embedding_openai_call(distinct_id, trace_id, properties, groups)
37-
image_openai_call()
35+
# basic_openai_call(distinct_id, trace_id, properties, groups)
36+
# streaming_openai_call(distinct_id, trace_id, properties, groups)
37+
# embedding_openai_call(distinct_id, trace_id, properties, groups)
38+
# image_openai_call()
39+
beta_openai_call(distinct_id, trace_id, properties, groups)
3840
except Exception as e:
3941
print("Error during OpenAI call:", str(e))
4042

@@ -187,10 +189,32 @@ async def embedding_async_openai_call(posthog_distinct_id, posthog_trace_id, pos
187189
return response
188190

189191

192+
class CalendarEvent(BaseModel):
193+
name: str
194+
date: str
195+
participants: list[str]
196+
197+
198+
def beta_openai_call(distinct_id, trace_id, properties, groups):
199+
response = openai_client.beta.chat.completions.parse(
200+
model="gpt-4o-mini",
201+
messages=[
202+
{"role": "system", "content": "Extract the event information."},
203+
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
204+
],
205+
response_format=CalendarEvent,
206+
posthog_distinct_id=distinct_id,
207+
posthog_trace_id=trace_id,
208+
posthog_properties=properties,
209+
posthog_groups=groups,
210+
)
211+
print(response)
212+
return response
213+
214+
190215
# HOW TO RUN:
191216
# comment out one of these to run the other
192217

193218
if __name__ == "__main__":
194219
main_sync()
195-
196220
# asyncio.run(main_async())

mypy-baseline.txt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
posthog/utils.py:0: error: Library stubs not installed for "six" [import-untyped]
2+
posthog/utils.py:0: error: Library stubs not installed for "dateutil.tz" [import-untyped]
3+
posthog/utils.py:0: error: Statement is unreachable [unreachable]
4+
posthog/utils.py:0: error: Argument 1 to "join" of "str" has incompatible type "AttributeError"; expected "Iterable[str]" [arg-type]
5+
posthog/request.py:0: error: Library stubs not installed for "requests" [import-untyped]
6+
posthog/request.py:0: note: Hint: "python3 -m pip install types-requests"
7+
posthog/request.py:0: error: Library stubs not installed for "dateutil.tz" [import-untyped]
8+
posthog/request.py:0: error: Incompatible types in assignment (expression has type "bytes", variable has type "str") [assignment]
9+
posthog/consumer.py:0: error: Name "Empty" already defined (possibly by an import) [no-redef]
10+
posthog/consumer.py:0: error: Need type annotation for "items" (hint: "items: list[<type>] = ...") [var-annotated]
11+
posthog/consumer.py:0: error: Unsupported operand types for <= ("int" and "str") [operator]
12+
posthog/consumer.py:0: note: Right operand is of type "int | str"
13+
posthog/consumer.py:0: error: Unsupported operand types for < ("str" and "int") [operator]
14+
posthog/consumer.py:0: note: Left operand is of type "int | str"
15+
posthog/feature_flags.py:0: error: Library stubs not installed for "dateutil" [import-untyped]
16+
posthog/feature_flags.py:0: error: Library stubs not installed for "dateutil.relativedelta" [import-untyped]
17+
posthog/feature_flags.py:0: error: Unused "type: ignore" comment [unused-ignore]
18+
posthog/client.py:0: error: Library stubs not installed for "dateutil.tz" [import-untyped]
19+
posthog/client.py:0: note: Hint: "python3 -m pip install types-python-dateutil"
20+
posthog/client.py:0: note: (or run "mypy --install-types" to install all missing stub packages)
21+
posthog/client.py:0: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
22+
posthog/client.py:0: error: Library stubs not installed for "six" [import-untyped]
23+
posthog/client.py:0: note: Hint: "python3 -m pip install types-six"
24+
posthog/client.py:0: error: Name "queue" already defined (by an import) [no-redef]
25+
posthog/client.py:0: error: Need type annotation for "queue" [var-annotated]
26+
posthog/client.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
27+
simulator.py:0: error: Unexpected keyword argument "anonymous_id" for "capture" [call-arg]
28+
posthog/__init__.py:0: note: "capture" defined here
29+
simulator.py:0: error: Unexpected keyword argument "anonymous_id" for "identify" [call-arg]
30+
posthog/__init__.py:0: note: "identify" defined here
31+
simulator.py:0: error: Unexpected keyword argument "traits" for "identify" [call-arg]
32+
posthog/__init__.py:0: note: "identify" defined here
33+
example.py:0: error: Statement is unreachable [unreachable]
34+
posthog/sentry/posthog_integration.py:0: error: Statement is unreachable [unreachable]
35+
posthog/ai/utils.py:0: error: Need type annotation for "output" (hint: "output: list[<type>] = ...") [var-annotated]
36+
posthog/ai/utils.py:0: error: Function "builtins.any" is not valid as a type [valid-type]
37+
posthog/ai/utils.py:0: note: Perhaps you meant "typing.Any" instead of "any"?
38+
posthog/ai/utils.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
39+
posthog/ai/utils.py:0: error: Function "builtins.any" is not valid as a type [valid-type]
40+
posthog/ai/utils.py:0: note: Perhaps you meant "typing.Any" instead of "any"?
41+
posthog/ai/utils.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
42+
sentry_django_example/sentry_django_example/settings.py:0: error: Need type annotation for "ALLOWED_HOSTS" (hint: "ALLOWED_HOSTS: list[<type>] = ...") [var-annotated]
43+
sentry_django_example/sentry_django_example/settings.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "None") [assignment]
44+
posthog/ai/openai/openai_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
45+
posthog/ai/openai/openai_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
46+
posthog/ai/openai/openai_async.py:0: error: Unpacked dict entry 11 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item]
47+
posthog/ai/openai/openai_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
48+
posthog/ai/openai/openai_async.py:0: error: Unpacked dict entry 8 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item]
49+
posthog/ai/openai/openai.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
50+
posthog/ai/openai/openai.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
51+
posthog/ai/openai/openai.py:0: error: Unpacked dict entry 11 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item]
52+
posthog/ai/openai/openai.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
53+
posthog/ai/openai/openai.py:0: error: Unpacked dict entry 8 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item]
54+
posthog/ai/anthropic/anthropic_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
55+
posthog/ai/anthropic/anthropic_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
56+
posthog/ai/anthropic/anthropic_async.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
57+
posthog/ai/anthropic/anthropic.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
58+
posthog/ai/anthropic/anthropic.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
59+
posthog/ai/anthropic/anthropic.py:0: error: Incompatible types in assignment (expression has type "UUID", variable has type "str | None") [assignment]
60+
llm_observability_examples.py:0: error: Argument "posthog_client" to "OpenAI" has incompatible type Module; expected "Client" [arg-type]
61+
llm_observability_examples.py:0: error: Argument "posthog_client" to "AsyncOpenAI" has incompatible type Module; expected "Client" [arg-type]

mypy.ini

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[mypy]
2+
python_version = 3.11
3+
plugins =
4+
pydantic.mypy
5+
strict_optional = True
6+
no_implicit_optional = True
7+
warn_unused_ignores = True
8+
check_untyped_defs = True
9+
warn_unreachable = True
10+
strict_equality = True
11+
ignore_missing_imports = True
12+
13+
[mypy-django.*]
14+
ignore_missing_imports = True
15+
16+
[mypy-sentry_sdk.*]
17+
ignore_missing_imports = True
18+
19+
[mypy-posthog.test.*]
20+
ignore_errors = True
21+
22+
[mypy-posthog.*.test.*]
23+
ignore_errors = True
24+
25+
[mypy-openai.*]
26+
ignore_missing_imports = True
27+
28+
[mypy-langchain.*]
29+
ignore_missing_imports = True
30+
31+
[mypy-langchain_core.*]
32+
ignore_missing_imports = True
33+
34+
[mypy-anthropic.*]
35+
ignore_missing_imports = True
36+
37+
[mypy-httpx.*]
38+
ignore_missing_imports = True

posthog/__init__.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime # noqa: F401
2+
import warnings
23
from typing import Callable, Dict, List, Optional, Tuple # noqa: F401
34

45
from posthog.client import Client
@@ -64,6 +65,14 @@ def capture(
6465
posthog.capture('distinct id', 'purchase', groups={'company': 'id:5'})
6566
```
6667
"""
68+
69+
if context is not None:
70+
warnings.warn(
71+
"The 'context' parameter is deprecated and will be removed in a future version.",
72+
DeprecationWarning,
73+
stacklevel=2,
74+
)
75+
6776
return _proxy(
6877
"capture",
6978
distinct_id=distinct_id,
@@ -102,6 +111,14 @@ def identify(
102111
})
103112
```
104113
"""
114+
115+
if context is not None:
116+
warnings.warn(
117+
"The 'context' parameter is deprecated and will be removed in a future version.",
118+
DeprecationWarning,
119+
stacklevel=2,
120+
)
121+
105122
return _proxy(
106123
"identify",
107124
distinct_id=distinct_id,
@@ -137,6 +154,14 @@ def set(
137154
})
138155
```
139156
"""
157+
158+
if context is not None:
159+
warnings.warn(
160+
"The 'context' parameter is deprecated and will be removed in a future version.",
161+
DeprecationWarning,
162+
stacklevel=2,
163+
)
164+
140165
return _proxy(
141166
"set",
142167
distinct_id=distinct_id,
@@ -172,6 +197,14 @@ def set_once(
172197
})
173198
```
174199
"""
200+
201+
if context is not None:
202+
warnings.warn(
203+
"The 'context' parameter is deprecated and will be removed in a future version.",
204+
DeprecationWarning,
205+
stacklevel=2,
206+
)
207+
175208
return _proxy(
176209
"set_once",
177210
distinct_id=distinct_id,
@@ -208,6 +241,14 @@ def group_identify(
208241
})
209242
```
210243
"""
244+
245+
if context is not None:
246+
warnings.warn(
247+
"The 'context' parameter is deprecated and will be removed in a future version.",
248+
DeprecationWarning,
249+
stacklevel=2,
250+
)
251+
211252
return _proxy(
212253
"group_identify",
213254
group_type=group_type,
@@ -245,6 +286,14 @@ def alias(
245286
posthog.alias('anonymous session id', 'distinct id')
246287
```
247288
"""
289+
290+
if context is not None:
291+
warnings.warn(
292+
"The 'context' parameter is deprecated and will be removed in a future version.",
293+
DeprecationWarning,
294+
stacklevel=2,
295+
)
296+
248297
return _proxy(
249298
"alias",
250299
previous_id=previous_id,
@@ -288,6 +337,14 @@ def capture_exception(
288337
289338
```
290339
"""
340+
341+
if context is not None:
342+
warnings.warn(
343+
"The 'context' parameter is deprecated and will be removed in a future version.",
344+
DeprecationWarning,
345+
stacklevel=2,
346+
)
347+
291348
return _proxy(
292349
"capture_exception",
293350
exception=exception,

0 commit comments

Comments
 (0)