google-cloud-spanner 3.55.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. google/cloud/spanner.py +47 -0
  2. google/cloud/spanner_admin_database_v1/__init__.py +146 -0
  3. google/cloud/spanner_admin_database_v1/gapic_metadata.json +418 -0
  4. google/cloud/spanner_admin_database_v1/gapic_version.py +16 -0
  5. google/cloud/spanner_admin_database_v1/py.typed +2 -0
  6. google/cloud/spanner_admin_database_v1/services/__init__.py +15 -0
  7. google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +22 -0
  8. google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +4097 -0
  9. google/cloud/spanner_admin_database_v1/services/database_admin/client.py +4602 -0
  10. google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +989 -0
  11. google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +38 -0
  12. google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +820 -0
  13. google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +1303 -0
  14. google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +1688 -0
  15. google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +6512 -0
  16. google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest_base.py +1650 -0
  17. google/cloud/spanner_admin_database_v1/types/__init__.py +144 -0
  18. google/cloud/spanner_admin_database_v1/types/backup.py +1106 -0
  19. google/cloud/spanner_admin_database_v1/types/backup_schedule.py +369 -0
  20. google/cloud/spanner_admin_database_v1/types/common.py +180 -0
  21. google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +1303 -0
  22. google/cloud/spanner_admin_instance_v1/__init__.py +110 -0
  23. google/cloud/spanner_admin_instance_v1/gapic_metadata.json +343 -0
  24. google/cloud/spanner_admin_instance_v1/gapic_version.py +16 -0
  25. google/cloud/spanner_admin_instance_v1/py.typed +2 -0
  26. google/cloud/spanner_admin_instance_v1/services/__init__.py +15 -0
  27. google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +22 -0
  28. google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +3466 -0
  29. google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +3881 -0
  30. google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +856 -0
  31. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +38 -0
  32. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +545 -0
  33. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +1347 -0
  34. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +1539 -0
  35. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +4834 -0
  36. google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest_base.py +1198 -0
  37. google/cloud/spanner_admin_instance_v1/types/__init__.py +104 -0
  38. google/cloud/spanner_admin_instance_v1/types/common.py +99 -0
  39. google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +2375 -0
  40. google/cloud/spanner_dbapi/__init__.py +93 -0
  41. google/cloud/spanner_dbapi/_helpers.py +113 -0
  42. google/cloud/spanner_dbapi/batch_dml_executor.py +135 -0
  43. google/cloud/spanner_dbapi/checksum.py +80 -0
  44. google/cloud/spanner_dbapi/client_side_statement_executor.py +140 -0
  45. google/cloud/spanner_dbapi/client_side_statement_parser.py +106 -0
  46. google/cloud/spanner_dbapi/connection.py +818 -0
  47. google/cloud/spanner_dbapi/cursor.py +609 -0
  48. google/cloud/spanner_dbapi/exceptions.py +172 -0
  49. google/cloud/spanner_dbapi/parse_utils.py +392 -0
  50. google/cloud/spanner_dbapi/parsed_statement.py +63 -0
  51. google/cloud/spanner_dbapi/parser.py +258 -0
  52. google/cloud/spanner_dbapi/partition_helper.py +41 -0
  53. google/cloud/spanner_dbapi/transaction_helper.py +294 -0
  54. google/cloud/spanner_dbapi/types.py +106 -0
  55. google/cloud/spanner_dbapi/utils.py +147 -0
  56. google/cloud/spanner_dbapi/version.py +20 -0
  57. google/cloud/spanner_v1/__init__.py +154 -0
  58. google/cloud/spanner_v1/_helpers.py +751 -0
  59. google/cloud/spanner_v1/_opentelemetry_tracing.py +165 -0
  60. google/cloud/spanner_v1/backup.py +397 -0
  61. google/cloud/spanner_v1/batch.py +433 -0
  62. google/cloud/spanner_v1/client.py +538 -0
  63. google/cloud/spanner_v1/data_types.py +350 -0
  64. google/cloud/spanner_v1/database.py +1968 -0
  65. google/cloud/spanner_v1/database_sessions_manager.py +249 -0
  66. google/cloud/spanner_v1/gapic_metadata.json +268 -0
  67. google/cloud/spanner_v1/gapic_version.py +16 -0
  68. google/cloud/spanner_v1/instance.py +735 -0
  69. google/cloud/spanner_v1/keyset.py +193 -0
  70. google/cloud/spanner_v1/merged_result_set.py +146 -0
  71. google/cloud/spanner_v1/metrics/constants.py +71 -0
  72. google/cloud/spanner_v1/metrics/metrics_capture.py +75 -0
  73. google/cloud/spanner_v1/metrics/metrics_exporter.py +384 -0
  74. google/cloud/spanner_v1/metrics/metrics_interceptor.py +156 -0
  75. google/cloud/spanner_v1/metrics/metrics_tracer.py +588 -0
  76. google/cloud/spanner_v1/metrics/metrics_tracer_factory.py +328 -0
  77. google/cloud/spanner_v1/metrics/spanner_metrics_tracer_factory.py +172 -0
  78. google/cloud/spanner_v1/param_types.py +110 -0
  79. google/cloud/spanner_v1/pool.py +813 -0
  80. google/cloud/spanner_v1/py.typed +2 -0
  81. google/cloud/spanner_v1/request_id_header.py +64 -0
  82. google/cloud/spanner_v1/services/__init__.py +15 -0
  83. google/cloud/spanner_v1/services/spanner/__init__.py +22 -0
  84. google/cloud/spanner_v1/services/spanner/async_client.py +2205 -0
  85. google/cloud/spanner_v1/services/spanner/client.py +2624 -0
  86. google/cloud/spanner_v1/services/spanner/pagers.py +196 -0
  87. google/cloud/spanner_v1/services/spanner/transports/__init__.py +38 -0
  88. google/cloud/spanner_v1/services/spanner/transports/base.py +520 -0
  89. google/cloud/spanner_v1/services/spanner/transports/grpc.py +911 -0
  90. google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +1144 -0
  91. google/cloud/spanner_v1/services/spanner/transports/rest.py +3468 -0
  92. google/cloud/spanner_v1/services/spanner/transports/rest_base.py +981 -0
  93. google/cloud/spanner_v1/session.py +631 -0
  94. google/cloud/spanner_v1/session_options.py +133 -0
  95. google/cloud/spanner_v1/snapshot.py +1057 -0
  96. google/cloud/spanner_v1/streamed.py +402 -0
  97. google/cloud/spanner_v1/table.py +181 -0
  98. google/cloud/spanner_v1/testing/__init__.py +0 -0
  99. google/cloud/spanner_v1/testing/database_test.py +121 -0
  100. google/cloud/spanner_v1/testing/interceptors.py +118 -0
  101. google/cloud/spanner_v1/testing/mock_database_admin.py +38 -0
  102. google/cloud/spanner_v1/testing/mock_spanner.py +261 -0
  103. google/cloud/spanner_v1/testing/spanner_database_admin_pb2_grpc.py +1267 -0
  104. google/cloud/spanner_v1/testing/spanner_pb2_grpc.py +882 -0
  105. google/cloud/spanner_v1/transaction.py +747 -0
  106. google/cloud/spanner_v1/types/__init__.py +118 -0
  107. google/cloud/spanner_v1/types/commit_response.py +94 -0
  108. google/cloud/spanner_v1/types/keys.py +248 -0
  109. google/cloud/spanner_v1/types/mutation.py +201 -0
  110. google/cloud/spanner_v1/types/query_plan.py +220 -0
  111. google/cloud/spanner_v1/types/result_set.py +379 -0
  112. google/cloud/spanner_v1/types/spanner.py +1815 -0
  113. google/cloud/spanner_v1/types/transaction.py +818 -0
  114. google/cloud/spanner_v1/types/type.py +288 -0
  115. google_cloud_spanner-3.55.0.dist-info/LICENSE +202 -0
  116. google_cloud_spanner-3.55.0.dist-info/METADATA +318 -0
  117. google_cloud_spanner-3.55.0.dist-info/RECORD +119 -0
  118. google_cloud_spanner-3.55.0.dist-info/WHEEL +5 -0
  119. google_cloud_spanner-3.55.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,350 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Custom data types for spanner."""
16
+
17
+ import json
18
+ import types
19
+ import re
20
+ from dataclasses import dataclass
21
+ from google.protobuf.message import Message
22
+ from google.protobuf.internal.enum_type_wrapper import EnumTypeWrapper
23
+
24
+
25
+ class JsonObject(dict):
26
+ """
27
+ Provides functionality of JSON data type in Cloud Spanner
28
+ API, mimicking simple `dict()` behaviour and making
29
+ all the necessary conversions under the hood.
30
+ """
31
+
32
+ def __init__(self, *args, **kwargs):
33
+ self._is_null = (args, kwargs) == ((), {}) or args == (None,)
34
+ self._is_array = len(args) and isinstance(args[0], (list, tuple))
35
+ self._is_scalar_value = len(args) == 1 and not isinstance(args[0], (list, dict))
36
+
37
+ # if the JSON object is represented with an array,
38
+ # the value is contained separately
39
+ if self._is_array:
40
+ self._array_value = args[0]
41
+ return
42
+
43
+ # If it's a scalar value, set _simple_value and return early
44
+ if self._is_scalar_value:
45
+ self._simple_value = args[0]
46
+ return
47
+
48
+ if len(args) and isinstance(args[0], JsonObject):
49
+ self._is_array = args[0]._is_array
50
+ self._is_scalar_value = args[0]._is_scalar_value
51
+ if self._is_array:
52
+ self._array_value = args[0]._array_value
53
+ elif self._is_scalar_value:
54
+ self._simple_value = args[0]._simple_value
55
+
56
+ if not self._is_null:
57
+ super(JsonObject, self).__init__(*args, **kwargs)
58
+
59
+ def __repr__(self):
60
+ if self._is_array:
61
+ return str(self._array_value)
62
+
63
+ if self._is_scalar_value:
64
+ return str(self._simple_value)
65
+
66
+ return super(JsonObject, self).__repr__()
67
+
68
+ @classmethod
69
+ def from_str(cls, str_repr):
70
+ """Initiate an object from its `str` representation.
71
+
72
+ Args:
73
+ str_repr (str): JSON text representation.
74
+
75
+ Returns:
76
+ JsonObject: JSON object.
77
+ """
78
+ if str_repr == "null":
79
+ return cls()
80
+
81
+ return cls(json.loads(str_repr))
82
+
83
+ def serialize(self):
84
+ """Return the object text representation.
85
+
86
+ Returns:
87
+ str: JSON object text representation.
88
+ """
89
+ if self._is_null:
90
+ return None
91
+
92
+ if self._is_scalar_value:
93
+ return json.dumps(self._simple_value)
94
+
95
+ if self._is_array:
96
+ return json.dumps(self._array_value, sort_keys=True, separators=(",", ":"))
97
+
98
+ return json.dumps(self, sort_keys=True, separators=(",", ":"))
99
+
100
+
101
+ @dataclass
102
+ class Interval:
103
+ """Represents a Spanner INTERVAL type.
104
+
105
+ An interval is a combination of months, days and nanoseconds.
106
+ Internally, Spanner supports Interval value with the following range of individual fields:
107
+ months: [-120000, 120000]
108
+ days: [-3660000, 3660000]
109
+ nanoseconds: [-316224000000000000000, 316224000000000000000]
110
+ """
111
+
112
+ months: int = 0
113
+ days: int = 0
114
+ nanos: int = 0
115
+
116
+ def __str__(self) -> str:
117
+ """Returns the ISO8601 duration format string representation."""
118
+ result = ["P"]
119
+
120
+ # Handle years and months
121
+ if self.months:
122
+ is_negative = self.months < 0
123
+ abs_months = abs(self.months)
124
+ years, months = divmod(abs_months, 12)
125
+ if years:
126
+ result.append(f"{'-' if is_negative else ''}{years}Y")
127
+ if months:
128
+ result.append(f"{'-' if is_negative else ''}{months}M")
129
+
130
+ # Handle days
131
+ if self.days:
132
+ result.append(f"{self.days}D")
133
+
134
+ # Handle time components
135
+ if self.nanos:
136
+ result.append("T")
137
+ nanos = abs(self.nanos)
138
+ is_negative = self.nanos < 0
139
+
140
+ # Convert to hours, minutes, seconds
141
+ nanos_per_hour = 3600000000000
142
+ hours, nanos = divmod(nanos, nanos_per_hour)
143
+ if hours:
144
+ if is_negative:
145
+ result.append("-")
146
+ result.append(f"{hours}H")
147
+
148
+ nanos_per_minute = 60000000000
149
+ minutes, nanos = divmod(nanos, nanos_per_minute)
150
+ if minutes:
151
+ if is_negative:
152
+ result.append("-")
153
+ result.append(f"{minutes}M")
154
+
155
+ nanos_per_second = 1000000000
156
+ seconds, nanos_fraction = divmod(nanos, nanos_per_second)
157
+
158
+ if seconds or nanos_fraction:
159
+ if is_negative:
160
+ result.append("-")
161
+ if seconds:
162
+ result.append(str(seconds))
163
+ elif nanos_fraction:
164
+ result.append("0")
165
+
166
+ if nanos_fraction:
167
+ nano_str = f"{nanos_fraction:09d}"
168
+ trimmed = nano_str.rstrip("0")
169
+ if len(trimmed) <= 3:
170
+ while len(trimmed) < 3:
171
+ trimmed += "0"
172
+ elif len(trimmed) <= 6:
173
+ while len(trimmed) < 6:
174
+ trimmed += "0"
175
+ else:
176
+ while len(trimmed) < 9:
177
+ trimmed += "0"
178
+ result.append(f".{trimmed}")
179
+ result.append("S")
180
+
181
+ if len(result) == 1:
182
+ result.append("0Y") # Special case for zero interval
183
+
184
+ return "".join(result)
185
+
186
+ @classmethod
187
+ def from_str(cls, s: str) -> "Interval":
188
+ """Parse an ISO8601 duration format string into an Interval."""
189
+ pattern = r"^P(-?\d+Y)?(-?\d+M)?(-?\d+D)?(T(-?\d+H)?(-?\d+M)?(-?((\d+([.,]\d{1,9})?)|([.,]\d{1,9}))S)?)?$"
190
+ match = re.match(pattern, s)
191
+ if not match or len(s) == 1:
192
+ raise ValueError(f"Invalid interval format: {s}")
193
+
194
+ parts = match.groups()
195
+ if not any(parts[:3]) and not parts[3]:
196
+ raise ValueError(
197
+ f"Invalid interval format: at least one component (Y/M/D/H/M/S) is required: {s}"
198
+ )
199
+
200
+ if parts[3] == "T" and not any(parts[4:7]):
201
+ raise ValueError(
202
+ f"Invalid interval format: time designator 'T' present but no time components specified: {s}"
203
+ )
204
+
205
+ def parse_num(s: str, suffix: str) -> int:
206
+ if not s:
207
+ return 0
208
+ return int(s.rstrip(suffix))
209
+
210
+ years = parse_num(parts[0], "Y")
211
+ months = parse_num(parts[1], "M")
212
+ total_months = years * 12 + months
213
+
214
+ days = parse_num(parts[2], "D")
215
+
216
+ nanos = 0
217
+ if parts[3]: # Has time component
218
+ # Convert hours to nanoseconds
219
+ hours = parse_num(parts[4], "H")
220
+ nanos += hours * 3600000000000
221
+
222
+ # Convert minutes to nanoseconds
223
+ minutes = parse_num(parts[5], "M")
224
+ nanos += minutes * 60000000000
225
+
226
+ # Handle seconds and fractional seconds
227
+ if parts[6]:
228
+ seconds = parts[6].rstrip("S")
229
+ if "," in seconds:
230
+ seconds = seconds.replace(",", ".")
231
+
232
+ if "." in seconds:
233
+ sec_parts = seconds.split(".")
234
+ whole_seconds = sec_parts[0] if sec_parts[0] else "0"
235
+ nanos += int(whole_seconds) * 1000000000
236
+ frac = sec_parts[1][:9].ljust(9, "0")
237
+ frac_nanos = int(frac)
238
+ if seconds.startswith("-"):
239
+ frac_nanos = -frac_nanos
240
+ nanos += frac_nanos
241
+ else:
242
+ nanos += int(seconds) * 1000000000
243
+
244
+ return cls(months=total_months, days=days, nanos=nanos)
245
+
246
+
247
+ def _proto_message(bytes_val, proto_message_object):
248
+ """Helper for :func:`get_proto_message`.
249
+ parses serialized protocol buffer bytes data into proto message.
250
+
251
+ Args:
252
+ bytes_val (bytes): bytes object.
253
+ proto_message_object (Message): Message object for parsing
254
+
255
+ Returns:
256
+ Message: parses serialized protocol buffer data into this message.
257
+
258
+ Raises:
259
+ ValueError: if the input proto_message_object is not of type Message
260
+ """
261
+ if isinstance(bytes_val, types.NoneType):
262
+ return None
263
+
264
+ if not isinstance(bytes_val, bytes):
265
+ raise ValueError("Expected input bytes_val to be a string")
266
+
267
+ proto_message = proto_message_object.__deepcopy__()
268
+ proto_message.ParseFromString(bytes_val)
269
+ return proto_message
270
+
271
+
272
+ def _proto_enum(int_val, proto_enum_object):
273
+ """Helper for :func:`get_proto_enum`.
274
+ parses int value into string containing the name of an enum value.
275
+
276
+ Args:
277
+ int_val (int): integer value.
278
+ proto_enum_object (EnumTypeWrapper): Enum object.
279
+
280
+ Returns:
281
+ str: string containing the name of an enum value.
282
+
283
+ Raises:
284
+ ValueError: if the input proto_enum_object is not of type EnumTypeWrapper
285
+ """
286
+ if isinstance(int_val, types.NoneType):
287
+ return None
288
+
289
+ if not isinstance(int_val, int):
290
+ raise ValueError("Expected input int_val to be a integer")
291
+
292
+ return proto_enum_object.Name(int_val)
293
+
294
+
295
+ def get_proto_message(bytes_string, proto_message_object):
296
+ """parses serialized protocol buffer bytes' data or its list into proto message or list of proto message.
297
+
298
+ Args:
299
+ bytes_string (bytes or list[bytes]): bytes object.
300
+ proto_message_object (Message): Message object for parsing
301
+
302
+ Returns:
303
+ Message or list[Message]: parses serialized protocol buffer data into this message.
304
+
305
+ Raises:
306
+ ValueError: if the input proto_message_object is not of type Message
307
+ """
308
+ if isinstance(bytes_string, types.NoneType):
309
+ return None
310
+
311
+ if not isinstance(proto_message_object, Message):
312
+ raise ValueError("Input proto_message_object should be of type Message")
313
+
314
+ if not isinstance(bytes_string, (bytes, list)):
315
+ raise ValueError(
316
+ "Expected input bytes_string to be a string or list of strings"
317
+ )
318
+
319
+ if isinstance(bytes_string, list):
320
+ return [_proto_message(item, proto_message_object) for item in bytes_string]
321
+
322
+ return _proto_message(bytes_string, proto_message_object)
323
+
324
+
325
+ def get_proto_enum(int_value, proto_enum_object):
326
+ """parses int or list of int values into enum or list of enum values.
327
+
328
+ Args:
329
+ int_value (int or list[int]): list of integer value.
330
+ proto_enum_object (EnumTypeWrapper): Enum object.
331
+
332
+ Returns:
333
+ str or list[str]: list of strings containing the name of enum value.
334
+
335
+ Raises:
336
+ ValueError: if the input int_list is not of type list
337
+ """
338
+ if isinstance(int_value, types.NoneType):
339
+ return None
340
+
341
+ if not isinstance(proto_enum_object, EnumTypeWrapper):
342
+ raise ValueError("Input proto_enum_object should be of type EnumTypeWrapper")
343
+
344
+ if not isinstance(int_value, (int, list)):
345
+ raise ValueError("Expected input int_value to be a integer or list of integers")
346
+
347
+ if isinstance(int_value, list):
348
+ return [_proto_enum(item, proto_enum_object) for item in int_value]
349
+
350
+ return _proto_enum(int_value, proto_enum_object)