From c596635473515be921a01538ee3f330a9d70c21e Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Mon, 24 Oct 2022 16:05:34 -0700 Subject: [PATCH 1/9] feat: Allow non-fully-qualified enums in routing headers --- google/api_core/gapic_v1/routing_header.py | 20 ++++++++++++++--- tests/unit/gapic/test_routing_header.py | 26 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py index a7bcb5a8..1251f1a3 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, fully_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. + fully_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 fully_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, fully_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. + fully_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, fully_qualified_enums)) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 30378676..0aab7602 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -14,6 +14,8 @@ import pytest +from enum import Enum + try: import grpc # noqa: F401 except ImportError: @@ -35,6 +37,30 @@ 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, fully_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, fully_qualified_enums=False) + assert value == "color=RED" + + def test_to_grpc_metadata(): params = [("name", "meep"), ("book.read", "1")] metadata = routing_header.to_grpc_metadata(params) From 860d7743cb42b87a819035205ccdb820775d591f Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Mon, 24 Oct 2022 20:17:52 -0700 Subject: [PATCH 2/9] Rename s/fully_qualified_enums/qualified_enums/g for correctness --- google/api_core/gapic_v1/routing_header.py | 12 ++++++------ tests/unit/gapic/test_routing_header.py | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py index 1251f1a3..e5da01aa 100644 --- a/google/api_core/gapic_v1/routing_header.py +++ b/google/api_core/gapic_v1/routing_header.py @@ -26,13 +26,13 @@ ROUTING_METADATA_KEY = "x-goog-request-params" -def to_routing_header(params, fully_qualified_enums=True): +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. - fully_qualified_enums (bool): Whether to represent enum values + qualified_enums (bool): Whether to represent enum values as their type-qualified symbol names instead of as their unqualified symbol names. @@ -40,7 +40,7 @@ def to_routing_header(params, fully_qualified_enums=True): str: The routing header string. """ - if not fully_qualified_enums: + if not qualified_enums: if isinstance(params, dict): tuples = params.items() else: @@ -53,14 +53,14 @@ def to_routing_header(params, fully_qualified_enums=True): ) -def to_grpc_metadata(params, fully_qualified_enums=True): +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. - fully_qualified_enums (bool): Whether to represent enum values + qualified_enums (bool): Whether to represent enum values as their type-qualified symbol names instead of as their unqualified symbol names. @@ -68,4 +68,4 @@ def to_grpc_metadata(params, fully_qualified_enums=True): Tuple(str, str): The gRPC metadata containing the routing header key and value. """ - return (ROUTING_METADATA_KEY, to_routing_header(params, fully_qualified_enums)) + return (ROUTING_METADATA_KEY, to_routing_header(params, qualified_enums)) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 0aab7602..002c518e 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -46,7 +46,7 @@ class Color(Enum): params = [("color", Message.Color.RED)] value = routing_header.to_routing_header(params) assert value == "color=Color.RED" - value = routing_header.to_routing_header(params, fully_qualified_enums=True) + value = routing_header.to_routing_header(params, qualified_enums=True) assert value == "color=Color.RED" @@ -57,8 +57,8 @@ class Color(Enum): GREEN = 2 BLUE = 3 params = [("color", Message.Color.RED),("num",5)] - value = routing_header.to_routing_header(params, fully_qualified_enums=False) - assert value == "color=RED" + value = routing_header.to_routing_header(params, qualified_enums=False) + assert value == "color=RED&num=5" def test_to_grpc_metadata(): From 697c4e9f8db90e1ab3ad2a15f9d65257c8afedfd Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Mon, 7 Nov 2022 12:47:58 -0800 Subject: [PATCH 3/9] chore: minor tweaks --- google/api_core/gapic_v1/routing_header.py | 2 +- tests/unit/gapic/test_routing_header.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py index e5da01aa..28b13abf 100644 --- a/google/api_core/gapic_v1/routing_header.py +++ b/google/api_core/gapic_v1/routing_header.py @@ -45,7 +45,7 @@ def to_routing_header(params, qualified_enums=True): tuples = params.items() else: tuples = params - params = [(x[0],x[1].name) if isinstance(x[1], Enum) else x for x in tuples] + 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. diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 002c518e..7fdeb334 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -40,9 +40,10 @@ def test_to_routing_header_with_slashes(): def test_enum_fully_qualified(): class Message: class Color(Enum): - RED= 1 + RED = 1 GREEN = 2 BLUE = 3 + params = [("color", Message.Color.RED)] value = routing_header.to_routing_header(params) assert value == "color=Color.RED" @@ -53,10 +54,11 @@ class Color(Enum): def test_enum_nonqualified(): class Message: class Color(Enum): - RED= 1 + RED = 1 GREEN = 2 BLUE = 3 - params = [("color", Message.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" From 35b8d51b188d3749b077022083eb8430c29eacd3 Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Mon, 7 Nov 2022 17:49:26 -0800 Subject: [PATCH 4/9] chore: Temporary workaround for pytest in noxfile. --- noxfile.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index 2d8f1e02..3e890c64 100644 --- a/noxfile.py +++ b/noxfile.py @@ -95,7 +95,10 @@ def default(session, install_grpc=True): ) # Install all test dependencies, then install this package in-place. - session.install("dataclasses", "mock", "pytest", "pytest-cov", "pytest-xdist") + # + # TODO: Revert to just "pytest" once + # https://github.com/pytest-dev/pytest/issues/10451 is fixed, as per PR#462 + session.install("dataclasses", "mock", "pytest<7.2.0", "pytest-cov", "pytest-xdist") if install_grpc: session.install("-e", ".[grpc]", "-c", constraints_path) else: From e0877ad28b46debd700b7fad4a682232b736bc8e Mon Sep 17 00:00:00 2001 From: Victor Chudnovsky Date: Mon, 7 Nov 2022 17:55:40 -0800 Subject: [PATCH 5/9] Fix import order --- tests/unit/gapic/test_routing_header.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 7fdeb334..fcb04a76 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest - from enum import Enum +import pytest + try: import grpc # noqa: F401 except ImportError: From 587bbbea7d7180efbe8e503d0ec5eb578c1fe78d Mon Sep 17 00:00:00 2001 From: Anthonios Partheniou Date: Thu, 10 Nov 2022 10:23:31 -0500 Subject: [PATCH 6/9] bring coverage to 100% --- tests/unit/gapic/test_routing_header.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index fcb04a76..27ab5509 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -61,6 +61,9 @@ class Color(Enum): 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(): From 12da402e845fbce0bd3449eb0c4b3fc7937303c6 Mon Sep 17 00:00:00 2001 From: Anthonios Partheniou Date: Thu, 10 Nov 2022 15:25:23 +0000 Subject: [PATCH 7/9] lint --- tests/unit/gapic/test_routing_header.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 27ab5509..9d31eb39 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -61,7 +61,7 @@ class Color(Enum): 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} + params = {"color": Message.Color.RED, "num": 5} value = routing_header.to_routing_header(params, qualified_enums=False) assert value == "color=RED&num=5" From 1ead8af8d8b8bd9c30cfb544735e6c95bf2a09d5 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Thu, 10 Nov 2022 15:25:32 +0000 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20po?= =?UTF-8?q?st-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .github/workflows/lint.yml | 2 +- tests/unit/gapic/test_routing_header.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d2aee5b7..eae860a2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.7" - name: Install nox run: | python -m pip install --upgrade setuptools pip wheel diff --git a/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py index 27ab5509..9d31eb39 100644 --- a/tests/unit/gapic/test_routing_header.py +++ b/tests/unit/gapic/test_routing_header.py @@ -61,7 +61,7 @@ class Color(Enum): 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} + params = {"color": Message.Color.RED, "num": 5} value = routing_header.to_routing_header(params, qualified_enums=False) assert value == "color=RED&num=5" From 7812c3e5fec081c7bd78093e01ec6dd3c42dfebc Mon Sep 17 00:00:00 2001 From: Anthonios Partheniou Date: Thu, 10 Nov 2022 10:26:29 -0500 Subject: [PATCH 9/9] remove replacement in owlbot.py causing lint failure --- .github/workflows/lint.yml | 2 +- owlbot.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index eae860a2..d2aee5b7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" - name: Install nox run: | python -m pip install --upgrade setuptools pip wheel 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)