pydantic-rpc 0.11.0__py3-none-any.whl → 0.12.0__py3-none-any.whl

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.
pydantic_rpc/core.py CHANGED
@@ -27,7 +27,7 @@ import annotated_types
27
27
  import grpc
28
28
  from grpc import ServicerContext
29
29
  import grpc_tools
30
- from connecpy.code import Code as Errors
30
+ from connectrpc.code import Code as Errors
31
31
 
32
32
  # Protobuf Python modules for Timestamp, Duration (requires protobuf / grpcio)
33
33
  from google.protobuf import duration_pb2, timestamp_pb2, empty_pb2
@@ -726,15 +726,15 @@ def connect_obj_with_stub_async(
726
726
  return ConcreteServiceClass
727
727
 
728
728
 
729
- def connect_obj_with_stub_connecpy(
730
- connecpy_module: Any, pb2_module: Any, obj: object
729
+ def connect_obj_with_stub_connect_python(
730
+ connect_python_module: Any, pb2_module: Any, obj: object
731
731
  ) -> type:
732
732
  """
733
- Connect a Python service object to a Connecpy stub.
733
+ Connect a Python service object to a Connect Python stub.
734
734
  """
735
735
  service_class = obj.__class__
736
736
  stub_class_name = service_class.__name__
737
- stub_class = getattr(connecpy_module, stub_class_name)
737
+ stub_class = getattr(connect_python_module, stub_class_name)
738
738
 
739
739
  class ConcreteServiceClass(stub_class):
740
740
  pass
@@ -845,15 +845,15 @@ def connect_obj_with_stub_connecpy(
845
845
  return ConcreteServiceClass
846
846
 
847
847
 
848
- def connect_obj_with_stub_async_connecpy(
849
- connecpy_module: Any, pb2_module: Any, obj: object
848
+ def connect_obj_with_stub_async_connect_python(
849
+ connect_python_module: Any, pb2_module: Any, obj: object
850
850
  ) -> type:
851
851
  """
852
- Connect a Python service object to a Connecpy stub for async methods with streaming support.
852
+ Connect a Python service object to a Connect Python stub for async methods with streaming support.
853
853
  """
854
854
  service_class = obj.__class__
855
855
  stub_class_name = service_class.__name__
856
- stub_class = getattr(connecpy_module, stub_class_name)
856
+ stub_class = getattr(connect_python_module, stub_class_name)
857
857
 
858
858
  class ConcreteServiceClass(stub_class):
859
859
  pass
@@ -2030,10 +2030,10 @@ def generate_grpc_code(proto_path: Path) -> types.ModuleType | None:
2030
2030
  return module
2031
2031
 
2032
2032
 
2033
- def generate_connecpy_code(proto_path: Path) -> types.ModuleType | None:
2033
+ def generate_connect_python_code(proto_path: Path) -> types.ModuleType | None:
2034
2034
  """
2035
- Run protoc with the Connecpy plugin to generate Python Connecpy code from proto_path.
2036
- Writes foo_connecpy.py next to proto_path, then imports and returns that module.
2035
+ Run protoc with the Connect Python plugin to generate Python Connect code from proto_path.
2036
+ Writes foo_connect_python.py next to proto_path, then imports and returns that module.
2037
2037
  """
2038
2038
  # 1) Ensure the .proto exists
2039
2039
  if not proto_path.is_file():
@@ -2051,7 +2051,7 @@ def generate_connecpy_code(proto_path: Path) -> types.ModuleType | None:
2051
2051
  "protoc", # Dummy program name (required for protoc.main)
2052
2052
  "-I.",
2053
2053
  f"-I{well_known_path}",
2054
- f"--connecpy_out={out_str}",
2054
+ f"--connect-python_out={out_str}",
2055
2055
  proto_path.name,
2056
2056
  ]
2057
2057
 
@@ -2065,7 +2065,7 @@ def generate_connecpy_code(proto_path: Path) -> types.ModuleType | None:
2065
2065
 
2066
2066
  # 4) Locate the generated file
2067
2067
  base_name = proto_path.stem # "foo"
2068
- generated_filename = f"{base_name}_connecpy.py" # "foo_connecpy.py"
2068
+ generated_filename = f"{base_name}_connect.py" # "foo_connect.py"
2069
2069
  generated_filepath = out_dir / generated_filename
2070
2070
 
2071
2071
  # 5) Add out_dir to sys.path so we can import by filename
@@ -2074,7 +2074,7 @@ def generate_connecpy_code(proto_path: Path) -> types.ModuleType | None:
2074
2074
 
2075
2075
  # 6) Load and return the module
2076
2076
  spec = importlib.util.spec_from_file_location(
2077
- base_name + "_connecpy", str(generated_filepath)
2077
+ base_name + "_connect", str(generated_filepath)
2078
2078
  )
2079
2079
  if spec is None or spec.loader is None:
2080
2080
  return None
@@ -2259,7 +2259,7 @@ def get_proto_path(proto_filename: str) -> Path:
2259
2259
  return base / proto_filename
2260
2260
 
2261
2261
 
2262
- def generate_and_compile_proto_using_connecpy(
2262
+ def generate_and_compile_proto_using_connect_python(
2263
2263
  obj: object,
2264
2264
  package_name: str = "",
2265
2265
  existing_proto_path: Path | None = None,
@@ -2268,7 +2268,7 @@ def generate_and_compile_proto_using_connecpy(
2268
2268
  import importlib
2269
2269
 
2270
2270
  pb2_module = None
2271
- connecpy_module = None
2271
+ connect_python_module = None
2272
2272
 
2273
2273
  try:
2274
2274
  pb2_module = importlib.import_module(
@@ -2278,14 +2278,14 @@ def generate_and_compile_proto_using_connecpy(
2278
2278
  pass
2279
2279
 
2280
2280
  try:
2281
- connecpy_module = importlib.import_module(
2282
- f"{obj.__class__.__name__.lower()}_connecpy"
2281
+ connect_python_module = importlib.import_module(
2282
+ f"{obj.__class__.__name__.lower()}_connect"
2283
2283
  )
2284
2284
  except ImportError:
2285
2285
  pass
2286
2286
 
2287
- if connecpy_module is not None and pb2_module is not None:
2288
- return connecpy_module, pb2_module
2287
+ if connect_python_module is not None and pb2_module is not None:
2288
+ return connect_python_module, pb2_module
2289
2289
 
2290
2290
  # If the modules are not found, generate and compile the proto files.
2291
2291
 
@@ -2306,10 +2306,10 @@ def generate_and_compile_proto_using_connecpy(
2306
2306
  if gen_pb is None:
2307
2307
  raise Exception("Generating pb code")
2308
2308
 
2309
- gen_connecpy = generate_connecpy_code(proto_file_path)
2310
- if gen_connecpy is None:
2311
- raise Exception("Generating Connecpy code")
2312
- return gen_connecpy, gen_pb
2309
+ gen_connect_python = generate_connect_python_code(proto_file_path)
2310
+ if gen_connect_python is None:
2311
+ raise Exception("Generating Connect Python code")
2312
+ return gen_connect_python, gen_pb
2313
2313
 
2314
2314
 
2315
2315
  def is_combined_proto_enabled() -> bool:
@@ -2804,20 +2804,24 @@ class AsyncIOServer:
2804
2804
  await self._server.stop(10)
2805
2805
  print("gRPC server shutdown.")
2806
2806
 
2807
+ async def stop(self, grace: float = 10.0):
2808
+ """Stop the gRPC server gracefully."""
2809
+ await self._server.stop(grace)
2807
2810
 
2808
- def get_connecpy_asgi_app_class(connecpy_module: Any, service_name: str):
2809
- """Get the ASGI application class from connecpy module (Connecpy v2.x)."""
2810
- return getattr(connecpy_module, f"{service_name}ASGIApplication")
2811
2811
 
2812
+ def get_connect_python_asgi_app_class(connect_python_module: Any, service_name: str):
2813
+ """Get the ASGI application class from connect-python module."""
2814
+ return getattr(connect_python_module, f"{service_name}ASGIApplication")
2812
2815
 
2813
- def get_connecpy_wsgi_app_class(connecpy_module: Any, service_name: str):
2814
- """Get the WSGI application class from connecpy module (Connecpy v2.x)."""
2815
- return getattr(connecpy_module, f"{service_name}WSGIApplication")
2816
+
2817
+ def get_connect_python_wsgi_app_class(connect_python_module: Any, service_name: str):
2818
+ """Get the WSGI application class from connect-python module."""
2819
+ return getattr(connect_python_module, f"{service_name}WSGIApplication")
2816
2820
 
2817
2821
 
2818
2822
  class ASGIApp:
2819
2823
  """
2820
- An ASGI-compatible application that can serve Connect-RPC via Connecpy.
2824
+ An ASGI-compatible application that can serve Connect-RPC via connect-python.
2821
2825
  """
2822
2826
 
2823
2827
  def __init__(self, service: Optional[object] = None, package_name: str = ""):
@@ -2828,23 +2832,25 @@ class ASGIApp:
2828
2832
 
2829
2833
  def mount(self, obj: object, package_name: str = ""):
2830
2834
  """Generate and compile proto files, then mount the async service implementation."""
2831
- connecpy_module, pb2_module = generate_and_compile_proto_using_connecpy(
2832
- obj, package_name
2835
+ connect_python_module, pb2_module = (
2836
+ generate_and_compile_proto_using_connect_python(obj, package_name)
2833
2837
  )
2834
- self.mount_using_pb2_modules(connecpy_module, pb2_module, obj)
2838
+ self.mount_using_pb2_modules(connect_python_module, pb2_module, obj)
2835
2839
 
2836
2840
  def mount_using_pb2_modules(
2837
- self, connecpy_module: Any, pb2_module: Any, obj: object
2841
+ self, connect_python_module: Any, pb2_module: Any, obj: object
2838
2842
  ):
2839
- """Connect the compiled connecpy and pb2 modules with the async service implementation."""
2840
- concreteServiceClass = connect_obj_with_stub_async_connecpy(
2841
- connecpy_module, pb2_module, obj
2843
+ """Connect the compiled connect-python and pb2 modules with the async service implementation."""
2844
+ concreteServiceClass = connect_obj_with_stub_async_connect_python(
2845
+ connect_python_module, pb2_module, obj
2842
2846
  )
2843
2847
  service_name = obj.__class__.__name__
2844
2848
  service_impl = concreteServiceClass()
2845
2849
 
2846
2850
  # Get the service-specific ASGI application class
2847
- app_class = get_connecpy_asgi_app_class(connecpy_module, service_name)
2851
+ app_class = get_connect_python_asgi_app_class(
2852
+ connect_python_module, service_name
2853
+ )
2848
2854
  app = app_class(service=service_impl)
2849
2855
 
2850
2856
  # Store the app and its path for routing
@@ -2899,7 +2905,7 @@ class ASGIApp:
2899
2905
 
2900
2906
  class WSGIApp:
2901
2907
  """
2902
- A WSGI-compatible application that can serve Connect-RPC via Connecpy.
2908
+ A WSGI-compatible application that can serve Connect-RPC via connect-python.
2903
2909
  """
2904
2910
 
2905
2911
  def __init__(self, service: Optional[object] = None, package_name: str = ""):
@@ -2910,23 +2916,25 @@ class WSGIApp:
2910
2916
 
2911
2917
  def mount(self, obj: object, package_name: str = ""):
2912
2918
  """Generate and compile proto files, then mount the sync service implementation."""
2913
- connecpy_module, pb2_module = generate_and_compile_proto_using_connecpy(
2914
- obj, package_name
2919
+ connect_python_module, pb2_module = (
2920
+ generate_and_compile_proto_using_connect_python(obj, package_name)
2915
2921
  )
2916
- self.mount_using_pb2_modules(connecpy_module, pb2_module, obj)
2922
+ self.mount_using_pb2_modules(connect_python_module, pb2_module, obj)
2917
2923
 
2918
2924
  def mount_using_pb2_modules(
2919
- self, connecpy_module: Any, pb2_module: Any, obj: object
2925
+ self, connect_python_module: Any, pb2_module: Any, obj: object
2920
2926
  ):
2921
- """Connect the compiled connecpy and pb2 modules with the sync service implementation."""
2922
- concreteServiceClass = connect_obj_with_stub_connecpy(
2923
- connecpy_module, pb2_module, obj
2927
+ """Connect the compiled connect-python and pb2 modules with the sync service implementation."""
2928
+ concreteServiceClass = connect_obj_with_stub_connect_python(
2929
+ connect_python_module, pb2_module, obj
2924
2930
  )
2925
2931
  service_name = obj.__class__.__name__
2926
2932
  service_impl = concreteServiceClass()
2927
2933
 
2928
2934
  # Get the service-specific WSGI application class
2929
- app_class = get_connecpy_wsgi_app_class(connecpy_module, service_name)
2935
+ app_class = get_connect_python_wsgi_app_class(
2936
+ connect_python_module, service_name
2937
+ )
2930
2938
  app = app_class(service=service_impl)
2931
2939
 
2932
2940
  # Store the app and its path for routing
@@ -3,7 +3,7 @@
3
3
  from typing import Any, Callable, Dict, List, Optional, TypeVar, Type
4
4
  from functools import wraps
5
5
  import grpc
6
- from connecpy.code import Code as ConnectErrors
6
+ from connectrpc.code import Code as ConnectErrors
7
7
 
8
8
  from .options import OptionMetadata, OPTION_METADATA_ATTR
9
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pydantic-rpc
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: A Python library for building gRPC/ConnectRPC services with Pydantic models.
5
5
  Author: Yasushi Itoh
6
6
  Requires-Dist: annotated-types==0.7.0
@@ -9,7 +9,8 @@ Requires-Dist: grpcio>=1.56.2
9
9
  Requires-Dist: grpcio-tools>=1.56.2
10
10
  Requires-Dist: grpcio-reflection>=1.56.2
11
11
  Requires-Dist: grpcio-health-checking>=1.56.2
12
- Requires-Dist: connecpy>=2.2.0
12
+ Requires-Dist: connect-python>=0.5.0
13
+ Requires-Dist: protoc-gen-connect-python>=0.1.0
13
14
  Requires-Dist: mcp>=1.9.4
14
15
  Requires-Dist: starlette>=0.27.0
15
16
  Requires-Python: >=3.11
@@ -1247,6 +1248,64 @@ class MyMessage(Message):
1247
1248
 
1248
1249
  This approach works because protobuf allows message types within `oneof` fields, and the collections are contained within those messages.
1249
1250
 
1251
+ ## 🔧 Development
1252
+
1253
+ This project uses [`just`](https://github.com/casey/just) as a command runner for development tasks.
1254
+
1255
+ ### Installing just
1256
+
1257
+ **macOS:**
1258
+ ```bash
1259
+ brew install just
1260
+ ```
1261
+
1262
+ **Linux:**
1263
+ ```bash
1264
+ curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin
1265
+ ```
1266
+
1267
+ **Windows:**
1268
+ Download from [GitHub releases](https://github.com/casey/just/releases)
1269
+
1270
+ ### Quick Start
1271
+
1272
+ ```bash
1273
+ # Install dependencies
1274
+ just install
1275
+
1276
+ # Run tests
1277
+ just test # or just t
1278
+
1279
+ # Format and lint code
1280
+ just format # or just f
1281
+ just lint # or just l
1282
+
1283
+ # Run all checks (lint + tests)
1284
+ just check # or just c
1285
+
1286
+ # See all available commands
1287
+ just --list
1288
+ ```
1289
+
1290
+ ### Running Examples
1291
+
1292
+ ```bash
1293
+ # Start servers
1294
+ just greeting-server # gRPC server on port 50051
1295
+ just greeting-asgi # Connect RPC ASGI on port 8000
1296
+ just greeting-wsgi # Connect RPC WSGI on port 3000
1297
+
1298
+ # Test with buf curl (in another terminal)
1299
+ just greet # gRPC request
1300
+ just connect-greet # Connect RPC request
1301
+ just wsgi-greet # WSGI request
1302
+
1303
+ # Custom names
1304
+ just greet-name Alice
1305
+ just connect-greet-name Bob
1306
+ ```
1307
+
1308
+ For more development commands and options, see the [Justfile](Justfile) or run `just --list`.
1250
1309
 
1251
1310
  ## TODO
1252
1311
  - [x] Streaming Support
@@ -1,12 +1,12 @@
1
1
  pydantic_rpc/__init__.py,sha256=c5e0b5d4ed6de3e3c7c1ada5389e704ce149ea56ca0930392db6abdf222b4e86,871
2
- pydantic_rpc/core.py,sha256=9f1a8e669df10d99fea575b83efcb7209c186e461de0ae7050e0592ee675d45c,114131
3
- pydantic_rpc/decorators.py,sha256=d147eb7c0814043b79ef2f8551947341f32852296467b35b12bc4e63469ef294,6217
2
+ pydantic_rpc/core.py,sha256=450c03111224052a3e2b85567ffd16a0ff6dd4d6f02bcfa23c09f6d39cf30861,114578
3
+ pydantic_rpc/decorators.py,sha256=94d87825e034b6303df46dd74e6c8c7ed5c88133aa504d61249a83dbf82f1de3,6219
4
4
  pydantic_rpc/mcp/__init__.py,sha256=f05ad62cc38db5c5972e16870c484523c58c5ac650d8454706f1ce4539cc7a52,123
5
5
  pydantic_rpc/mcp/converter.py,sha256=b60dcaf82e6bff6be4b2ab8b1e9f2d16e09cb98d8f00182a4f6f73d1a78848a4,4158
6
6
  pydantic_rpc/mcp/exporter.py,sha256=20833662f9a973ed9e1a705b9b59aaa2533de6c514ebd87ef66664a430a0d04f,10239
7
7
  pydantic_rpc/options.py,sha256=6094036184a500b92715fd91d31ecc501460a56de47dcf6024c6335ae8e5d6e3,4561
8
8
  pydantic_rpc/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
9
9
  pydantic_rpc/tls.py,sha256=0eb290cc09c8ebedc71e7a97c01736d9675a314f70ebd80a2ce73e3f1689d359,3567
10
- pydantic_rpc-0.11.0.dist-info/WHEEL,sha256=ab6157bc637547491fb4567cd7ddf26b04d63382916ca16c29a5c8e94c9c9ef7,79
11
- pydantic_rpc-0.11.0.dist-info/METADATA,sha256=fae01debdcc0725d6cc2f89180d9dd88cfcb5e05581faee71b75f95b4119b195,34906
12
- pydantic_rpc-0.11.0.dist-info/RECORD,,
10
+ pydantic_rpc-0.12.0.dist-info/WHEEL,sha256=ab6157bc637547491fb4567cd7ddf26b04d63382916ca16c29a5c8e94c9c9ef7,79
11
+ pydantic_rpc-0.12.0.dist-info/METADATA,sha256=daa91c220e04adae53cb3e654d249f2feaca8e461f84e9d03f70fad2b48e403b,36156
12
+ pydantic_rpc-0.12.0.dist-info/RECORD,,