feat: Allow representing enums with their unqualified symbolic names in headers (#465)
* 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 <partheniou@google.com>
Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py
index a7bcb5a..28b13ab 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_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 9bc2d96..4dcae55 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -94,7 +94,6 @@
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 8a60b15..5a83032 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 3037867..9d31eb3 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 @@
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)