grpc-server-kit 0.1.0__tar.gz → 0.2.0__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 (60) hide show
  1. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/CHANGELOG.md +18 -0
  2. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/PKG-INFO +15 -1
  3. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/README.md +14 -0
  4. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/__init__.py +2 -0
  5. grpc_server_kit-0.2.0/grpc_server_kit/__version__.py +1 -0
  6. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/__init__.py +10 -1
  7. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/context.py +9 -2
  8. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/settings.py +18 -2
  9. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/pyproject.toml +4 -0
  10. grpc_server_kit-0.1.0/grpc_server_kit/__version__.py +0 -1
  11. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/.gitignore +0 -0
  12. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/LICENSE +0 -0
  13. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/app.py +0 -0
  14. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/builder.py +0 -0
  15. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/__init__.py +0 -0
  16. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/bundle.py +0 -0
  17. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/interceptors.py +0 -0
  18. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/metrics.py +0 -0
  19. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/observability.py +0 -0
  20. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/dishka/server.py +0 -0
  21. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/__init__.py +0 -0
  22. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/cache.py +0 -0
  23. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/checkers/__init__.py +0 -0
  24. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/checkers/postgres.py +0 -0
  25. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/checkers/redis.py +0 -0
  26. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/checkers/utils.py +0 -0
  27. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/orchestrator.py +0 -0
  28. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/protocols.py +0 -0
  29. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/health/servicer.py +0 -0
  30. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/__init__.py +0 -0
  31. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/base.py +0 -0
  32. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/exception_handler.py +0 -0
  33. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/metadata.py +0 -0
  34. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/metrics.py +0 -0
  35. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/protocols.py +0 -0
  36. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/request_logger.py +0 -0
  37. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/sentry.py +0 -0
  38. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/interceptors/tracing.py +0 -0
  39. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/observability/__init__.py +0 -0
  40. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/observability/tracing.py +0 -0
  41. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/runtime.py +0 -0
  42. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/aio/server.py +0 -0
  43. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/config.py +0 -0
  44. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/constants.py +0 -0
  45. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/credentials.py +0 -0
  46. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/dishka/__init__.py +0 -0
  47. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/dishka/settings.py +0 -0
  48. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/interceptors/__init__.py +0 -0
  49. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/interceptors/constants.py +0 -0
  50. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/interceptors/utils.py +0 -0
  51. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/observability/__init__.py +0 -0
  52. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/observability/metrics.py +0 -0
  53. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/observability/naming.py +0 -0
  54. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/observability/protocols.py +0 -0
  55. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/observability/sentry.py +0 -0
  56. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/options.py +0 -0
  57. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/protocols.py +0 -0
  58. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/py.typed +0 -0
  59. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/server.py +0 -0
  60. {grpc_server_kit-0.1.0 → grpc_server_kit-0.2.0}/grpc_server_kit/signals.py +0 -0
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0](https://github.com/bedrock-python/grpc-server-kit/compare/grpc-server-kit-v0.1.1...grpc-server-kit-v0.2.0) (2026-09-14)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * `BaseGrpcServerSettings(port=0)` now raises `ValidationError`; pass `allow_ephemeral_port=True` (or `GRPC__ALLOW_EPHEMERAL_PORT=true`) to bind an ephemeral port on purpose.
9
+
10
+ ### Features
11
+
12
+ * BaseGrpcServerSettings rejects port=0 unless allow_ephemeral_port=True ([4a450e4](https://github.com/bedrock-python/grpc-server-kit/commit/4a450e4dbc7ffe0a7d5fd107e9b2d0e7e2c2d279)), closes [#24](https://github.com/bedrock-python/grpc-server-kit/issues/24)
13
+
14
+ ## [0.1.1](https://github.com/bedrock-python/grpc-server-kit/compare/grpc-server-kit-v0.1.0...grpc-server-kit-v0.1.1) (2026-09-06)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * missing exports, context skip_methods, and compression "none" ([#17](https://github.com/bedrock-python/grpc-server-kit/issues/17)) ([9c70e9d](https://github.com/bedrock-python/grpc-server-kit/commit/9c70e9db467f8fc3c25c2426c98869b22a3ce0aa))
20
+
3
21
  ## 0.1.0 (2026-08-11)
4
22
 
5
23
  Initial release of grpc-server-kit.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: grpc-server-kit
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Batteries-optional async gRPC server toolkit (app facade, builder, TLS, lifecycle, health, streaming-aware interceptors, observability)
5
5
  Project-URL: Repository, https://github.com/bedrock-python/grpc-server-kit
6
6
  Project-URL: Documentation, https://bedrock-python.github.io/grpc-server-kit/
@@ -277,6 +277,16 @@ Dishka DI, and typed pydantic settings.
277
277
  The core depends only on `grpcio`. Every integration is an opt-in extra, so you
278
278
  install exactly what you use.
279
279
 
280
+ > [!TIP]
281
+ > **Building this with an AI assistant?** Hand it
282
+ > **[one page](https://bedrock-python.github.io/grpc-server-kit/agents/)** instead of
283
+ > the whole site: the complete API surface, the ordering rules that break a server when
284
+ > they are broken (build-then-configure, outermost-first interceptors, Sentry inside the
285
+ > exception handler), the mistakes models actually make with `grpc.aio`, and a map of
286
+ > which page to fetch for the rest. Every docs page is also served as raw Markdown at its
287
+ > own URL, and a **Copy page** button at the top of each one hands it straight to a chat
288
+ > window.
289
+
280
290
  ## Installation
281
291
 
282
292
  ```bash
@@ -479,6 +489,10 @@ Runnable, self-contained scripts in [`examples/`](examples/) — each prints wha
479
489
 
480
490
  Full documentation at [bedrock-python.github.io/grpc-server-kit](https://bedrock-python.github.io/grpc-server-kit/).
481
491
 
492
+ - [For AI agents](https://bedrock-python.github.io/grpc-server-kit/agents/) — the whole
493
+ API surface, the rules that break a server when broken and a map of the rest, on one
494
+ page to hand to a coding assistant
495
+
482
496
  ## License
483
497
 
484
498
  Apache 2.0 — see [LICENSE](LICENSE).
@@ -19,6 +19,16 @@ Dishka DI, and typed pydantic settings.
19
19
  The core depends only on `grpcio`. Every integration is an opt-in extra, so you
20
20
  install exactly what you use.
21
21
 
22
+ > [!TIP]
23
+ > **Building this with an AI assistant?** Hand it
24
+ > **[one page](https://bedrock-python.github.io/grpc-server-kit/agents/)** instead of
25
+ > the whole site: the complete API surface, the ordering rules that break a server when
26
+ > they are broken (build-then-configure, outermost-first interceptors, Sentry inside the
27
+ > exception handler), the mistakes models actually make with `grpc.aio`, and a map of
28
+ > which page to fetch for the rest. Every docs page is also served as raw Markdown at its
29
+ > own URL, and a **Copy page** button at the top of each one hands it straight to a chat
30
+ > window.
31
+
22
32
  ## Installation
23
33
 
24
34
  ```bash
@@ -221,6 +231,10 @@ Runnable, self-contained scripts in [`examples/`](examples/) — each prints wha
221
231
 
222
232
  Full documentation at [bedrock-python.github.io/grpc-server-kit](https://bedrock-python.github.io/grpc-server-kit/).
223
233
 
234
+ - [For AI agents](https://bedrock-python.github.io/grpc-server-kit/agents/) — the whole
235
+ API surface, the rules that break a server when broken and a map of the rest, on one
236
+ page to hand to a coding assistant
237
+
224
238
  ## License
225
239
 
226
240
  Apache 2.0 — see [LICENSE](LICENSE).
@@ -10,6 +10,7 @@ from .protocols import (
10
10
  GrpcAsyncServerProtocol,
11
11
  GrpcServerProtocol,
12
12
  GrpcServerSettingsProtocol,
13
+ GrpcServiceName,
13
14
  GrpcSettingsProtocol,
14
15
  GrpcSslSettingsProtocol,
15
16
  )
@@ -23,6 +24,7 @@ __all__ = [
23
24
  "GrpcServerConfig",
24
25
  "GrpcServerProtocol",
25
26
  "GrpcServerSettingsProtocol",
27
+ "GrpcServiceName",
26
28
  "GrpcSettingsProtocol",
27
29
  "GrpcSslSettingsProtocol",
28
30
  "__version__",
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0"
@@ -7,11 +7,17 @@ from ..protocols import (
7
7
  GrpcAsyncServerProtocol,
8
8
  GrpcServerProtocol,
9
9
  GrpcServerSettingsProtocol,
10
+ GrpcServiceName,
10
11
  GrpcSettingsProtocol,
11
12
  GrpcSslSettingsProtocol,
12
13
  )
13
14
  from ..server import bind_server_port
14
- from ..signals import reset_signal_handlers, setup_signal_handlers
15
+ from ..signals import (
16
+ SignalManager,
17
+ reset_signal_handlers,
18
+ reset_signal_handlers_async,
19
+ setup_signal_handlers,
20
+ )
15
21
  from .app import GrpcApp
16
22
  from .builder import AsyncGrpcServerBuilder
17
23
  from .runtime import ServerLifecycleManager, run_async_grpc_server
@@ -30,15 +36,18 @@ __all__ = [
30
36
  "GrpcServerConfig",
31
37
  "GrpcServerProtocol",
32
38
  "GrpcServerSettingsProtocol",
39
+ "GrpcServiceName",
33
40
  "GrpcSettingsProtocol",
34
41
  "GrpcSslSettingsProtocol",
35
42
  "ServerLifecycleManager",
43
+ "SignalManager",
36
44
  "bind_server_port",
37
45
  "build_grpc_options",
38
46
  "create_async_grpc_server",
39
47
  "create_base_async_grpc_server",
40
48
  "load_server_credentials",
41
49
  "reset_signal_handlers",
50
+ "reset_signal_handlers_async",
42
51
  "run_async_grpc_server",
43
52
  "setup_signal_handlers",
44
53
  ]
@@ -12,7 +12,7 @@ from .base import AsyncServerInterceptor, RpcCall
12
12
  from .metadata import get_metadata_dict
13
13
 
14
14
  if TYPE_CHECKING:
15
- from collections.abc import AsyncIterator, Callable
15
+ from collections.abc import AsyncIterator, Callable, Collection
16
16
 
17
17
  import structlog
18
18
  else:
@@ -62,6 +62,8 @@ class AsyncContextInterceptor(AsyncServerInterceptor):
62
62
  bind_method_name: bool = True,
63
63
  bind_structlog: bool = True,
64
64
  method_key: str = "grpc_method",
65
+ *,
66
+ skip_methods: Collection[str] = (),
65
67
  ) -> None:
66
68
  """Initialize interceptor with header configurations.
67
69
 
@@ -71,8 +73,13 @@ class AsyncContextInterceptor(AsyncServerInterceptor):
71
73
  bind_structlog: Whether to bind extracted variables to structlog context
72
74
  (no-op if structlog is not installed).
73
75
  method_key: Key for the gRPC method name in context.
76
+ skip_methods: Full RPC method names to leave unwrapped. Empty by
77
+ default — unlike the observability interceptors, this one binds
78
+ values the handler itself may read, so nothing is skipped
79
+ unless you say so. Pass ``SKIPPED_HEALTH_METHODS`` to keep
80
+ health probes out (required headers included).
74
81
  """
75
- super().__init__()
82
+ super().__init__(skip_methods=skip_methods)
76
83
  self._header_configs = header_configs
77
84
  self._bind_method_name = bind_method_name
78
85
  self._bind_structlog = bind_structlog
@@ -30,7 +30,10 @@ from grpc_server_kit.constants import (
30
30
  DEFAULT_PORT,
31
31
  )
32
32
 
33
- GrpcCompressionAlgorithm = Literal["deflate", "gzip"]
33
+ # Mirrors the keys of ``grpc_server_kit.options.COMPRESSION_ALGORITHMS``:
34
+ # "none" is gRPC's explicit no-compression algorithm, not the absence of a
35
+ # setting (that is ``None``).
36
+ GrpcCompressionAlgorithm = Literal["none", "deflate", "gzip"]
34
37
 
35
38
 
36
39
  class BaseHealthSettings(BaseModel):
@@ -59,6 +62,10 @@ class BaseGrpcServerSettings(BaseModel):
59
62
  # Basic
60
63
  host: str = Field(default=DEFAULT_HOST, min_length=1, description="gRPC server host")
61
64
  port: int = Field(default=DEFAULT_PORT, ge=0, le=65535, description="gRPC server port (0 = ephemeral)")
65
+ allow_ephemeral_port: bool = Field(
66
+ default=False,
67
+ description="Accept port=0 (ephemeral); off by default, a Service targeting a fixed port cannot reach one",
68
+ )
62
69
 
63
70
  # TLS/SSL settings
64
71
  ssl_enabled: bool = Field(default=False, description="Enable TLS/SSL")
@@ -106,7 +113,7 @@ class BaseGrpcServerSettings(BaseModel):
106
113
  # Compression
107
114
  compression_algorithm: GrpcCompressionAlgorithm | None = Field(
108
115
  default=None,
109
- description="Default compression: deflate or gzip (None = no compression)",
116
+ description="Default compression: none, deflate or gzip (None = leave the gRPC default alone)",
110
117
  )
111
118
 
112
119
  # Flow control settings
@@ -132,6 +139,15 @@ class BaseGrpcServerSettings(BaseModel):
132
139
  # Health (consumed by GrpcApp.enable_health as its defaults)
133
140
  health: BaseHealthSettings = Field(default_factory=BaseHealthSettings, description="Health check configuration")
134
141
 
142
+ @model_validator(mode="after")
143
+ def _validate_port(self) -> "BaseGrpcServerSettings":
144
+ if self.port == 0 and not self.allow_ephemeral_port:
145
+ raise ValueError(
146
+ "gRPC port=0 binds an ephemeral port and a Service targeting a fixed port will not reach this "
147
+ "process; set allow_ephemeral_port=True if that is intended"
148
+ )
149
+ return self
150
+
135
151
  @model_validator(mode="after")
136
152
  def _validate_ssl(self) -> "BaseGrpcServerSettings":
137
153
  if self.ssl_enabled:
@@ -122,6 +122,10 @@ warn_unreachable = true
122
122
  [tool.ruff]
123
123
  line-length = 120
124
124
  target-version = "py312"
125
+ # The Markdown guides hold fragments -- a keyword argument on its own, a body
126
+ # without its def -- that read as code to a formatter and come out as
127
+ # something else. ruff 0.16 formats fenced Python in Markdown by default.
128
+ extend-exclude = ["*.md"]
125
129
 
126
130
  [tool.ruff.lint]
127
131
  select = ["F", "E", "W", "I", "B", "N", "S", "C4", "DTZ", "SIM", "TRY", "PERF", "RUF", "UP", "ANN", "T20", "PTH", "PLC", "PLE", "PLW"]
@@ -1 +0,0 @@
1
- __version__ = "0.1.0"
File without changes