| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0c4c5da commit 0da5f78
21 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,6 +38,7 @@ | |||
| 38 | 38 | from .types.spanner import BatchWriteRequest | |
| 39 | 39 | from .types.spanner import BatchWriteResponse | |
| 40 | 40 | from .types.spanner import BeginTransactionRequest | |
| 41 | + from .types.spanner import ClientContext | ||
| 41 | 42 | from .types.spanner import CommitRequest | |
| 42 | 43 | from .types.spanner import CreateSessionRequest | |
| 43 | 44 | from .types.spanner import DeleteSessionRequest | |
@@ -110,6 +111,7 @@ | |||
| 110 | 111 | "BatchWriteRequest", | |
| 111 | 112 | "BatchWriteResponse", | |
| 112 | 113 | "BeginTransactionRequest", | |
| 114 | + "ClientContext", | ||
| 113 | 115 | "CommitRequest", | |
| 114 | 116 | "CommitResponse", | |
| 115 | 117 | "CreateSessionRequest", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,6 +34,8 @@ | |||
| 34 | 34 | from google.cloud._helpers import _date_from_iso8601_date | |
| 35 | 35 | from google.cloud.spanner_v1.types import ExecuteSqlRequest | |
| 36 | 36 | from google.cloud.spanner_v1.types import TransactionOptions | |
| 37 | + from google.cloud.spanner_v1.types import ClientContext | ||
| 38 | + from google.cloud.spanner_v1.types import RequestOptions | ||
| 37 | 39 | from google.cloud.spanner_v1.data_types import JsonObject, Interval | |
| 38 | 40 | from google.cloud.spanner_v1.request_id_header import ( | |
| 39 | 41 | with_request_id, | |
@@ -172,15 +174,15 @@ def _merge_query_options(base, merge): | |||
| 172 | 174 | If the resultant object only has empty fields, returns None. | |
| 173 | 175 | """ | |
| 174 | 176 | combined = base or ExecuteSqlRequest.QueryOptions() | |
| 175 | - if type(combined) is dict: | ||
| 177 | + if isinstance(combined, dict): | ||
| 176 | 178 | combined = ExecuteSqlRequest.QueryOptions( | |
| 177 | 179 | optimizer_version=combined.get("optimizer_version", ""), | |
| 178 | 180 | optimizer_statistics_package=combined.get( | |
| 179 | 181 | "optimizer_statistics_package", "" | |
| 180 | 182 | ), | |
| 181 | 183 | ) | |
| 182 | 184 | merge = merge or ExecuteSqlRequest.QueryOptions() | |
| 183 | - if type(merge) is dict: | ||
| 185 | + if isinstance(merge, dict): | ||
| 184 | 186 | merge = ExecuteSqlRequest.QueryOptions( | |
| 185 | 187 | optimizer_version=merge.get("optimizer_version", ""), | |
| 186 | 188 | optimizer_statistics_package=merge.get("optimizer_statistics_package", ""), | |
@@ -191,6 +193,95 @@ def _merge_query_options(base, merge): | |||
| 191 | 193 | return combined | |
| 192 | 194 | ||
| 193 | 195 | ||
| 196 | + def _merge_client_context(base, merge): | ||
| 197 | + """Merge higher precedence ClientContext with current ClientContext. | ||
| 198 | + | ||
| 199 | + :type base: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 200 | + or :class:`dict` or None | ||
| 201 | + :param base: The current ClientContext that is intended for use. | ||
| 202 | + | ||
| 203 | + :type merge: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 204 | + or :class:`dict` or None | ||
| 205 | + :param merge: | ||
| 206 | + The ClientContext that has a higher priority than base. These options | ||
| 207 | + should overwrite the fields in base. | ||
| 208 | + | ||
| 209 | + :rtype: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 210 | + or None | ||
| 211 | + :returns: | ||
| 212 | + ClientContext object formed by merging the two given ClientContexts. | ||
| 213 | + """ | ||
| 214 | + if base is None and merge is None: | ||
| 215 | + return None | ||
| 216 | + | ||
| 217 | + # Avoid in-place modification of base | ||
| 218 | + combined_pb = ClientContext()._pb | ||
| 219 | + if base: | ||
| 220 | + base_pb = ClientContext(base)._pb if isinstance(base, dict) else base._pb | ||
| 221 | + combined_pb.MergeFrom(base_pb) | ||
| 222 | + if merge: | ||
| 223 | + merge_pb = ClientContext(merge)._pb if isinstance(merge, dict) else merge._pb | ||
| 224 | + combined_pb.MergeFrom(merge_pb) | ||
| 225 | + | ||
| 226 | + combined = ClientContext(combined_pb) | ||
| 227 | + | ||
| 228 | + if not combined.secure_context: | ||
| 229 | + return None | ||
| 230 | + return combined | ||
| 231 | + | ||
| 232 | + | ||
| 233 | + def _validate_client_context(client_context): | ||
| 234 | + """Validate and convert client_context. | ||
| 235 | + | ||
| 236 | + :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 237 | + or :class:`dict` | ||
| 238 | + :param client_context: (Optional) Client context to use. | ||
| 239 | + | ||
| 240 | + :rtype: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 241 | + :returns: Validated ClientContext object or None. | ||
| 242 | + :raises TypeError: if client_context is not a ClientContext or a dict. | ||
| 243 | + """ | ||
| 244 | + if client_context is not None: | ||
| 245 | + if isinstance(client_context, dict): | ||
| 246 | + client_context = ClientContext(client_context) | ||
| 247 | + elif not isinstance(client_context, ClientContext): | ||
| 248 | + raise TypeError("client_context must be a ClientContext or a dict") | ||
| 249 | + return client_context | ||
| 250 | + | ||
| 251 | + | ||
| 252 | + def _merge_request_options(request_options, client_context): | ||
| 253 | + """Merge RequestOptions and ClientContext. | ||
| 254 | + | ||
| 255 | + :type request_options: :class:`~google.cloud.spanner_v1.types.RequestOptions` | ||
| 256 | + or :class:`dict` or None | ||
| 257 | + :param request_options: The current RequestOptions that is intended for use. | ||
| 258 | + | ||
| 259 | + :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 260 | + or :class:`dict` or None | ||
| 261 | + :param client_context: | ||
| 262 | + The ClientContext to merge into request_options. | ||
| 263 | + | ||
| 264 | + :rtype: :class:`~google.cloud.spanner_v1.types.RequestOptions` | ||
| 265 | + or None | ||
| 266 | + :returns: | ||
| 267 | + RequestOptions object formed by merging the given ClientContext. | ||
| 268 | + """ | ||
| 269 | + if request_options is None and client_context is None: | ||
| 270 | + return None | ||
| 271 | + | ||
| 272 | + if request_options is None: | ||
| 273 | + request_options = RequestOptions() | ||
| 274 | + elif isinstance(request_options, dict): | ||
| 275 | + request_options = RequestOptions(request_options) | ||
| 276 | + | ||
| 277 | + if client_context: | ||
| 278 | + request_options.client_context = _merge_client_context( | ||
| 279 | + client_context, request_options.client_context | ||
| 280 | + ) | ||
| 281 | + | ||
| 282 | + return request_options | ||
| 283 | + | ||
| 284 | + | ||
| 194 | 285 | def _assert_numeric_precision_and_scale(value): | |
| 195 | 286 | """ | |
| 196 | 287 | Asserts that input numeric field is within Spanner supported range. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,6 +28,9 @@ | |||
| 28 | 28 | _metadata_with_prefix, | |
| 29 | 29 | _metadata_with_leader_aware_routing, | |
| 30 | 30 | _merge_Transaction_Options, | |
| 31 | + _merge_client_context, | ||
| 32 | + _merge_request_options, | ||
| 33 | + _validate_client_context, | ||
| 31 | 34 | AtomicCounter, | |
| 32 | 35 | ) | |
| 33 | 36 | from google.cloud.spanner_v1._opentelemetry_tracing import trace_call | |
@@ -37,6 +40,7 @@ | |||
| 37 | 40 | from google.cloud.spanner_v1._helpers import _check_rst_stream_error | |
| 38 | 41 | from google.api_core.exceptions import InternalServerError | |
| 39 | 42 | from google.cloud.spanner_v1.metrics.metrics_capture import MetricsCapture | |
| 43 | + from google.cloud.spanner_v1.types import ClientContext | ||
| 40 | 44 | import time | |
| 41 | 45 | ||
| 42 | 46 | DEFAULT_RETRY_TIMEOUT_SECS = 30 | |
@@ -47,9 +51,14 @@ class _BatchBase(_SessionWrapper): | |||
| 47 | 51 | ||
| 48 | 52 | :type session: :class:`~google.cloud.spanner_v1.session.Session` | |
| 49 | 53 | :param session: the session used to perform the commit | |
| 54 | + | ||
| 55 | + :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 56 | + or :class:`dict` | ||
| 57 | + :param client_context: (Optional) Client context to use for all requests made | ||
| 58 | + by this batch. | ||
| 50 | 59 | """ | |
| 51 | 60 | ||
| 52 | - def __init__(self, session): | ||
| 61 | + def __init__(self, session, client_context=None): | ||
| 53 | 62 | super(_BatchBase, self).__init__(session) | |
| 54 | 63 | ||
| 55 | 64 | self._mutations: List[Mutation] = [] | |
@@ -58,6 +67,7 @@ def __init__(self, session): | |||
| 58 | 67 | self.committed = None | |
| 59 | 68 | """Timestamp at which the batch was successfully committed.""" | |
| 60 | 69 | self.commit_stats: Optional[CommitResponse.CommitStats] = None | |
| 70 | + self._client_context = _validate_client_context(client_context) | ||
| 61 | 71 | ||
| 62 | 72 | def insert(self, table, columns, values): | |
| 63 | 73 | """Insert one or more new table rows. | |
@@ -227,10 +237,14 @@ def commit( | |||
| 227 | 237 | txn_options, | |
| 228 | 238 | ) | |
| 229 | 239 | ||
| 240 | + client_context = _merge_client_context( | ||
| 241 | + database._instance._client._client_context, self._client_context | ||
| 242 | + ) | ||
| 243 | + request_options = _merge_request_options(request_options, client_context) | ||
| 244 | + | ||
| 230 | 245 | if request_options is None: | |
| 231 | 246 | request_options = RequestOptions() | |
| 232 | - elif type(request_options) is dict: | ||
| 233 | - request_options = RequestOptions(request_options) | ||
| 247 | + | ||
| 234 | 248 | request_options.transaction_tag = self.transaction_tag | |
| 235 | 249 | ||
| 236 | 250 | # Request tags are not supported for commit requests. | |
@@ -317,13 +331,25 @@ class MutationGroups(_SessionWrapper): | |||
| 317 | 331 | ||
| 318 | 332 | :type session: :class:`~google.cloud.spanner_v1.session.Session` | |
| 319 | 333 | :param session: the session used to perform the commit | |
| 334 | + | ||
| 335 | + :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` | ||
| 336 | + or :class:`dict` | ||
| 337 | + :param client_context: (Optional) Client context to use for all requests made | ||
| 338 | + by this mutation group. | ||
| 320 | 339 | """ | |
| 321 | 340 | ||
| 322 | - def __init__(self, session): | ||
| 341 | + def __init__(self, session, client_context=None): | ||
| 323 | 342 | super(MutationGroups, self).__init__(session) | |
| 324 | 343 | self._mutation_groups: List[MutationGroup] = [] | |
| 325 | 344 | self.committed: bool = False | |
| 326 | 345 | ||
| 346 | + if client_context is not None: | ||
| 347 | + if isinstance(client_context, dict): | ||
| 348 | + client_context = ClientContext(client_context) | ||
| 349 | + elif not isinstance(client_context, ClientContext): | ||
| 350 | + raise TypeError("client_context must be a ClientContext or a dict") | ||
| 351 | + self._client_context = client_context | ||
| 352 | + | ||
| 327 | 353 | def group(self): | |
| 328 | 354 | """Returns a new `MutationGroup` to which mutations can be added.""" | |
| 329 | 355 | mutation_group = BatchWriteRequest.MutationGroup() | |
@@ -365,10 +391,13 @@ def batch_write(self, request_options=None, exclude_txn_from_change_streams=Fals | |||
| 365 | 391 | _metadata_with_leader_aware_routing(database._route_to_leader_enabled) | |
| 366 | 392 | ) | |
| 367 | 393 | ||
| 394 | + client_context = _merge_client_context( | ||
| 395 | + database._instance._client._client_context, self._client_context | ||
| 396 | + ) | ||
| 397 | + request_options = _merge_request_options(request_options, client_context) | ||
| 398 | + | ||
| 368 | 399 | if request_options is None: | |
| 369 | 400 | request_options = RequestOptions() | |
| 370 | - elif type(request_options) is dict: | ||
| 371 | - request_options = RequestOptions(request_options) | ||
| 372 | 401 | ||
| 373 | 402 | with trace_call( | |
| 374 | 403 | name="CloudSpanner.batch_write", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,6 +55,7 @@ | |||
| 55 | 55 | _merge_query_options, | |
| 56 | 56 | ) | |
| 57 | 57 | from google.cloud.spanner_v1._helpers import _metadata_with_prefix | |
| 58 | + from google.cloud.spanner_v1._helpers import _validate_client_context | ||
| 58 | 59 | from google.cloud.spanner_v1.instance import Instance | |
| 59 | 60 | from google.cloud.spanner_v1.metrics.constants import ( | |
| 60 | 61 | METRIC_EXPORT_INTERVAL_MS, | |
@@ -228,6 +229,10 @@ class Client(ClientWithProject): | |||
| 228 | 229 | :param disable_builtin_metrics: (Optional) Default False. Set to True to disable | |
| 229 | 230 | the Spanner built-in metrics collection and exporting. | |
| 230 | 231 | ||
| 232 | + :type client_context: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` | ||
| 233 | + or :class:`dict` | ||
| 234 | + :param client_context: (Optional) Client context to use for all requests made by this client. | ||
| 235 | + | ||
| 231 | 236 | :raises: :class:`ValueError <exceptions.ValueError>` if both ``read_only`` | |
| 232 | 237 | and ``admin`` are :data:`True` | |
| 233 | 238 | ||
@@ -278,6 +283,7 @@ def __init__( | |||
| 278 | 283 | default_transaction_options: Optional[DefaultTransactionOptions] = None, | |
| 279 | 284 | experimental_host=None, | |
| 280 | 285 | disable_builtin_metrics=False, | |
| 286 | + client_context=None, | ||
| 281 | 287 | use_plain_text=False, | |
| 282 | 288 | ca_certificate=None, | |
| 283 | 289 | client_certificate=None, | |
@@ -324,6 +330,7 @@ def __init__( | |||
| 324 | 330 | ||
| 325 | 331 | # Environment flag config has higher precedence than application config. | |
| 326 | 332 | self._query_options = _merge_query_options(query_options, env_query_options) | |
| 333 | + self._client_context = _validate_client_context(client_context) | ||
| 327 | 334 | ||
| 328 | 335 | if self._emulator_host is not None and ( | |
| 329 | 336 | "http://" in self._emulator_host or "https://" in self._emulator_host | |
| Back | FazBrowse Home | New Git URL |
0 commit comments