Skip to content

Commit fcbb34d

Browse files
authored
Merge branch 'master' into frank/pin-actions-versions
2 parents 19734aa + da69b68 commit fcbb34d

39 files changed

+2406
-555
lines changed

.github/workflows/release.yaml

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,43 @@
1-
name: 'Release'
1+
name: "Release"
22

33
on:
4-
- workflow_dispatch
4+
push:
5+
branches:
6+
- master
7+
paths:
8+
- "posthog/version.py"
9+
workflow_dispatch:
510

611
jobs:
7-
release:
8-
name: Publish release
9-
runs-on: ubuntu-20.04
10-
env:
11-
TWINE_USERNAME: __token__
12-
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
13-
steps:
14-
- name: Checkout the repository
15-
uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
16-
with:
17-
fetch-depth: 0
18-
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
12+
release:
13+
name: Publish release
14+
runs-on: ubuntu-latest
15+
env:
16+
TWINE_USERNAME: __token__
17+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
18+
steps:
19+
- name: Checkout the repository
20+
uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
21+
with:
22+
fetch-depth: 0
23+
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
1924

20-
- name: Set up Python
21-
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55
25+
- name: Set up Python
26+
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55
2227

23-
- name: Detect version
24-
run: echo "REPO_VERSION=$(python3 posthog/version.py)" >> $GITHUB_ENV
28+
- name: Detect version
29+
run: echo "REPO_VERSION=$(python3 posthog/version.py)" >> $GITHUB_ENV
2530

26-
- name: Prepare for building release
27-
run: pip install -U pip setuptools wheel twine
31+
- name: Prepare for building release
32+
run: pip install -U pip setuptools wheel twine
2833

29-
- name: Push release to PyPI
30-
run: make release && make release_analytics
34+
- name: Push release to PyPI
35+
run: make release && make release_analytics
3136

32-
- name: Create GitHub release
33-
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1
34-
env:
35-
GITHUB_TOKEN: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
36-
with:
37-
tag_name: v${{ env.REPO_VERSION }}
38-
release_name: ${{ env.REPO_VERSION }}
37+
- name: Create GitHub release
38+
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
41+
with:
42+
tag_name: v${{ env.REPO_VERSION }}
43+
release_name: ${{ env.REPO_VERSION }}

CHANGELOG.md

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,75 @@
1+
## 4.2.0 - 2025-05-22
2+
3+
Add support for google gemini
4+
5+
## 4.1.0 - 2025-05-22
6+
7+
Moved ai openai package to a composition approach over inheritance.
8+
9+
## 4.0.1 – 2025-04-29
10+
11+
1. Remove deprecated `monotonic` library. Use Python's core `time.monotonic` function instead
12+
2. Clarify Python 3.9+ is required
13+
14+
## 4.0.0 - 2025-04-24
15+
16+
1. Added new method `get_feature_flag_result` which returns a `FeatureFlagResult` object. This object breaks down the result of a feature flag into its enabled state, variant, and payload. The benefit of this method is it allows you to retrieve the result of a feature flag and its payload in a single API call. You can call `get_value` on the result to get the value of the feature flag, which is the same value returned by `get_feature_flag` (aka the string `variant` if the flag is a multivariate flag or the `boolean` value if the flag is a boolean flag).
17+
18+
Example:
19+
20+
```python
21+
result = posthog.get_feature_flag_result("my-flag", "distinct_id")
22+
print(result.enabled) # True or False
23+
print(result.variant) # 'the-variant-value' or None
24+
print(result.payload) # {'foo': 'bar'}
25+
print(result.get_value()) # 'the-variant-value' or True or False
26+
print(result.reason) # 'matched condition set 2' (Not available for local evaluation)
27+
```
28+
29+
Breaking change:
30+
31+
1. `get_feature_flag_payload` now deserializes payloads from JSON strings to `Any`. Previously, it returned the payload as a JSON encoded string.
32+
33+
Before:
34+
35+
```python
36+
payload = get_feature_flag_payload('key', 'distinct_id') # "{\"some\": \"payload\"}"
37+
```
38+
39+
After:
40+
41+
```python
42+
payload = get_feature_flag_payload('key', 'distinct_id') # {"some": "payload"}
43+
```
44+
45+
## 3.25.0 – 2025-04-15
46+
47+
1. Roll out new `/flags` endpoint to 100% of `/decide` traffic, excluding the top 10 customers.
48+
49+
## 3.24.3 – 2025-04-15
50+
51+
1. Fix hash inclusion/exclusion for flag rollout
52+
53+
## 3.24.2 – 2025-04-15
54+
55+
1. Roll out new /flags endpoint to 10% of /decide traffic
56+
57+
## 3.24.1 – 2025-04-11
58+
59+
1. Add `log_captured_exceptions` option to proxy setup
60+
61+
## 3.24.0 – 2025-04-10
62+
63+
1. Add config option to `log_captured_exceptions`
64+
165
## 3.23.0 – 2025-03-26
266

367
1. Expand automatic retries to include read errors (e.g. RemoteDisconnected)
468

569
## 3.22.0 – 2025-03-26
670

771
1. Add more information to `$feature_flag_called` events.
8-
2. Support for the `/decide?v=3` endpoint which contains more information about feature flags.
72+
2. Support for the `/decide?v=4` endpoint which contains more information about feature flags.
973

1074
## 3.21.0 – 2025-03-17
1175

@@ -203,7 +267,6 @@
203267

204268
1. Update type hints for module variables to work with newer versions of mypy
205269

206-
207270
## 3.3.3 - 2024-01-26
208271

209272
1. Remove new relative date operators, combine into regular date operators

LICENSE

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
SOFTWARE.
2222

23+
---
24+
25+
Some files in this codebase contain code from getsentry/sentry-javascript by Software, Inc. dba Sentry.
26+
In such cases it is explicitly stated in the file header. This license only applies to the relevant code in such cases.
27+
28+
MIT License
29+
30+
Copyright (c) 2012 Functional Software, Inc. dba Sentry
31+
32+
Permission is hereby granted, free of charge, to any person obtaining a copy of
33+
this software and associated documentation files (the "Software"), to deal in
34+
the Software without restriction, including without limitation the rights to
35+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
36+
of the Software, and to permit persons to whom the Software is furnished to do
37+
so, subject to the following conditions:
38+
39+
The above copyright notice and this permission notice shall be included in all
40+
copies or substantial portions of the Software.
41+
42+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48+
SOFTWARE.

bin/build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
#/ Usage: bin/build
3+
#/ Description: Runs linter and mypy
4+
source bin/helpers/_utils.sh
5+
set_source_and_root_dir
6+
7+
flake8 posthog --ignore E501,W503
8+
mypy --no-site-packages --config-file mypy.ini . | mypy-baseline filter

bin/fmt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
#/ Usage: bin/fmt
3+
#/ Description: Formats and lints the code
4+
source bin/helpers/_utils.sh
5+
set_source_and_root_dir
6+
ensure_virtual_env
7+
8+
if [[ "$1" == "--check" ]]; then
9+
black --check .
10+
isort --check-only .
11+
else
12+
black .
13+
isort .
14+
fi

bin/helpers/_utils.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error() {
2+
echo "$@" >&2
3+
}
4+
5+
fatal() {
6+
error "$@"
7+
exit 1
8+
}
9+
10+
set_source_and_root_dir() {
11+
{ set +x; } 2>/dev/null
12+
source_dir="$( cd -P "$( dirname "$0" )" >/dev/null 2>&1 && pwd )"
13+
root_dir=$(cd "$source_dir" && cd ../ && pwd)
14+
cd "$root_dir"
15+
}
16+
17+
ensure_virtual_env() {
18+
if [ -z "$VIRTUAL_ENV" ]; then
19+
echo "Virtual environment not activated. Activating now..."
20+
if [ ! -f env/bin/activate ]; then
21+
echo "Virtual environment not found. Please run 'python -m venv env' first."
22+
exit 1
23+
fi
24+
source env/bin/activate
25+
fi
26+
}

bin/setup

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
#/ Usage: bin/setup
3+
#/ Description: Sets up the dependencies needed to develop this project
4+
source bin/helpers/_utils.sh
5+
set_source_and_root_dir
6+
7+
if [ ! -d "env" ]; then
8+
python3 -m venv env
9+
fi
10+
11+
source env/bin/activate
12+
pip install -e ".[dev,test]"

bin/test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
#/ Usage: bin/test
3+
#/ Description: Runs all the unit tests for this project
4+
source bin/helpers/_utils.sh
5+
set_source_and_root_dir
6+
7+
ensure_virtual_env
8+
9+
# Pass through all arguments to pytest
10+
pytest "$@"

mypy.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ check_untyped_defs = True
99
warn_unreachable = True
1010
strict_equality = True
1111
ignore_missing_imports = True
12+
exclude = env/.*|venv/.*
1213

1314
[mypy-django.*]
1415
ignore_missing_imports = True

posthog/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
# Currently alpha, use at your own risk
2727
enable_exception_autocapture = False # type: bool
2828
exception_autocapture_integrations = [] # type: List[Integrations]
29+
log_captured_exceptions = False # type: bool
2930
# Used to determine in app paths for exception autocapture. Defaults to the current working directory
3031
project_root = None # type: Optional[str]
3132
# Used for our AI observability feature to not capture any prompt or output just usage + metadata
@@ -314,6 +315,7 @@ def capture_exception(
314315
timestamp=None, # type: Optional[datetime.datetime]
315316
uuid=None, # type: Optional[str]
316317
groups=None, # type: Optional[Dict]
318+
**kwargs
317319
):
318320
# type: (...) -> Tuple[bool, dict]
319321
"""
@@ -327,6 +329,7 @@ def capture_exception(
327329
Optionally you can submit
328330
- `properties`, which can be a dict with any information you'd like to add
329331
- `groups`, which is a dict of group type -> group key mappings
332+
- remaining `kwargs` will be logged if `log_captured_exceptions` is enabled
330333
331334
For example:
332335
```python
@@ -355,6 +358,7 @@ def capture_exception(
355358
timestamp=timestamp,
356359
uuid=uuid,
357360
groups=groups,
361+
**kwargs
358362
)
359363

360364

@@ -590,6 +594,7 @@ def _proxy(method, *args, **kwargs):
590594
# This kind of initialisation is very annoying for exception capture. We need to figure out a way around this,
591595
# or deprecate this proxy option fully (it's already in the process of deprecation, no new clients should be using this method since like 5-6 months)
592596
enable_exception_autocapture=enable_exception_autocapture,
597+
log_captured_exceptions=log_captured_exceptions,
593598
exception_autocapture_integrations=exception_autocapture_integrations,
594599
)
595600

0 commit comments

Comments
 (0)