debugbundle-python 1.1.0__tar.gz → 1.1.3__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.
- {debugbundle_python-1.1.0/src/debugbundle_python.egg-info → debugbundle_python-1.1.3}/PKG-INFO +1 -1
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/pyproject.toml +1 -1
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/core.py +16 -4
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/relay.py +10 -2
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3/src/debugbundle_python.egg-info}/PKG-INFO +1 -1
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_relay.py +24 -1
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_repository_metadata.py +17 -1
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_smoke_script.py +2 -2
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/LICENSE +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/README.md +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/setup.cfg +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/__init__.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/config.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/__init__.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/common.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/django.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/fastapi.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/flask.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_django.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_fastapi.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_flask.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/logger_integrations.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/py.typed +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/redaction.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/relay_delivery.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/suppression.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/transport.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/trigger_token.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/SOURCES.txt +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/dependency_links.txt +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/requires.txt +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/top_level.txt +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_contracts.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_framework_integrations.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_hooks.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_http_integration.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_optional_imports.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_relay_delivery.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_remote_config.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_schema_validation.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_sdk.py +0 -0
- {debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/tests/test_trigger_token.py +0 -0
|
@@ -528,23 +528,27 @@ class DebugBundleSdk:
|
|
|
528
528
|
payload: dict[str, object],
|
|
529
529
|
context: Mapping[str, object] | None = None,
|
|
530
530
|
) -> dict[str, object]:
|
|
531
|
-
|
|
531
|
+
merged_context = self._merged_context(context)
|
|
532
|
+
event: dict[str, object] = {
|
|
532
533
|
"schema_version": SCHEMA_VERSION,
|
|
533
534
|
"event_id": str(uuid.uuid4()),
|
|
534
535
|
"event_type": event_type,
|
|
535
536
|
"occurred_at": _iso_now(self._time_provider),
|
|
536
537
|
"sdk_name": "debugbundle-python",
|
|
537
538
|
"sdk_version": _sdk_version(),
|
|
538
|
-
"sdk_language": "python",
|
|
539
539
|
"service": {
|
|
540
540
|
"name": self._service,
|
|
541
541
|
"runtime": "python",
|
|
542
542
|
"framework": None,
|
|
543
543
|
"environment": self._environment,
|
|
544
544
|
},
|
|
545
|
-
"correlation": _correlation_payload(
|
|
545
|
+
"correlation": _correlation_payload(merged_context),
|
|
546
546
|
"payload": payload,
|
|
547
547
|
}
|
|
548
|
+
envelope_context = _event_context(merged_context)
|
|
549
|
+
if envelope_context:
|
|
550
|
+
event["context"] = envelope_context
|
|
551
|
+
return event
|
|
548
552
|
|
|
549
553
|
def _merged_context(self, context: Mapping[str, object] | None = None) -> dict[str, object]:
|
|
550
554
|
merged = dict(self._context)
|
|
@@ -861,6 +865,14 @@ def _correlation_payload(context: Mapping[str, object]) -> dict[str, str | None]
|
|
|
861
865
|
}
|
|
862
866
|
|
|
863
867
|
|
|
868
|
+
def _event_context(context: Mapping[str, object]) -> dict[str, object]:
|
|
869
|
+
return {
|
|
870
|
+
str(key): value
|
|
871
|
+
for key, value in context.items()
|
|
872
|
+
if key not in {"request", "response", "correlation", "request_id", "trace_id", "session_id", "user_id_hash"}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
|
|
864
876
|
def _coerce_optional_string(value: object) -> str | None:
|
|
865
877
|
if value is None:
|
|
866
878
|
return None
|
|
@@ -942,7 +954,7 @@ def _sdk_version() -> str:
|
|
|
942
954
|
try:
|
|
943
955
|
return metadata.version("debugbundle-python")
|
|
944
956
|
except metadata.PackageNotFoundError:
|
|
945
|
-
return "1.1.
|
|
957
|
+
return "1.1.3"
|
|
946
958
|
|
|
947
959
|
|
|
948
960
|
def _sdk_config_endpoint(events_endpoint: str) -> str:
|
|
@@ -25,6 +25,7 @@ ACCEPTED_EVENT_TYPES = frozenset(
|
|
|
25
25
|
"frontend_breadcrumb",
|
|
26
26
|
"request_event",
|
|
27
27
|
"probe_event",
|
|
28
|
+
"analytics_event",
|
|
28
29
|
}
|
|
29
30
|
)
|
|
30
31
|
|
|
@@ -376,8 +377,15 @@ def _sanitize_event(
|
|
|
376
377
|
correlation = event.get("correlation")
|
|
377
378
|
if isinstance(correlation, dict):
|
|
378
379
|
normalized_correlation: dict[str, Any] = {}
|
|
379
|
-
|
|
380
|
-
|
|
380
|
+
correlation_keys = (
|
|
381
|
+
("session_id", "visitor_id_hash", "user_id_hash", "trace_id", "deploy_id")
|
|
382
|
+
if event_type == "analytics_event"
|
|
383
|
+
else ("request_id", "trace_id", "session_id", "user_id_hash")
|
|
384
|
+
)
|
|
385
|
+
for key in correlation_keys:
|
|
386
|
+
if key not in correlation:
|
|
387
|
+
continue
|
|
388
|
+
value = correlation[key]
|
|
381
389
|
if isinstance(value, str) or value is None:
|
|
382
390
|
normalized_correlation[key] = value
|
|
383
391
|
|
|
@@ -72,6 +72,21 @@ def test_accepts_valid_batch() -> None:
|
|
|
72
72
|
assert response.body["rejected"] == 0
|
|
73
73
|
|
|
74
74
|
|
|
75
|
+
def test_accepts_analytics_events_and_preserves_analytics_correlation() -> None:
|
|
76
|
+
fixture = _relay_compliance_fixture("valid-analytics-event")
|
|
77
|
+
accepted: list[BrowserRelayAcceptedBatch] = []
|
|
78
|
+
handler = BrowserRelayHandler(
|
|
79
|
+
allowed_origins=[fixture["request"]["headers"]["origin"]],
|
|
80
|
+
on_accept=lambda batch: accepted.append(batch),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
response = handler.handle(_make_request_from_fixture(fixture["request"]))
|
|
84
|
+
|
|
85
|
+
assert response.status == 202
|
|
86
|
+
assert accepted[0].events[0] == fixture["expectedEventFile"][0]
|
|
87
|
+
assert "project_token" not in accepted[0].events[0]
|
|
88
|
+
|
|
89
|
+
|
|
75
90
|
def test_rejects_non_post() -> None:
|
|
76
91
|
handler = BrowserRelayHandler(allowed_origins=["https://example.com"])
|
|
77
92
|
response = handler.handle(_make_request(method="GET"))
|
|
@@ -211,7 +226,15 @@ def test_preserves_correlation_trace_id() -> None:
|
|
|
211
226
|
|
|
212
227
|
def test_accepts_all_supported_event_types() -> None:
|
|
213
228
|
handler = BrowserRelayHandler(allowed_origins=["https://example.com"])
|
|
214
|
-
|
|
229
|
+
supported_event_types = (
|
|
230
|
+
"frontend_exception",
|
|
231
|
+
"error_suppressed",
|
|
232
|
+
"frontend_breadcrumb",
|
|
233
|
+
"request_event",
|
|
234
|
+
"probe_event",
|
|
235
|
+
"analytics_event",
|
|
236
|
+
)
|
|
237
|
+
for event_type in supported_event_types:
|
|
215
238
|
evt = _valid_event(event_type)
|
|
216
239
|
response = handler.handle(
|
|
217
240
|
_make_request(body={"batch": [evt]}, ip_address=f"10.0.0.{hash(event_type) % 254 + 1}")
|
|
@@ -30,7 +30,23 @@ def test_standalone_changelog_and_security_policy_are_launch_ready() -> None:
|
|
|
30
30
|
security = (REPO_ROOT / "SECURITY.md").read_text(encoding="utf-8")
|
|
31
31
|
|
|
32
32
|
assert "## [Unreleased]" in changelog
|
|
33
|
-
assert
|
|
33
|
+
assert (
|
|
34
|
+
"## [1.1.3] - 2026-07-17\n\n"
|
|
35
|
+
"### Added\n"
|
|
36
|
+
"- Added browser-relay support for `analytics_event` envelopes, preserving only the "
|
|
37
|
+
"analytics correlation fields needed for aggregation while continuing to strip "
|
|
38
|
+
"browser-supplied credentials.\n\n"
|
|
39
|
+
"## [1.1.2] - 2026-06-19\n\n"
|
|
40
|
+
"### Fixed\n"
|
|
41
|
+
"- Release packaging quality gates so the published Python SDK patch can ship cleanly "
|
|
42
|
+
"without changing runtime behavior.\n\n"
|
|
43
|
+
"## [1.1.1] - 2026-06-19\n\n"
|
|
44
|
+
"### Fixed\n"
|
|
45
|
+
"- Normalized canonical event-envelope emission so custom app context now stays in envelope `context`, "
|
|
46
|
+
"request events avoid legacy payload extras, and installed projects stop tripping malformed ingestion rejects "
|
|
47
|
+
"after upgrade.\n\n"
|
|
48
|
+
"## [1.1.0] - 2026-06-08" in changelog
|
|
49
|
+
)
|
|
34
50
|
assert "https://github.com/debugbundle/debugbundle-python/security/advisories/new" in security
|
|
35
51
|
|
|
36
52
|
|
|
@@ -32,7 +32,7 @@ def test_install_with_retry_retries_until_success(monkeypatch) -> None:
|
|
|
32
32
|
monkeypatch.setattr(SMOKE.time, "sleep", sleeps.append)
|
|
33
33
|
|
|
34
34
|
SMOKE._install_with_retry(
|
|
35
|
-
["python", "-m", "pip", "install", "debugbundle-python==1.1.
|
|
35
|
+
["python", "-m", "pip", "install", "debugbundle-python==1.1.3"],
|
|
36
36
|
retries=3,
|
|
37
37
|
retry_delay_seconds=7,
|
|
38
38
|
)
|
|
@@ -50,7 +50,7 @@ def test_install_with_retry_raises_after_final_attempt(monkeypatch) -> None:
|
|
|
50
50
|
|
|
51
51
|
try:
|
|
52
52
|
SMOKE._install_with_retry(
|
|
53
|
-
["python", "-m", "pip", "install", "debugbundle-python==1.1.
|
|
53
|
+
["python", "-m", "pip", "install", "debugbundle-python==1.1.3"],
|
|
54
54
|
retries=2,
|
|
55
55
|
retry_delay_seconds=1,
|
|
56
56
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/__init__.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/common.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/django.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/fastapi.py
RENAMED
|
File without changes
|
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_django.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_fastapi.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/integrations/relay_flask.py
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle/logger_integrations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{debugbundle_python-1.1.0 → debugbundle_python-1.1.3}/src/debugbundle_python.egg-info/top_level.txt
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
|
|
File without changes
|