Repository navigation
Next Python SDK major - #5005
sentrivana wants to merge 468 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #5005 +/- ##
===========================================
+ Coverage 70.55% 83.76% +13.21%
===========================================
Files 180 180
Lines 18077 18080 +3
Branches 3008 3009 +1
===========================================
+ Hits 12754 15145 +2391
+ Misses 4432 1943 -2489
- Partials 891 992 +101
|
Coverage Results 📊✅ 57871 passed | ⏭️ 3012 skipped | Total: 60883 | Pass Rate: 95.05% | Execution Time: 154m 7s All tests are passing successfully. ✅ Patch coverage is 88.79% (2852 of 3212 changed executable lines covered; target 80%). Changed files with executable lines (143)
Coverage diff@@ Coverage Diff @@
## master #5005 +/-##
==========================================
+ Coverage 90.35% 90.40% +0.05%
==========================================
Files 203 199 -4
Tracked lines 26931 21337 -5594
Branches 10058 7378 -2680
==========================================
- Hits 24331 19288 -5043
+ Misses 2600 2049 -551
+ Partials 1517 1234 -283Generated by Coverage Action |
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛Anthropic
Documentation 📚
Internal Changes 🔧
Other
🤖 This preview updates automatically when you update the PR. |
Fixes for things that the bots [surfaced](#5005) on the major branch: - some version checks were too late (after patching) - fix TrytondWSGI integration name/`_MIN_VERSIONS` entry mismatch Also, changed the warning of the `DidNotEnable` message from "X not installed" to "X not installed or incompatible".
Originally raised by a bot [here](#5005 (comment)): the `parse_version` function parses version strings as is (e.g. 3.1 becomes `(3, 1)`). We use these parsed version tuples in integrations to compare the installed version against the minimum (defined in `integrations/__init__.py`). The minimum versions are often three-part, e.g. `(3, 1, 0)`. This means that we can mistakenly consider a valid version to be below the minimum, because in pure tuple terms, `(3, 1) < (3, 1, 0)` is true. This can also happen in reverse (package version has three parts, while our min version boundary has two). In this PR, we make the internal version comparison work as expected regardless of mismatches in the length of the version strings/tuples.
…8154) ### Description Removes the `PY37` flag from `sentry_sdk/_compat.py`, along with the code paths that only ran when it was `False`. It also removes the `nanosecond_time()` wrapper, which existed only to choose between those paths. `setup.py` sets `python_requires=">=3.7"`, so `PY37` is always `True` on every supported interpreter, and the `tox.ini` matrix starts at py3.7. That makes these branches unreachable: - `nanosecond_time()` in `sentry_sdk/utils.py`: the `int(time.perf_counter() * 1e9)` fallback is gone. Once only `time.perf_counter_ns()` was left, the wrapper added nothing, so it's removed as well. Its two call sites in `sentry_sdk/traces.py` (`Span` start and end) now call `time.perf_counter_ns()` directly. - `tests/test_gevent.py`: `compression_algo` always includes `"br"` now, as it already did in practice. - `tests/test_transport.py`: `elif PY37:` becomes `else:`, and the pre-3.7 case list after it is removed. The cases that run on 3.7 are unchanged. `PY38`, `PY310` and `PY311` are still used, so they stay. This doesn't depend on #8153; the two only touch different lines of `_compat.py` and merge cleanly together. `_compat` and `utils` are private modules, and nothing else in the repo (including tests) references `nanosecond_time`. Runtime behavior doesn't change on any supported Python version. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description Removes the private `_get_usage_attributes()` helper from `sentry_sdk/tracing_utils.py`. Nothing on `major/3.0` calls it anymore. It pulled `gen_ai.usage.*` token counts out of return values for the AI Agents `@trace` templates added in #4676. #7457 ("Remove trace template, trace_ignore_status_codes") deleted the template code that called it, but left the helper behind. **Evidence** - On `major/3.0`, `git grep -w _get_usage_attributes` matches only the definition. There are no callers in `sentry_sdk` or `tests`. - No open PR touches it. `_get_value()` is still imported by the LangChain integration, so it stays. On `master` the helper is still used, because the trace templates still exist there. This change only applies to `major/3.0`. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description Removes the private `_ScopeManager` class from `sentry_sdk/scope.py`. Nothing on `major/3.0` uses it anymore. It was the context manager behind `push_scope()` and the `Hub` scope helpers. #6919 ("Drop hub related code in new major") and #6944 ("Remove `push_scope`, `configure_scope` in new major") removed those callers and their imports, but left the class behind. **Evidence** - On `major/3.0`, `git grep -w _ScopeManager` matches only the class definition in `sentry_sdk/` and `tests/`. The only other hits are historical `CHANGELOG.md` and `MIGRATION_GUIDE.md` entries from 2.0 about it moving out of `sentry_sdk.hub`. - No open PR touches it. It's underscore-private and isn't exported, so this doesn't touch the public API. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description Removes two helpers that only `EventScrubber` used: - `iter_event_frames()` in `sentry_sdk/utils.py` - `AnnotatedValue.substituted_because_contains_sensitive_data()` in `sentry_sdk/_types.py` #7772 ("Remove `EventScrubber` and the `event_scrubber` option") deleted `sentry_sdk/scrubber.py`, which held the only call to each of them: frame-vars scrubbing called `iter_event_frames(event)`, and denylisted keys were replaced with `AnnotatedValue.substituted_because_contains_sensitive_data()`. Both helpers were left behind. **Evidence** - On `major/3.0`, `git grep -w` for each name matches only its definition. There are no callers in `sentry_sdk`, `tests`, `scripts` or `docs`. - No open PR touches either one. `iter_event_stacktraces()` (used by `handle_in_app`) and `SENSITIVE_DATA_SUBSTITUTE` (used by the data-collection filtering and several integrations) are still used, so they stay. On `master`, `EventScrubber` still uses both helpers, so this only applies to `major/3.0`. `iter_event_frames` could be imported from `sentry_sdk.utils`, but it isn't documented anywhere, and `major/3.0` is already a breaking release. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
### Description Removes `AwsCallContext.service_id_hyphenized` from `sentry_sdk/integrations/boto3/_context.py`. It's still computed on every call (`service_id.hyphenize()`), but on `major/3.0` nothing reads it. It had two readers. One was the `aws.service_id` span tag, which #7261 ("Drop tags auto-set by the SDK") removed. The other was the span name: #7800 ("align span names with OTel conventions") switched that to `ctx.service_id`, so the hyphenized value lost its last reader. This removes the slot, the attribute and the `hyphenize()` call. **Evidence** - On `major/3.0`, `git grep -w service_id_hyphenized` matches only the three lines in `_context.py` that set it up. - The open boto3 extension PRs against `major/3.0` (#8117 SQS, #8137 Lambda) don't reference it. On `master`, `service_id_hyphenized` is still used for the span name and the tag, so this only applies to `major/3.0`. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description Removes `get_url_attributes_legacy()` from `sentry_sdk/tracing_utils.py`. Nothing on `major/3.0` calls it anymore. Its callers were the outgoing HTTP client integrations (pyreqwest, httpx, httpx2). It handled their old `send_default_pii` behavior. When #7698, #7819 and #7830 dropped `send_default_pii` support from those integrations, each one removed its calls and switched to `get_url_attributes()`. The legacy helper was left behind. **Evidence** - On `major/3.0`, `git grep -w get_url_attributes_legacy` matches only the definition. There are no callers in `sentry_sdk`, `tests`, `scripts` or `docs`. - No open PR mentions it. The function doesn't exist on `master`, so a future `master` → `major/3.0` merge can't bring it back. `get_url_attributes()` and `_apply_data_collection_filtering_to_query_string` are still used, so they stay. #### Issues n/a <!-- junior-request-attribution:start --> via **Ivana Kellyer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
….1 (#8168) ### Description Partially reverts #7058 so projects pinned to redis-py 3.x and redis-py-cluster 2.x keep their Redis instrumentation in 3.0. With the 4.2 minimum, an explicitly configured `RedisIntegration()` raises `DidNotEnable` and `sentry_sdk.init()` fails. This came up while dogfooding 3.0 in getsentry/sentry, which is pinned to redis-py 3.4.1 because it still uses redis-py-cluster (which requires `redis<4`). It also can't move past redis-py 4.x yet because `rb` breaks on redis-py 5+. Only what's needed for those versions is restored: - Lower the redis-py minimum from 4.2 to 3.4.1. - Patch the `redis.asyncio` client and pipeline only if `redis.asyncio` exists (added in redis-py 4.2). This import was guarded in 2.x and #7058 made it unconditional, which is the actual reason 3.x stopped working. - Restore the redis-py-cluster instrumentation, limited to 2.x. 1.x requires redis-py 2.x, which is below the new minimum, so the `StrictRedisCluster`/`StrictClusterPipeline` branches aren't brought back. - Re-add the `redis_py_cluster_legacy` test suite (rewritten for span streaming and the 3.0 attribute names) and its CI entry. Kept from #7058: the `max_data_size` removal and the `StrictRedis` -> `Redis` switch. `tox.ini` was regenerated with `populate_tox.py --only redis redis_py_cluster_legacy` to avoid unrelated matrix churn. This adds redis 3.4.1/3.5.3 and drops 4.2.2 as the lowest 4.x env. CI only runs redis 3.x on py3.7/3.8 because of its classifiers. I also checked 3.4.1 + rb + redis-py-cluster 2.1.0 on Python 3.13 manually against getsentry/sentry.
…heck-ins (#8184) ### Description According to the [check-in spec](https://develop.sentry.dev/sdk/telemetry/check-ins/), check-ins MUST NOT go through `before_send`. SDKs may offer a separate `beforeSendCheckIn` hook instead. - Check-ins no longer go through `before_send`. - New `before_send_check_in` option to modify or drop check-ins. - Check-ins dropped by `before_send_check_in` are recorded under the `monitor` data category in client reports (previously `error`). - Added a test making sure event processors are not applied to check-ins (existing behavior, previously untested). - Added a note to the migration guide. This is technically a bugfix, but the incorrect behavior has been out there for so long that it may now be expected behavior, so considering this breaking. #### Issues Closes #4814 #### Reminders - Please add tests to validate your changes, and lint your code using `uv run ruff`. - Add GH Issue ID _&_ Linear ID (if applicable) - PR title should use [conventional commit](https://develop.sentry.dev/engineering-practices/commit-messages/#type) style (`feat:`, `fix:`, `ref:`, `meta:`) - For external contributors: [CONTRIBUTING.md](https://github.com/getsentry/sentry-python/blob/master/CONTRIBUTING.md), [Sentry SDK development docs](https://develop.sentry.dev/sdk/), [Discord community](https://discord.gg/Ww9hbqr)
| gevent_version = tuple( | ||
| int(part) for part in re.split(r"a|b|rc|\.", gevent.__version__)[:2] | ||
| ) |
There was a problem hiding this comment.
Gevent version check uses fragile custom parsing instead of parse_version
Please parse gevent with parse_version (as greenlet does below) instead of re.split(r"a|b|rc|\."); the ad-hoc splitter can raise on prefixes/suffixes like v or dev, hit the bare except Exception, and silently skip the unsupported-version warning.
Evidence
_check_version_deprecations()buildsgevent_versionviare.split(r"a|b|rc|\.", gevent.__version__)[:2]thenint(part).- The greenlet branch in the same function already uses
parse_version(greenlet.__version__). - Any
ValueError/TypeErrorfrom parsing is swallowed byexcept Exception: pass, so thelogger.warning(...)never runs. parse_versioninsentry_sdk/utils.pyalready handles PEP 440 forms (optionalv, pre/dev/post) used elsewhere in the SDK.
Identified by Warden · code-review · 27V-U35
We're preparing our next major on this branch.
The project is tracked in Linear. If you don't have access, we'll try to tag issues belonging to the project with the
SDK3.0 label on GitHub so that you can follow along.Notable changes
Context
You might have read this announcement about us discontinuing work on a 3.0. This is referring to the work done on the
potel-basebranch, which included two types of changes: a huge refactor of our tracing code on the one hand, and various unrelated changes, improvements and fixes on the other. We're dropping the huge refactor part, and only porting the rest, to a new branch and eventually a new 3.0 release.