From 522b98ecc1ebd1c2280d3d7c73a02f6e4fb528d4 Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Thu, 10 Nov 2022 07:27:57 -0800 Subject: [PATCH] feat: Allow representing enums with their unqualified symbolic names in headers (#465) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Allow non-fully-qualified enums in routing headers * Rename s/fully_qualified_enums/qualified_enums/g for correctness * chore: minor tweaks * chore: Temporary workaround for pytest in noxfile. * Fix import order * bring coverage to 100% * lint * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * remove replacement in owlbot.py causing lint failure Co-authored-by: Anthonios Partheniou Co-authored-by: Owl Bot --- google/api_core/gapic_v1/routing_header.py | 20 +++++++++++--- noxfile.py | 1 - owlbot.py | 2 -- tests/unit/gapic/test_routing_header.py | 31 ++++++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py index a7bcb5a8..28b13abf 100644 --- a/google/api_core/gapic_v1/routing_header.py +++ b/google/api_core/gapic_v1/routing_header.py @@ -20,21 +20,32 @@ Generally, these headers are specified as gRPC metadata. """ +from enum import Enum from urllib.parse import urlencode ROUTING_METADATA_KEY = "x-goog-request-params" -def to_routing_header(params): +def to_routing_header(params, qualified_enums=True): """Returns a routing header string for the given request parameters. Args: params (Mapping[str, Any]): A dictionary containing the request parameters used for routing. + qualified_enums (bool): Whether to represent enum values + as their type-qualified symbol names instead of as their + unqualified symbol names. Returns: str: The routing header string. + """ + if not qualified_enums: + if isinstance(params, dict): + tuples = params.items() + else: + tuples = params + params = [(x[0], x[1].name) if isinstance(x[1], Enum) else x for x in tuples] return urlencode( params, # Per Google API policy (go/api-url-encoding), / is not encoded. @@ -42,16 +53,19 @@ def to_routing_header(params): ) -def to_grpc_metadata(params): +def to_grpc_metadata(params, qualified_enums=True): """Returns the gRPC metadata containing the routing headers for the given request parameters. Args: params (Mapping[str, Any]): A dictionary containing the request parameters used for routing. + qualified_enums (bool): Whether to represent enum values + as their type-qualified symbol names instead of as their + unqualified symbol names. Returns: Tuple(str, str): The gRPC metadata containing the routing header key and value. """ - return (ROUTING_METADATA_KEY, to_routing_header(params)) + return (ROUTING_METADATA_KEY, to_routing_header(params, qualified_enums)) diff --git a/noxfile.py b/noxfile.py index 9bc2d967..4dcae556 100644 --- a/noxfile.py +++ b/noxfile.py @@ -94,7 +94,6 @@ def default(session, install_grpc=True): CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" ) - # Install all test dependencies, then install this package in-place. session.install( "dataclasses", "mock", diff --git a/owlbot.py b/owlbot.py index 8a60b152..5a83032e 100644 --- a/owlbot.py +++ b/owlbot.py @@ -48,8 +48,6 @@ """, ) -s.replace(".github/workflows/lint.yml", "python-version: \"3.10\"", "python-version: \"3.7\"") - python.configure_previous_major_version_branches() s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 30378676..9d31eb39 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from enum import Enum + import pytest try: @@ -35,6 +37,35 @@ def test_to_routing_header_with_slashes(): assert value == "name=me/ep&book.read=1%262" +def test_enum_fully_qualified(): + class Message: + class Color(Enum): + RED = 1 + GREEN = 2 + BLUE = 3 + + params = [("color", Message.Color.RED)] + value = routing_header.to_routing_header(params) + assert value == "color=Color.RED" + value = routing_header.to_routing_header(params, qualified_enums=True) + assert value == "color=Color.RED" + + +def test_enum_nonqualified(): + class Message: + class Color(Enum): + RED = 1 + GREEN = 2 + BLUE = 3 + + params = [("color", Message.Color.RED), ("num", 5)] + value = routing_header.to_routing_header(params, qualified_enums=False) + assert value == "color=RED&num=5" + params = {"color": Message.Color.RED, "num": 5} + value = routing_header.to_routing_header(params, qualified_enums=False) + assert value == "color=RED&num=5" + + def test_to_grpc_metadata(): params = [("name", "meep"), ("book.read", "1")] metadata = routing_header.to_grpc_metadata(params)