2020Generally, these headers are specified as gRPC metadata.
2121"""
2222
23+ import functools
2324from enum import Enum
2425from urllib .parse import urlencode
2526
2627ROUTING_METADATA_KEY = "x-goog-request-params"
28+ # This is the value for the `maxsize` argument of @functools.lru_cache
29+ # https://docs.python.org/3/library/functools.html#functools.lru_cache
30+ # This represents the number of recent function calls to store.
31+ ROUTING_PARAM_CACHE_SIZE = 32
2732
2833
2934def to_routing_header (params , qualified_enums = True ):
3035 """Returns a routing header string for the given request parameters.
3136
3237 Args:
33- params (Mapping[str, Any ]): A dictionary containing the request
38+ params (Mapping[str, str | bytes | Enum ]): A dictionary containing the request
3439 parameters used for routing.
3540 qualified_enums (bool): Whether to represent enum values
3641 as their type-qualified symbol names instead of as their
3742 unqualified symbol names.
3843
3944 Returns:
4045 str: The routing header string.
41-
4246 """
47+ tuples = params .items () if isinstance (params , dict ) else params
4348 if not qualified_enums :
44- if isinstance (params , dict ):
45- tuples = params .items ()
46- else :
47- tuples = params
48- params = [(x [0 ], x [1 ].name ) if isinstance (x [1 ], Enum ) else x for x in tuples ]
49- return urlencode (
50- params ,
51- # Per Google API policy (go/api-url-encoding), / is not encoded.
52- safe = "/" ,
53- )
49+ tuples = [(x [0 ], x [1 ].name ) if isinstance (x [1 ], Enum ) else x for x in tuples ]
50+ return "&" .join ([_urlencode_param (* t ) for t in tuples ])
5451
5552
5653def to_grpc_metadata (params , qualified_enums = True ):
5754 """Returns the gRPC metadata containing the routing headers for the given
5855 request parameters.
5956
6057 Args:
61- params (Mapping[str, Any ]): A dictionary containing the request
58+ params (Mapping[str, str | bytes | Enum ]): A dictionary containing the request
6259 parameters used for routing.
6360 qualified_enums (bool): Whether to represent enum values
6461 as their type-qualified symbol names instead of as their
@@ -69,3 +66,22 @@ def to_grpc_metadata(params, qualified_enums=True):
6966 and value.
7067 """
7168 return (ROUTING_METADATA_KEY , to_routing_header (params , qualified_enums ))
69+
70+
71+ # use caching to avoid repeated computation
72+ @functools .lru_cache (maxsize = ROUTING_PARAM_CACHE_SIZE )
73+ def _urlencode_param (key , value ):
74+ """Cacheable wrapper over urlencode
75+
76+ Args:
77+ key (str): The key of the parameter to encode.
78+ value (str | bytes | Enum): The value of the parameter to encode.
79+
80+ Returns:
81+ str: The encoded parameter.
82+ """
83+ return urlencode (
84+ {key : value },
85+ # Per Google API policy (go/api-url-encoding), / is not encoded.
86+ safe = "/" ,
87+ )
0 commit comments