Skip to content

Commit efcbf13

Browse files
Copilotbambriz
andcommitted
Add constants for common request options in Cosmos SDK
- Added comprehensive request option constants in _constants.py - Updated _COMMON_OPTIONS to use constants instead of hardcoded strings - Replaced hardcoded strings in GetHeaders function with constants - Updated session token and throughput functions to use constants - Added detailed documentation and best practices comments - All constants follow UPPER_SNAKE_CASE naming convention - Used Literal types for type safety Co-authored-by: bambriz <[email protected]>
1 parent 8c726ed commit efcbf13

File tree

2 files changed

+211
-95
lines changed

2 files changed

+211
-95
lines changed

sdk/cosmos/azure-cosmos/azure/cosmos/_base.py

Lines changed: 94 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,25 @@
5050
# pylint: disable=protected-access
5151

5252
_COMMON_OPTIONS = {
53-
'initial_headers': 'initialHeaders',
54-
'pre_trigger_include': 'preTriggerInclude',
55-
'post_trigger_include': 'postTriggerInclude',
56-
'access_condition': 'accessCondition',
57-
'session_token': 'sessionToken',
58-
'resource_token_expiry_seconds': 'resourceTokenExpirySeconds',
59-
'offer_enable_ru_per_minute_throughput': 'offerEnableRUPerMinuteThroughput',
60-
'disable_ru_per_minute_usage': 'disableRUPerMinuteUsage',
61-
'continuation': 'continuation',
62-
'content_type': 'contentType',
63-
'is_query_plan_request': 'isQueryPlanRequest',
64-
'supported_query_features': 'supportedQueryFeatures',
65-
'query_version': 'queryVersion',
66-
'priority': 'priorityLevel',
67-
'no_response': 'responsePayloadOnWriteDisabled',
53+
'initial_headers': Constants.Kwargs.INITIAL_HEADERS,
54+
'pre_trigger_include': Constants.Kwargs.PRE_TRIGGER_INCLUDE,
55+
'post_trigger_include': Constants.Kwargs.POST_TRIGGER_INCLUDE,
56+
'access_condition': Constants.Kwargs.ACCESS_CONDITION,
57+
'session_token': Constants.Kwargs.SESSION_TOKEN,
58+
'resource_token_expiry_seconds': Constants.Kwargs.RESOURCE_TOKEN_EXPIRY_SECONDS,
59+
'offer_enable_ru_per_minute_throughput': Constants.Kwargs.OFFER_ENABLE_RU_PER_MINUTE_THROUGHPUT,
60+
'disable_ru_per_minute_usage': Constants.Kwargs.DISABLE_RU_PER_MINUTE_USAGE,
61+
'continuation': Constants.Kwargs.CONTINUATION,
62+
'content_type': Constants.Kwargs.CONTENT_TYPE,
63+
'is_query_plan_request': Constants.Kwargs.IS_QUERY_PLAN_REQUEST,
64+
'supported_query_features': Constants.Kwargs.SUPPORTED_QUERY_FEATURES,
65+
'query_version': Constants.Kwargs.QUERY_VERSION,
66+
'priority': Constants.Kwargs.PRIORITY_LEVEL,
67+
'no_response': Constants.Kwargs.RESPONSE_PAYLOAD_ON_WRITE_DISABLED,
6868
'retry_write': Constants.Kwargs.RETRY_WRITE,
69-
'max_item_count': 'maxItemCount',
70-
'throughput_bucket': 'throughputBucket',
71-
'excluded_locations': 'excludedLocations'
69+
'max_item_count': Constants.Kwargs.MAX_ITEM_COUNT,
70+
'throughput_bucket': Constants.Kwargs.THROUGHPUT_BUCKET,
71+
'excluded_locations': Constants.Kwargs.EXCLUDED_LOCATIONS
7272
}
7373

7474
# Cosmos resource ID validation regex breakdown:
@@ -151,93 +151,93 @@ def GetHeaders( # pylint: disable=too-many-statements,too-many-branches
151151
if cosmos_client_connection.UseMultipleWriteLocations:
152152
headers[http_constants.HttpHeaders.AllowTentativeWrites] = "true"
153153

154-
pre_trigger_include = options.get("preTriggerInclude")
154+
pre_trigger_include = options.get(Constants.Kwargs.PRE_TRIGGER_INCLUDE)
155155
if pre_trigger_include:
156156
headers[http_constants.HttpHeaders.PreTriggerInclude] = (
157157
pre_trigger_include if isinstance(pre_trigger_include, str) else (",").join(pre_trigger_include)
158158
)
159159

160-
post_trigger_include = options.get("postTriggerInclude")
160+
post_trigger_include = options.get(Constants.Kwargs.POST_TRIGGER_INCLUDE)
161161
if post_trigger_include:
162162
headers[http_constants.HttpHeaders.PostTriggerInclude] = (
163163
post_trigger_include if isinstance(post_trigger_include, str) else (",").join(post_trigger_include)
164164
)
165165

166-
if options.get("maxItemCount"):
167-
headers[http_constants.HttpHeaders.PageSize] = options["maxItemCount"]
166+
if options.get(Constants.Kwargs.MAX_ITEM_COUNT):
167+
headers[http_constants.HttpHeaders.PageSize] = options[Constants.Kwargs.MAX_ITEM_COUNT]
168168

169-
access_condition = options.get("accessCondition")
169+
access_condition = options.get(Constants.Kwargs.ACCESS_CONDITION)
170170
if access_condition:
171171
if access_condition["type"] == "IfMatch":
172172
headers[http_constants.HttpHeaders.IfMatch] = access_condition["condition"]
173173
else:
174174
headers[http_constants.HttpHeaders.IfNoneMatch] = access_condition["condition"]
175175

176-
if options.get("indexingDirective"):
177-
headers[http_constants.HttpHeaders.IndexingDirective] = options["indexingDirective"]
176+
if options.get(Constants.Kwargs.INDEXING_DIRECTIVE):
177+
headers[http_constants.HttpHeaders.IndexingDirective] = options[Constants.Kwargs.INDEXING_DIRECTIVE]
178178

179179
# set request consistency level - if session consistency, the client should be setting this on its own
180-
if options.get("consistencyLevel"):
181-
headers[http_constants.HttpHeaders.ConsistencyLevel] = options["consistencyLevel"]
180+
if options.get(Constants.Kwargs.CONSISTENCY_LEVEL):
181+
headers[http_constants.HttpHeaders.ConsistencyLevel] = options[Constants.Kwargs.CONSISTENCY_LEVEL]
182182

183-
if options.get("enableScanInQuery"):
184-
headers[http_constants.HttpHeaders.EnableScanInQuery] = options["enableScanInQuery"]
183+
if options.get(Constants.Kwargs.ENABLE_SCAN_IN_QUERY):
184+
headers[http_constants.HttpHeaders.EnableScanInQuery] = options[Constants.Kwargs.ENABLE_SCAN_IN_QUERY]
185185

186-
if options.get("resourceTokenExpirySeconds"):
187-
headers[http_constants.HttpHeaders.ResourceTokenExpiry] = options["resourceTokenExpirySeconds"]
186+
if options.get(Constants.Kwargs.RESOURCE_TOKEN_EXPIRY_SECONDS):
187+
headers[http_constants.HttpHeaders.ResourceTokenExpiry] = options[Constants.Kwargs.RESOURCE_TOKEN_EXPIRY_SECONDS]
188188

189-
if options.get("offerType"):
190-
headers[http_constants.HttpHeaders.OfferType] = options["offerType"]
189+
if options.get(Constants.Kwargs.OFFER_TYPE):
190+
headers[http_constants.HttpHeaders.OfferType] = options[Constants.Kwargs.OFFER_TYPE]
191191

192-
if options.get("offerThroughput"):
193-
headers[http_constants.HttpHeaders.OfferThroughput] = options["offerThroughput"]
192+
if options.get(Constants.Kwargs.OFFER_THROUGHPUT):
193+
headers[http_constants.HttpHeaders.OfferThroughput] = options[Constants.Kwargs.OFFER_THROUGHPUT]
194194

195-
if options.get("contentType"):
196-
headers[http_constants.HttpHeaders.ContentType] = options['contentType']
195+
if options.get(Constants.Kwargs.CONTENT_TYPE):
196+
headers[http_constants.HttpHeaders.ContentType] = options[Constants.Kwargs.CONTENT_TYPE]
197197

198-
if options.get("isQueryPlanRequest"):
199-
headers[http_constants.HttpHeaders.IsQueryPlanRequest] = options['isQueryPlanRequest']
198+
if options.get(Constants.Kwargs.IS_QUERY_PLAN_REQUEST):
199+
headers[http_constants.HttpHeaders.IsQueryPlanRequest] = options[Constants.Kwargs.IS_QUERY_PLAN_REQUEST]
200200

201-
if options.get("supportedQueryFeatures"):
202-
headers[http_constants.HttpHeaders.SupportedQueryFeatures] = options['supportedQueryFeatures']
201+
if options.get(Constants.Kwargs.SUPPORTED_QUERY_FEATURES):
202+
headers[http_constants.HttpHeaders.SupportedQueryFeatures] = options[Constants.Kwargs.SUPPORTED_QUERY_FEATURES]
203203

204-
if options.get("queryVersion"):
205-
headers[http_constants.HttpHeaders.QueryVersion] = options['queryVersion']
204+
if options.get(Constants.Kwargs.QUERY_VERSION):
205+
headers[http_constants.HttpHeaders.QueryVersion] = options[Constants.Kwargs.QUERY_VERSION]
206206

207-
if "partitionKey" in options:
207+
if Constants.Kwargs.PARTITION_KEY in options:
208208
# if partitionKey value is Undefined, serialize it as [{}] to be consistent with other SDKs.
209-
if isinstance(options["partitionKey"], _Undefined):
209+
if isinstance(options[Constants.Kwargs.PARTITION_KEY], _Undefined):
210210
headers[http_constants.HttpHeaders.PartitionKey] = [{}]
211211
# If partitionKey value is Empty, serialize it as [], which is the equivalent sent for migrated collections
212-
elif isinstance(options["partitionKey"], _Empty):
212+
elif isinstance(options[Constants.Kwargs.PARTITION_KEY], _Empty):
213213
headers[http_constants.HttpHeaders.PartitionKey] = []
214214
# else serialize using json dumps method which apart from regular values will serialize None into null
215215
else:
216216
# single partitioning uses a string and needs to be turned into a list
217-
is_sequence_not_string = (isinstance(options["partitionKey"], Sequence) and
218-
not isinstance(options["partitionKey"], str))
217+
is_sequence_not_string = (isinstance(options[Constants.Kwargs.PARTITION_KEY], Sequence) and
218+
not isinstance(options[Constants.Kwargs.PARTITION_KEY], str))
219219

220-
if is_sequence_not_string and options["partitionKey"]:
221-
pk_val = json.dumps(list(options["partitionKey"]), separators=(',', ':'))
220+
if is_sequence_not_string and options[Constants.Kwargs.PARTITION_KEY]:
221+
pk_val = json.dumps(list(options[Constants.Kwargs.PARTITION_KEY]), separators=(',', ':'))
222222
else:
223-
pk_val = json.dumps([options["partitionKey"]])
223+
pk_val = json.dumps([options[Constants.Kwargs.PARTITION_KEY]])
224224
headers[http_constants.HttpHeaders.PartitionKey] = pk_val
225225

226-
if options.get("enableCrossPartitionQuery"):
227-
headers[http_constants.HttpHeaders.EnableCrossPartitionQuery] = options["enableCrossPartitionQuery"]
226+
if options.get(Constants.Kwargs.ENABLE_CROSS_PARTITION_QUERY):
227+
headers[http_constants.HttpHeaders.EnableCrossPartitionQuery] = options[Constants.Kwargs.ENABLE_CROSS_PARTITION_QUERY]
228228

229-
if options.get("populateQueryMetrics"):
230-
headers[http_constants.HttpHeaders.PopulateQueryMetrics] = options["populateQueryMetrics"]
229+
if options.get(Constants.Kwargs.POPULATE_QUERY_METRICS):
230+
headers[http_constants.HttpHeaders.PopulateQueryMetrics] = options[Constants.Kwargs.POPULATE_QUERY_METRICS]
231231

232-
if options.get("populateIndexMetrics"):
233-
headers[http_constants.HttpHeaders.PopulateIndexMetrics] = options["populateIndexMetrics"]
232+
if options.get(Constants.Kwargs.POPULATE_INDEX_METRICS):
233+
headers[http_constants.HttpHeaders.PopulateIndexMetrics] = options[Constants.Kwargs.POPULATE_INDEX_METRICS]
234234

235-
if options.get("responseContinuationTokenLimitInKb"):
235+
if options.get(Constants.Kwargs.RESPONSE_CONTINUATION_TOKEN_LIMIT_IN_KB):
236236
headers[http_constants.HttpHeaders.ResponseContinuationTokenLimitInKb] = options[
237-
"responseContinuationTokenLimitInKb"]
237+
Constants.Kwargs.RESPONSE_CONTINUATION_TOKEN_LIMIT_IN_KB]
238238

239-
if options.get("priorityLevel"):
240-
headers[http_constants.HttpHeaders.PriorityLevel] = options["priorityLevel"]
239+
if options.get(Constants.Kwargs.PRIORITY_LEVEL):
240+
headers[http_constants.HttpHeaders.PriorityLevel] = options[Constants.Kwargs.PRIORITY_LEVEL]
241241

242242
# formatdate guarantees RFC 1123 date format regardless of current locale
243243
headers[http_constants.HttpHeaders.XDate] = formatdate(timeval=None, localtime=False, usegmt=True)
@@ -268,43 +268,43 @@ def GetHeaders( # pylint: disable=too-many-statements,too-many-branches
268268
elif cosmos_client_connection and cosmos_client_connection.client_id:
269269
headers[http_constants.HttpHeaders.ClientId] = cosmos_client_connection.client_id
270270

271-
if options.get("enableScriptLogging"):
272-
headers[http_constants.HttpHeaders.EnableScriptLogging] = options["enableScriptLogging"]
271+
if options.get(Constants.Kwargs.ENABLE_SCRIPT_LOGGING):
272+
headers[http_constants.HttpHeaders.EnableScriptLogging] = options[Constants.Kwargs.ENABLE_SCRIPT_LOGGING]
273273

274-
if options.get("offerEnableRUPerMinuteThroughput"):
274+
if options.get(Constants.Kwargs.OFFER_ENABLE_RU_PER_MINUTE_THROUGHPUT):
275275
headers[http_constants.HttpHeaders.OfferIsRUPerMinuteThroughputEnabled] = options[
276-
"offerEnableRUPerMinuteThroughput"
276+
Constants.Kwargs.OFFER_ENABLE_RU_PER_MINUTE_THROUGHPUT
277277
]
278278

279-
if options.get("disableRUPerMinuteUsage"):
280-
headers[http_constants.HttpHeaders.DisableRUPerMinuteUsage] = options["disableRUPerMinuteUsage"]
279+
if options.get(Constants.Kwargs.DISABLE_RU_PER_MINUTE_USAGE):
280+
headers[http_constants.HttpHeaders.DisableRUPerMinuteUsage] = options[Constants.Kwargs.DISABLE_RU_PER_MINUTE_USAGE]
281281

282-
if options.get("continuation"):
283-
headers[http_constants.HttpHeaders.Continuation] = options["continuation"]
282+
if options.get(Constants.Kwargs.CONTINUATION):
283+
headers[http_constants.HttpHeaders.Continuation] = options[Constants.Kwargs.CONTINUATION]
284284

285-
if options.get("populatePartitionKeyRangeStatistics"):
285+
if options.get(Constants.Kwargs.POPULATE_PARTITION_KEY_RANGE_STATISTICS):
286286
headers[http_constants.HttpHeaders.PopulatePartitionKeyRangeStatistics] = options[
287-
"populatePartitionKeyRangeStatistics"
287+
Constants.Kwargs.POPULATE_PARTITION_KEY_RANGE_STATISTICS
288288
]
289289

290-
if options.get("populateQuotaInfo"):
291-
headers[http_constants.HttpHeaders.PopulateQuotaInfo] = options["populateQuotaInfo"]
290+
if options.get(Constants.Kwargs.POPULATE_QUOTA_INFO):
291+
headers[http_constants.HttpHeaders.PopulateQuotaInfo] = options[Constants.Kwargs.POPULATE_QUOTA_INFO]
292292

293-
if options.get("maxIntegratedCacheStaleness"):
294-
headers[http_constants.HttpHeaders.DedicatedGatewayCacheStaleness] = options["maxIntegratedCacheStaleness"]
293+
if options.get(Constants.Kwargs.MAX_INTEGRATED_CACHE_STALENESS):
294+
headers[http_constants.HttpHeaders.DedicatedGatewayCacheStaleness] = options[Constants.Kwargs.MAX_INTEGRATED_CACHE_STALENESS]
295295

296-
if options.get("autoUpgradePolicy"):
297-
headers[http_constants.HttpHeaders.AutoscaleSettings] = options["autoUpgradePolicy"]
296+
if options.get(Constants.Kwargs.AUTO_UPGRADE_POLICY):
297+
headers[http_constants.HttpHeaders.AutoscaleSettings] = options[Constants.Kwargs.AUTO_UPGRADE_POLICY]
298298

299-
if options.get("correlatedActivityId"):
300-
headers[http_constants.HttpHeaders.CorrelatedActivityId] = options["correlatedActivityId"]
299+
if options.get(Constants.Kwargs.CORRELATED_ACTIVITY_ID):
300+
headers[http_constants.HttpHeaders.CorrelatedActivityId] = options[Constants.Kwargs.CORRELATED_ACTIVITY_ID]
301301

302-
if options.get("throughputBucket"):
303-
headers[http_constants.HttpHeaders.ThroughputBucket] = options["throughputBucket"]
302+
if options.get(Constants.Kwargs.THROUGHPUT_BUCKET):
303+
headers[http_constants.HttpHeaders.ThroughputBucket] = options[Constants.Kwargs.THROUGHPUT_BUCKET]
304304

305305
if resource_type == "docs" and verb != "get":
306-
if "responsePayloadOnWriteDisabled" in options:
307-
responsePayloadOnWriteDisabled = options["responsePayloadOnWriteDisabled"]
306+
if Constants.Kwargs.RESPONSE_PAYLOAD_ON_WRITE_DISABLED in options:
307+
responsePayloadOnWriteDisabled = options[Constants.Kwargs.RESPONSE_PAYLOAD_ON_WRITE_DISABLED]
308308
else:
309309
responsePayloadOnWriteDisabled = cosmos_client_connection.connection_policy.ResponsePayloadOnWriteDisabled
310310

@@ -313,8 +313,8 @@ def GetHeaders( # pylint: disable=too-many-statements,too-many-branches
313313

314314
# If it is an operation at the container level, verify the rid of the container to see if the cache needs to be
315315
# refreshed.
316-
if resource_type != 'dbs' and options.get("containerRID"):
317-
headers[http_constants.HttpHeaders.IntendedCollectionRID] = options["containerRID"]
316+
if resource_type != 'dbs' and options.get(Constants.Kwargs.CONTAINER_RID):
317+
headers[http_constants.HttpHeaders.IntendedCollectionRID] = options[Constants.Kwargs.CONTAINER_RID]
318318

319319
if resource_type == "":
320320
resource_type = http_constants.ResourceType.DatabaseAccount
@@ -351,8 +351,8 @@ def set_session_token_header(
351351
# set session token if required
352352
if _is_session_token_request(cosmos_client_connection, headers, request_object):
353353
# if there is a token set via option, then use it to override default
354-
if options.get("sessionToken"):
355-
headers[http_constants.HttpHeaders.SessionToken] = options["sessionToken"]
354+
if options.get(Constants.Kwargs.SESSION_TOKEN):
355+
headers[http_constants.HttpHeaders.SessionToken] = options[Constants.Kwargs.SESSION_TOKEN]
356356
else:
357357
# check if the client's default consistency is session (and request consistency level is same),
358358
# then update from session container
@@ -361,7 +361,7 @@ def set_session_token_header(
361361
# populate session token from the client's session container
362362
session_token = (
363363
cosmos_client_connection.session.get_session_token(path,
364-
options.get('partitionKey'),
364+
options.get(Constants.Kwargs.PARTITION_KEY),
365365
cosmos_client_connection._container_properties_cache,
366366
cosmos_client_connection._routing_map_provider,
367367
partition_key_range_id))
@@ -378,8 +378,8 @@ async def set_session_token_header_async(
378378
# set session token if required
379379
if _is_session_token_request(cosmos_client_connection, headers, request_object):
380380
# if there is a token set via option, then use it to override default
381-
if options.get("sessionToken"):
382-
headers[http_constants.HttpHeaders.SessionToken] = options["sessionToken"]
381+
if options.get(Constants.Kwargs.SESSION_TOKEN):
382+
headers[http_constants.HttpHeaders.SessionToken] = options[Constants.Kwargs.SESSION_TOKEN]
383383
else:
384384
# check if the client's default consistency is session (and request consistency level is same),
385385
# then update from session container
@@ -388,7 +388,7 @@ async def set_session_token_header_async(
388388
# populate session token from the client's session container
389389
session_token = \
390390
await cosmos_client_connection.session.get_session_token_async(path,
391-
options.get('partitionKey'),
391+
options.get(Constants.Kwargs.PARTITION_KEY),
392392
cosmos_client_connection._container_properties_cache,
393393
cosmos_client_connection._routing_map_provider,
394394
partition_key_range_id)
@@ -795,19 +795,19 @@ def _stringify_auto_scale(offer: ThroughputProperties) -> str:
795795

796796
def _set_throughput_options(offer: Optional[Union[int, ThroughputProperties]], request_options: Dict[str, Any]) -> None:
797797
if isinstance(offer, int):
798-
request_options["offerThroughput"] = offer
798+
request_options[Constants.Kwargs.OFFER_THROUGHPUT] = offer
799799
elif offer is not None:
800800
try:
801801
max_throughput = offer.auto_scale_max_throughput
802802
increment_percent = offer.auto_scale_increment_percent
803803

804804
if max_throughput is not None:
805-
request_options['autoUpgradePolicy'] = _stringify_auto_scale(offer=offer)
805+
request_options[Constants.Kwargs.AUTO_UPGRADE_POLICY] = _stringify_auto_scale(offer=offer)
806806
elif increment_percent:
807807
raise ValueError("auto_scale_max_throughput must be supplied in "
808808
"conjunction with auto_scale_increment_percent")
809809
if offer.offer_throughput:
810-
request_options["offerThroughput"] = offer.offer_throughput
810+
request_options[Constants.Kwargs.OFFER_THROUGHPUT] = offer.offer_throughput
811811
except AttributeError as e:
812812
raise TypeError("offer_throughput must be int or an instance of ThroughputProperties") from e
813813

0 commit comments

Comments
 (0)