fastapi-observer 0.3.0__tar.gz → 0.3.1__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.
Files changed (66) hide show
  1. {fastapi_observer-0.3.0/src/fastapi_observer.egg-info → fastapi_observer-0.3.1}/PKG-INFO +2 -2
  2. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/README.md +1 -1
  3. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/pyproject.toml +0 -1
  4. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1/src/fastapi_observer.egg-info}/PKG-INFO +2 -2
  5. fastapi_observer-0.3.1/src/fastapiobserver/_version.py +1 -0
  6. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_fastapi_install.py +9 -5
  7. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_graphql_integrations.py +23 -17
  8. fastapi_observer-0.3.0/src/fastapiobserver/_version.py +0 -1
  9. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/LICENSE +0 -0
  10. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/setup.cfg +0 -0
  11. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapi_observer.egg-info/SOURCES.txt +0 -0
  12. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapi_observer.egg-info/dependency_links.txt +0 -0
  13. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapi_observer.egg-info/requires.txt +0 -0
  14. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapi_observer.egg-info/top_level.txt +0 -0
  15. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/__init__.py +0 -0
  16. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/config.py +0 -0
  17. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/control_plane.py +0 -0
  18. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/fastapi.py +0 -0
  19. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/integrations/__init__.py +0 -0
  20. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/integrations/strawberry.py +0 -0
  21. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/logging.py +0 -0
  22. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/loguru.py +0 -0
  23. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/metrics.py +0 -0
  24. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/middleware.py +0 -0
  25. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/__init__.py +0 -0
  26. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/lifecycle.py +0 -0
  27. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/logs.py +0 -0
  28. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/metrics.py +0 -0
  29. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/resource.py +0 -0
  30. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/settings.py +0 -0
  31. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/tracing.py +0 -0
  32. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/otel/types.py +0 -0
  33. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/plugins.py +0 -0
  34. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/propagation.py +0 -0
  35. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/py.typed +0 -0
  36. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/request_context.py +0 -0
  37. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/security.py +0 -0
  38. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/sinks.py +0 -0
  39. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/src/fastapiobserver/utils.py +0 -0
  40. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_body_media_allowlist.py +0 -0
  41. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_config_settings.py +0 -0
  42. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_excluded_url_precedence.py +0 -0
  43. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_log_queue_controls.py +0 -0
  44. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_logging_schema_contract.py +0 -0
  45. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_logtail_dlq.py +0 -0
  46. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_loguru_bridge.py +0 -0
  47. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_metrics_optional_dependency.py +0 -0
  48. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_middleware.py +0 -0
  49. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_negotiate_content_type.py +0 -0
  50. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_integration.py +0 -0
  51. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_lifecycle.py +0 -0
  52. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_log_correlation.py +0 -0
  53. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_logs_from_env.py +0 -0
  54. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_logs_pipeline.py +0 -0
  55. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otel_metrics_from_env.py +0 -0
  56. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_otlp_export_integration.py +0 -0
  57. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_plugin_isolation.py +0 -0
  58. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_propagation.py +0 -0
  59. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_redaction_presets.py +0 -0
  60. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_route_template_cardinality.py +0 -0
  61. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_runtime_control_auth.py +0 -0
  62. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_security_redaction.py +0 -0
  63. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_sink_circuit_breaker.py +0 -0
  64. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_sinks.py +0 -0
  65. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_trust_boundary.py +0 -0
  66. {fastapi_observer-0.3.0 → fastapi_observer-0.3.1}/tests/test_utils_refactors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-observer
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Zero-glue FastAPI observability with security presets and runtime controls
5
5
  Author-email: Vitaee <opensource@vitaee.dev>
6
6
  License-Expression: MIT
@@ -963,7 +963,7 @@ Reproducible benchmark harness and methodology:
963
963
  - `0.2.x`: OTel interoperability, security presets, allowlists
964
964
  - `1.0.0`: dynamic runtime controls and plugin stability
965
965
 
966
- Current release version: `0.3.0`
966
+ Current release version: `0.3.1`
967
967
 
968
968
  ## Changelog Policy
969
969
 
@@ -894,7 +894,7 @@ Reproducible benchmark harness and methodology:
894
894
  - `0.2.x`: OTel interoperability, security presets, allowlists
895
895
  - `1.0.0`: dynamic runtime controls and plugin stability
896
896
 
897
- Current release version: `0.3.0`
897
+ Current release version: `0.3.1`
898
898
 
899
899
  ## Changelog Policy
900
900
 
@@ -115,4 +115,3 @@ ignore_missing_imports = true
115
115
  [tool.pytest.ini_options]
116
116
  pythonpath = ["src"]
117
117
  testpaths = ["tests"]
118
- asyncio_mode = "auto"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-observer
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Zero-glue FastAPI observability with security presets and runtime controls
5
5
  Author-email: Vitaee <opensource@vitaee.dev>
6
6
  License-Expression: MIT
@@ -963,7 +963,7 @@ Reproducible benchmark harness and methodology:
963
963
  - `0.2.x`: OTel interoperability, security presets, allowlists
964
964
  - `1.0.0`: dynamic runtime controls and plugin stability
965
965
 
966
- Current release version: `0.3.0`
966
+ Current release version: `0.3.1`
967
967
 
968
968
  ## Changelog Policy
969
969
 
@@ -0,0 +1 @@
1
+ __version__ = "0.3.1"
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from fastapi import FastAPI
3
+ import asyncio
4
+
4
5
  import pytest
6
+ from fastapi import FastAPI
5
7
 
6
8
  import fastapiobserver.fastapi as fastapi_module
7
9
  from fastapiobserver import (
@@ -135,8 +137,7 @@ def test_install_observability_installs_otel_metrics_when_enabled(
135
137
  assert calls["otel_settings"] is None
136
138
 
137
139
 
138
- @pytest.mark.asyncio
139
- async def test_install_observability_registers_logging_shutdown_hook_once(
140
+ def test_install_observability_registers_logging_shutdown_hook_once(
140
141
  monkeypatch: pytest.MonkeyPatch,
141
142
  ) -> None:
142
143
  app = FastAPI()
@@ -155,7 +156,10 @@ async def test_install_observability_registers_logging_shutdown_hook_once(
155
156
  assert app in fastapi_module._REGISTERED_APPS
156
157
 
157
158
  # Verify the shutdown hook actively works when application teardown runs
158
- async with app.router.lifespan_context(app):
159
- pass
159
+ async def _run_lifespan() -> None:
160
+ async with app.router.lifespan_context(app):
161
+ pass
162
+
163
+ asyncio.run(_run_lifespan())
160
164
 
161
165
  assert len(mock_calls) == 1
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import pytest
4
5
  from unittest.mock import MagicMock, patch
5
6
 
@@ -12,8 +13,20 @@ def clean_context() -> None:
12
13
  clear_user_context()
13
14
 
14
15
 
15
- @pytest.mark.asyncio
16
- async def test_strawberry_extension_injects_operation_name_into_log_context() -> None:
16
+ def _drive_on_operation(
17
+ extension: StrawberryObservabilityExtension,
18
+ ) -> dict[str, object] | None:
19
+ async def _run() -> dict[str, object] | None:
20
+ generator = extension.on_operation()
21
+ await generator.__anext__()
22
+ context = get_user_context()
23
+ await generator.aclose()
24
+ return context
25
+
26
+ return asyncio.run(_run())
27
+
28
+
29
+ def test_strawberry_extension_injects_operation_name_into_log_context() -> None:
17
30
  # 1. Setup simulated execution context (Duck Typing Strawberry)
18
31
  mock_context = MagicMock()
19
32
  mock_context.operation_name = "GetUsersQuery"
@@ -26,44 +39,37 @@ async def test_strawberry_extension_injects_operation_name_into_log_context() ->
26
39
  extension = StrawberryObservabilityExtension(execution_context=mock_context)
27
40
 
28
41
  # 4. Run the async generator hook
29
- generator = extension.on_operation()
30
- await generator.__anext__()
42
+ final_context = _drive_on_operation(extension)
31
43
 
32
44
  # 5. Assert the observability context updated correctly
33
- final_context = get_user_context()
34
45
  assert final_context is not None
35
46
  assert final_context["tenant"] == "acme"
36
47
  assert "graphql" in final_context
37
48
  assert final_context["graphql"]["operation_name"] == "GetUsersQuery"
38
49
 
39
50
 
40
- @pytest.mark.asyncio
41
- async def test_strawberry_extension_handles_missing_operation_name() -> None:
51
+ def test_strawberry_extension_handles_missing_operation_name() -> None:
42
52
  mock_context = MagicMock()
43
53
  # E.g. a malformed query where Strawberry couldn't parse the operation
44
- mock_context.operation_name = None
54
+ mock_context.operation_name = None
45
55
 
46
56
  extension = StrawberryObservabilityExtension(execution_context=mock_context)
47
- generator = extension.on_operation()
48
- await generator.__anext__()
57
+ final_context = _drive_on_operation(extension)
49
58
 
50
- final_context = get_user_context()
51
59
  assert final_context is not None
52
60
  assert final_context["graphql"]["operation_name"] == "AnonymousOperation"
53
61
 
54
62
 
55
- @pytest.mark.asyncio
56
63
  @patch("fastapiobserver.integrations.strawberry.get_user_context")
57
- async def test_strawberry_extension_swallows_parsing_exceptions(mock_get: MagicMock) -> None:
64
+ def test_strawberry_extension_swallows_parsing_exceptions(mock_get: MagicMock) -> None:
58
65
  mock_context = MagicMock()
59
66
  # Force an exception on property access
60
67
  type(mock_context).operation_name = property(
61
68
  lambda self: (_ for _ in ()).throw(RuntimeError("boom"))
62
69
  )
63
-
70
+
64
71
  extension = StrawberryObservabilityExtension(execution_context=mock_context)
65
- generator = extension.on_operation()
66
- await generator.__anext__()
67
-
72
+ _drive_on_operation(extension)
73
+
68
74
  # It shouldn't crash. It should just gracefully yield and mark it anonymous.
69
75
  mock_get.assert_called_once()
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"