Compare commits

...

4 Commits

Author SHA1 Message Date
Chris Chua 3e221b77b4
Merge 0dfe05769e into 62f968a4c8 2024-07-31 12:32:13 +02:00
Vladimir Magamedov 62f968a4c8 Updated changelog, issued 0.4.8rc2 release candidate 2024-07-24 23:09:16 +03:00
Vladimir Magamedov e9adb679ec Fixed Channel to construct valid authority header when host is the IPv6 address, closes #197 2024-07-21 21:34:11 +03:00
chua 0dfe05769e first configurable version of adding a prefix 2024-06-28 07:55:48 +00:00
5 changed files with 51 additions and 10 deletions

View File

@ -4,6 +4,9 @@ Changelog
0.4.8
~~~~~
- Fixed ``authority`` header for the case when Channel's ``host`` argument
is the IPv6 address
- Fixed ``Channel`` for the case when ``ssl`` module is not available
- Dropped Python 3.7 support
- Added "wheel" packaging format

View File

@ -1,7 +1,7 @@
from .const import Status
from .exceptions import GRPCError
__version__ = '0.4.8rc1'
__version__ = '0.4.8rc2'
__all__ = (
'Status',

View File

@ -4,6 +4,7 @@ import http
import time
import asyncio
import warnings
import ipaddress
from types import TracebackType
from typing import Generic, Optional, Union, Type, List, Sequence, Any, cast
@ -683,9 +684,8 @@ class Channel:
self._codec = codec
self._status_details_codec = status_details_codec
self._ssl = ssl or None
self._authority = '{}:{}'.format(self._host, self._port)
self._scheme = 'https' if self._ssl else 'http'
self._authority = '{}:{}'.format(self._host, self._port)
self._authority = self._get_authority(self._host, self._port)
self._h2_config = H2Configuration(
client_side=True,
header_encoding='ascii',
@ -779,6 +779,15 @@ class Channel:
ctx.set_alpn_protocols(['h2'])
return ctx
def _get_authority(self, host: str, port: int) -> str:
try:
ipv6_address = ipaddress.IPv6Address(host)
except ipaddress.AddressValueError:
pass
else:
host = f"[{ipv6_address}]"
return "{}:{}".format(host, port)
def request(
self,
name: str,

View File

@ -22,6 +22,7 @@ _CARDINALITY = {
(True, True): const.Cardinality.STREAM_STREAM,
}
_PB2_MODULE_PREFIX_PARAMETER_KEY = 'pb2_module_prefix'
class Method(NamedTuple):
name: str
@ -174,8 +175,9 @@ def _base_module_name(proto_file_path: str) -> str:
return basename.replace("-", "_").replace("/", ".")
_pb2_module_prefix: str = ''
def _proto2pb2_module_name(proto_file_path: str) -> str:
return _base_module_name(proto_file_path) + "_pb2"
return _pb2_module_prefix + _base_module_name(proto_file_path) + "_pb2"
def _proto2grpc_module_name(proto_file_path: str) -> str:
@ -208,10 +210,19 @@ def _type_names(
parents.pop()
def _populate_config(request_parameter: str):
global _pb2_module_prefix
config = dict(item.split("=") for item in request_parameter.split(','))
if config.get(_PB2_MODULE_PREFIX_PARAMETER_KEY):
_pb2_module_prefix = config[_PB2_MODULE_PREFIX_PARAMETER_KEY]
def main() -> None:
with os.fdopen(sys.stdin.fileno(), 'rb') as inp:
request = CodeGeneratorRequest.FromString(inp.read())
_populate_config(request.parameter)
types_map: Dict[str, str] = {}
for pf in request.proto_file:
for mt in pf.message_type:

View File

@ -1,6 +1,7 @@
import os
import socket
import tempfile
import ipaddress
import pytest
@ -46,19 +47,27 @@ class ClientServer:
channel = None
channel_ctx = None
def __init__(self, *, host="127.0.0.1"):
self.host = host
async def __aenter__(self):
host = '127.0.0.1'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('127.0.0.1', 0))
_, port = s.getsockname()
try:
ipaddress.IPv6Address(self.host)
except ipaddress.AddressValueError:
family = socket.AF_INET
else:
family = socket.AF_INET6
with socket.socket(family, socket.SOCK_STREAM) as s:
s.bind((self.host, 0))
_, port, *_ = s.getsockname()
dummy_service = DummyService()
self.server = Server([dummy_service])
await self.server.start(host, port)
await self.server.start(self.host, port)
self.server_ctx = await self.server.__aenter__()
self.channel = Channel(host=host, port=port)
self.channel = Channel(host=self.host, port=port)
self.channel_ctx = await self.channel.__aenter__()
dummy_stub = DummyServiceStub(self.channel)
return dummy_service, dummy_stub
@ -211,3 +220,12 @@ async def test_stream_stream_advanced():
assert await stream.recv_message() == DummyReply(value='baz')
assert await stream.recv_message() is None
@pytest.mark.asyncio
@pytest.mark.skipif(not socket.has_ipv6, reason="No IPv6 support")
async def test_ipv6():
async with ClientServer(host="::1") as (handler, stub):
reply = await stub.UnaryUnary(DummyRequest(value='ping'))
assert reply == DummyReply(value='pong')
assert handler.log == [DummyRequest(value='ping')]