google-cloud-bigquery 3.31.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 (58) hide show
  1. google/cloud/bigquery/__init__.py +249 -0
  2. google/cloud/bigquery/_helpers.py +1102 -0
  3. google/cloud/bigquery/_http.py +47 -0
  4. google/cloud/bigquery/_job_helpers.py +600 -0
  5. google/cloud/bigquery/_pandas_helpers.py +1181 -0
  6. google/cloud/bigquery/_pyarrow_helpers.py +147 -0
  7. google/cloud/bigquery/_tqdm_helpers.py +137 -0
  8. google/cloud/bigquery/_versions_helpers.py +264 -0
  9. google/cloud/bigquery/client.py +4406 -0
  10. google/cloud/bigquery/dataset.py +1076 -0
  11. google/cloud/bigquery/dbapi/__init__.py +87 -0
  12. google/cloud/bigquery/dbapi/_helpers.py +522 -0
  13. google/cloud/bigquery/dbapi/connection.py +128 -0
  14. google/cloud/bigquery/dbapi/cursor.py +586 -0
  15. google/cloud/bigquery/dbapi/exceptions.py +58 -0
  16. google/cloud/bigquery/dbapi/types.py +96 -0
  17. google/cloud/bigquery/encryption_configuration.py +84 -0
  18. google/cloud/bigquery/enums.py +389 -0
  19. google/cloud/bigquery/exceptions.py +35 -0
  20. google/cloud/bigquery/external_config.py +1188 -0
  21. google/cloud/bigquery/format_options.py +147 -0
  22. google/cloud/bigquery/iam.py +38 -0
  23. google/cloud/bigquery/job/__init__.py +87 -0
  24. google/cloud/bigquery/job/base.py +1116 -0
  25. google/cloud/bigquery/job/copy_.py +282 -0
  26. google/cloud/bigquery/job/extract.py +271 -0
  27. google/cloud/bigquery/job/load.py +985 -0
  28. google/cloud/bigquery/job/query.py +2498 -0
  29. google/cloud/bigquery/magics/__init__.py +20 -0
  30. google/cloud/bigquery/magics/line_arg_parser/__init__.py +34 -0
  31. google/cloud/bigquery/magics/line_arg_parser/exceptions.py +25 -0
  32. google/cloud/bigquery/magics/line_arg_parser/lexer.py +200 -0
  33. google/cloud/bigquery/magics/line_arg_parser/parser.py +484 -0
  34. google/cloud/bigquery/magics/line_arg_parser/visitors.py +159 -0
  35. google/cloud/bigquery/magics/magics.py +776 -0
  36. google/cloud/bigquery/model.py +517 -0
  37. google/cloud/bigquery/opentelemetry_tracing.py +164 -0
  38. google/cloud/bigquery/py.typed +2 -0
  39. google/cloud/bigquery/query.py +1344 -0
  40. google/cloud/bigquery/retry.py +207 -0
  41. google/cloud/bigquery/routine/__init__.py +33 -0
  42. google/cloud/bigquery/routine/routine.py +744 -0
  43. google/cloud/bigquery/schema.py +896 -0
  44. google/cloud/bigquery/standard_sql.py +389 -0
  45. google/cloud/bigquery/table.py +3594 -0
  46. google/cloud/bigquery/version.py +15 -0
  47. google/cloud/bigquery_v2/__init__.py +56 -0
  48. google/cloud/bigquery_v2/types/__init__.py +54 -0
  49. google/cloud/bigquery_v2/types/encryption_config.py +48 -0
  50. google/cloud/bigquery_v2/types/model.py +1994 -0
  51. google/cloud/bigquery_v2/types/model_reference.py +57 -0
  52. google/cloud/bigquery_v2/types/standard_sql.py +156 -0
  53. google/cloud/bigquery_v2/types/table_reference.py +80 -0
  54. google_cloud_bigquery-3.31.0.dist-info/LICENSE +202 -0
  55. google_cloud_bigquery-3.31.0.dist-info/METADATA +203 -0
  56. google_cloud_bigquery-3.31.0.dist-info/RECORD +58 -0
  57. google_cloud_bigquery-3.31.0.dist-info/WHEEL +5 -0
  58. google_cloud_bigquery-3.31.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,87 @@
1
+ # Copyright 2017 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
+ """Google BigQuery implementation of the Database API Specification v2.0.
16
+
17
+ This module implements the `Python Database API Specification v2.0 (DB-API)`_
18
+ for Google BigQuery.
19
+
20
+ .. _Python Database API Specification v2.0 (DB-API):
21
+ https://www.python.org/dev/peps/pep-0249/
22
+ """
23
+
24
+ from google.cloud.bigquery.dbapi.connection import connect
25
+ from google.cloud.bigquery.dbapi.connection import Connection
26
+ from google.cloud.bigquery.dbapi.cursor import Cursor
27
+ from google.cloud.bigquery.dbapi.exceptions import Warning
28
+ from google.cloud.bigquery.dbapi.exceptions import Error
29
+ from google.cloud.bigquery.dbapi.exceptions import InterfaceError
30
+ from google.cloud.bigquery.dbapi.exceptions import DatabaseError
31
+ from google.cloud.bigquery.dbapi.exceptions import DataError
32
+ from google.cloud.bigquery.dbapi.exceptions import OperationalError
33
+ from google.cloud.bigquery.dbapi.exceptions import IntegrityError
34
+ from google.cloud.bigquery.dbapi.exceptions import InternalError
35
+ from google.cloud.bigquery.dbapi.exceptions import ProgrammingError
36
+ from google.cloud.bigquery.dbapi.exceptions import NotSupportedError
37
+ from google.cloud.bigquery.dbapi.types import Binary
38
+ from google.cloud.bigquery.dbapi.types import Date
39
+ from google.cloud.bigquery.dbapi.types import DateFromTicks
40
+ from google.cloud.bigquery.dbapi.types import Time
41
+ from google.cloud.bigquery.dbapi.types import TimeFromTicks
42
+ from google.cloud.bigquery.dbapi.types import Timestamp
43
+ from google.cloud.bigquery.dbapi.types import TimestampFromTicks
44
+ from google.cloud.bigquery.dbapi.types import BINARY
45
+ from google.cloud.bigquery.dbapi.types import DATETIME
46
+ from google.cloud.bigquery.dbapi.types import NUMBER
47
+ from google.cloud.bigquery.dbapi.types import ROWID
48
+ from google.cloud.bigquery.dbapi.types import STRING
49
+
50
+
51
+ apilevel = "2.0"
52
+
53
+ # Threads may share the module and connections, but not cursors.
54
+ threadsafety = 2
55
+
56
+ paramstyle = "pyformat"
57
+
58
+ __all__ = [
59
+ "apilevel",
60
+ "threadsafety",
61
+ "paramstyle",
62
+ "connect",
63
+ "Connection",
64
+ "Cursor",
65
+ "Warning",
66
+ "Error",
67
+ "InterfaceError",
68
+ "DatabaseError",
69
+ "DataError",
70
+ "OperationalError",
71
+ "IntegrityError",
72
+ "InternalError",
73
+ "ProgrammingError",
74
+ "NotSupportedError",
75
+ "Binary",
76
+ "Date",
77
+ "DateFromTicks",
78
+ "Time",
79
+ "TimeFromTicks",
80
+ "Timestamp",
81
+ "TimestampFromTicks",
82
+ "BINARY",
83
+ "DATETIME",
84
+ "NUMBER",
85
+ "ROWID",
86
+ "STRING",
87
+ ]
@@ -0,0 +1,522 @@
1
+ # Copyright 2017 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
+
16
+ from collections import abc as collections_abc
17
+ import datetime
18
+ import decimal
19
+ import functools
20
+ import numbers
21
+ import re
22
+ import typing
23
+
24
+ from google.cloud import bigquery
25
+ from google.cloud.bigquery import table, query
26
+ from google.cloud.bigquery.dbapi import exceptions
27
+
28
+
29
+ _NUMERIC_SERVER_MIN = decimal.Decimal("-9.9999999999999999999999999999999999999E+28")
30
+ _NUMERIC_SERVER_MAX = decimal.Decimal("9.9999999999999999999999999999999999999E+28")
31
+
32
+ type_parameters_re = re.compile(
33
+ r"""
34
+ \(
35
+ \s*[0-9]+\s*
36
+ (,
37
+ \s*[0-9]+\s*
38
+ )*
39
+ \)
40
+ """,
41
+ re.VERBOSE,
42
+ )
43
+
44
+
45
+ def _parameter_type(name, value, query_parameter_type=None, value_doc=""):
46
+ if query_parameter_type:
47
+ # Strip type parameters
48
+ query_parameter_type = type_parameters_re.sub("", query_parameter_type)
49
+ try:
50
+ parameter_type = getattr(
51
+ query.SqlParameterScalarTypes, query_parameter_type.upper()
52
+ )._type
53
+ except AttributeError:
54
+ raise exceptions.ProgrammingError(
55
+ f"The given parameter type, {query_parameter_type},"
56
+ f" for {name} is not a valid BigQuery scalar type."
57
+ )
58
+ else:
59
+ parameter_type = bigquery_scalar_type(value)
60
+ if parameter_type is None:
61
+ raise exceptions.ProgrammingError(
62
+ f"Encountered parameter {name} with "
63
+ f"{value_doc} value {value} of unexpected type."
64
+ )
65
+ return parameter_type
66
+
67
+
68
+ def scalar_to_query_parameter(value, name=None, query_parameter_type=None):
69
+ """Convert a scalar value into a query parameter.
70
+
71
+ Args:
72
+ value (Any):
73
+ A scalar value to convert into a query parameter.
74
+
75
+ name (str):
76
+ (Optional) Name of the query parameter.
77
+ query_parameter_type (Optional[str]): Given type for the parameter.
78
+
79
+ Returns:
80
+ google.cloud.bigquery.ScalarQueryParameter:
81
+ A query parameter corresponding with the type and value of the plain
82
+ Python object.
83
+
84
+ Raises:
85
+ google.cloud.bigquery.dbapi.exceptions.ProgrammingError:
86
+ if the type cannot be determined.
87
+ """
88
+ return bigquery.ScalarQueryParameter(
89
+ name, _parameter_type(name, value, query_parameter_type), value
90
+ )
91
+
92
+
93
+ def array_to_query_parameter(value, name=None, query_parameter_type=None):
94
+ """Convert an array-like value into a query parameter.
95
+
96
+ Args:
97
+ value (Sequence[Any]): The elements of the array (should not be a
98
+ string-like Sequence).
99
+ name (Optional[str]): Name of the query parameter.
100
+ query_parameter_type (Optional[str]): Given type for the parameter.
101
+
102
+ Returns:
103
+ A query parameter corresponding with the type and value of the plain
104
+ Python object.
105
+
106
+ Raises:
107
+ google.cloud.bigquery.dbapi.exceptions.ProgrammingError:
108
+ if the type of array elements cannot be determined.
109
+ """
110
+ if not array_like(value):
111
+ raise exceptions.ProgrammingError(
112
+ "The value of parameter {} must be a sequence that is "
113
+ "not string-like.".format(name)
114
+ )
115
+
116
+ if query_parameter_type or value:
117
+ array_type = _parameter_type(
118
+ name,
119
+ value[0] if value else None,
120
+ query_parameter_type,
121
+ value_doc="array element ",
122
+ )
123
+ else:
124
+ raise exceptions.ProgrammingError(
125
+ "Encountered an empty array-like value of parameter {}, cannot "
126
+ "determine array elements type.".format(name)
127
+ )
128
+
129
+ return bigquery.ArrayQueryParameter(name, array_type, value)
130
+
131
+
132
+ def _parse_struct_fields(
133
+ fields,
134
+ base,
135
+ parse_struct_field=re.compile(
136
+ r"""
137
+ (?:(\w+)\s+) # field name
138
+ ([A-Z0-9<> ,()]+) # Field type
139
+ $""",
140
+ re.VERBOSE | re.IGNORECASE,
141
+ ).match,
142
+ ):
143
+ # Split a string of struct fields. They're defined by commas, but
144
+ # we have to avoid splitting on commas internal to fields. For
145
+ # example:
146
+ # name string, children array<struct<name string, bdate date>>
147
+ #
148
+ # only has 2 top-level fields.
149
+ fields = fields.split(",")
150
+ fields = list(reversed(fields)) # in the off chance that there are very many
151
+ while fields:
152
+ field = fields.pop()
153
+ while fields and field.count("<") != field.count(">"):
154
+ field += "," + fields.pop()
155
+
156
+ m = parse_struct_field(field.strip())
157
+ if not m:
158
+ raise exceptions.ProgrammingError(
159
+ f"Invalid struct field, {field}, in {base}"
160
+ )
161
+ yield m.group(1, 2)
162
+
163
+
164
+ SCALAR, ARRAY, STRUCT = ("s", "a", "r")
165
+
166
+
167
+ def _parse_type(
168
+ type_,
169
+ name,
170
+ base,
171
+ complex_query_parameter_parse=re.compile(
172
+ r"""
173
+ \s*
174
+ (ARRAY|STRUCT|RECORD) # Type
175
+ \s*
176
+ <([A-Z0-9_<> ,()]+)> # Subtype(s)
177
+ \s*$
178
+ """,
179
+ re.IGNORECASE | re.VERBOSE,
180
+ ).match,
181
+ ):
182
+ if "<" not in type_:
183
+ # Scalar
184
+
185
+ # Strip type parameters
186
+ type_ = type_parameters_re.sub("", type_).strip()
187
+ try:
188
+ type_ = getattr(query.SqlParameterScalarTypes, type_.upper())
189
+ except AttributeError:
190
+ raise exceptions.ProgrammingError(
191
+ f"The given parameter type, {type_},"
192
+ f"{' for ' + name if name else ''}"
193
+ f" is not a valid BigQuery scalar type, in {base}."
194
+ )
195
+ if name:
196
+ type_ = type_.with_name(name)
197
+ return SCALAR, type_
198
+
199
+ m = complex_query_parameter_parse(type_)
200
+ if not m:
201
+ raise exceptions.ProgrammingError(f"Invalid parameter type, {type_}")
202
+ tname, sub = m.group(1, 2)
203
+ if tname.upper() == "ARRAY":
204
+ sub_type = complex_query_parameter_type(None, sub, base)
205
+ if isinstance(sub_type, query.ArrayQueryParameterType):
206
+ raise exceptions.ProgrammingError(f"Array can't contain an array in {base}")
207
+ sub_type._complex__src = sub
208
+ return ARRAY, sub_type
209
+ else:
210
+ return STRUCT, _parse_struct_fields(sub, base)
211
+
212
+
213
+ def complex_query_parameter_type(name: typing.Optional[str], type_: str, base: str):
214
+ """Construct a parameter type (`StructQueryParameterType`) for a complex type
215
+
216
+ or a non-complex type that's part of a complex type.
217
+
218
+ Examples:
219
+
220
+ array<struct<x float64, y float64>>
221
+
222
+ struct<name string, children array<struct<name string, bdate date>>>
223
+
224
+ This is used for computing array types.
225
+ """
226
+
227
+ type_type, sub_type = _parse_type(type_, name, base)
228
+ if type_type == SCALAR:
229
+ result_type = sub_type
230
+ elif type_type == ARRAY:
231
+ result_type = query.ArrayQueryParameterType(sub_type, name=name)
232
+ elif type_type == STRUCT:
233
+ fields = [
234
+ complex_query_parameter_type(field_name, field_type, base)
235
+ for field_name, field_type in sub_type
236
+ ]
237
+ result_type = query.StructQueryParameterType(*fields, name=name)
238
+ else: # pragma: NO COVER
239
+ raise AssertionError("Bad type_type", type_type) # Can't happen :)
240
+
241
+ return result_type
242
+
243
+
244
+ def complex_query_parameter(
245
+ name: typing.Optional[str], value, type_: str, base: typing.Optional[str] = None
246
+ ):
247
+ """
248
+ Construct a query parameter for a complex type (array or struct record)
249
+
250
+ or for a subtype, which may not be complex
251
+
252
+ Examples:
253
+
254
+ array<struct<x float64, y float64>>
255
+
256
+ struct<name string, children array<struct<name string, bdate date>>>
257
+
258
+ """
259
+ param: typing.Union[
260
+ query.ScalarQueryParameter,
261
+ query.ArrayQueryParameter,
262
+ query.StructQueryParameter,
263
+ ]
264
+
265
+ base = base or type_
266
+
267
+ type_type, sub_type = _parse_type(type_, name, base)
268
+
269
+ if type_type == SCALAR:
270
+ param = query.ScalarQueryParameter(name, sub_type._type, value)
271
+ elif type_type == ARRAY:
272
+ if not array_like(value):
273
+ raise exceptions.ProgrammingError(
274
+ f"Array type with non-array-like value"
275
+ f" with type {type(value).__name__}"
276
+ )
277
+ param = query.ArrayQueryParameter(
278
+ name,
279
+ sub_type,
280
+ (
281
+ value
282
+ if isinstance(sub_type, query.ScalarQueryParameterType)
283
+ else [
284
+ complex_query_parameter(None, v, sub_type._complex__src, base)
285
+ for v in value
286
+ ]
287
+ ),
288
+ )
289
+ elif type_type == STRUCT:
290
+ if not isinstance(value, collections_abc.Mapping):
291
+ raise exceptions.ProgrammingError(f"Non-mapping value for type {type_}")
292
+ value_keys = set(value)
293
+ fields = []
294
+ for field_name, field_type in sub_type:
295
+ if field_name not in value:
296
+ raise exceptions.ProgrammingError(
297
+ f"No field value for {field_name} in {type_}"
298
+ )
299
+ value_keys.remove(field_name)
300
+ fields.append(
301
+ complex_query_parameter(field_name, value[field_name], field_type, base)
302
+ )
303
+ if value_keys:
304
+ raise exceptions.ProgrammingError(f"Extra data keys for {type_}")
305
+
306
+ param = query.StructQueryParameter(name, *fields)
307
+ else: # pragma: NO COVER
308
+ raise AssertionError("Bad type_type", type_type) # Can't happen :)
309
+
310
+ return param
311
+
312
+
313
+ def _dispatch_parameter(type_, value, name=None):
314
+ if type_ is not None and "<" in type_:
315
+ param = complex_query_parameter(name, value, type_)
316
+ elif isinstance(value, collections_abc.Mapping):
317
+ raise NotImplementedError(
318
+ f"STRUCT-like parameter values are not supported"
319
+ f"{' (parameter ' + name + ')' if name else ''},"
320
+ f" unless an explicit type is give in the parameter placeholder"
321
+ f" (e.g. '%({name if name else ''}:struct<...>)s')."
322
+ )
323
+ elif array_like(value):
324
+ param = array_to_query_parameter(value, name, type_)
325
+ else:
326
+ param = scalar_to_query_parameter(value, name, type_)
327
+
328
+ return param
329
+
330
+
331
+ def to_query_parameters_list(parameters, parameter_types):
332
+ """Converts a sequence of parameter values into query parameters.
333
+
334
+ Args:
335
+ parameters (Sequence[Any]): Sequence of query parameter values.
336
+ parameter_types:
337
+ A list of parameter types, one for each parameter.
338
+ Unknown types are provided as None.
339
+
340
+ Returns:
341
+ List[google.cloud.bigquery.query._AbstractQueryParameter]:
342
+ A list of query parameters.
343
+ """
344
+ return [
345
+ _dispatch_parameter(type_, value)
346
+ for value, type_ in zip(parameters, parameter_types)
347
+ ]
348
+
349
+
350
+ def to_query_parameters_dict(parameters, query_parameter_types):
351
+ """Converts a dictionary of parameter values into query parameters.
352
+
353
+ Args:
354
+ parameters (Mapping[str, Any]): Dictionary of query parameter values.
355
+ parameter_types:
356
+ A dictionary of parameter types. It needn't have a key for each
357
+ parameter.
358
+
359
+ Returns:
360
+ List[google.cloud.bigquery.query._AbstractQueryParameter]:
361
+ A list of named query parameters.
362
+ """
363
+ return [
364
+ _dispatch_parameter(query_parameter_types.get(name), value, name)
365
+ for name, value in parameters.items()
366
+ ]
367
+
368
+
369
+ def to_query_parameters(parameters, parameter_types):
370
+ """Converts DB-API parameter values into query parameters.
371
+
372
+ Args:
373
+ parameters (Union[Mapping[str, Any], Sequence[Any]]):
374
+ A dictionary or sequence of query parameter values.
375
+ parameter_types (Union[Mapping[str, str], Sequence[str]]):
376
+ A dictionary or list of parameter types.
377
+
378
+ If parameters is a mapping, then this must be a dictionary
379
+ of parameter types. It needn't have a key for each
380
+ parameter.
381
+
382
+ If parameters is a sequence, then this must be a list of
383
+ parameter types, one for each paramater. Unknown types
384
+ are provided as None.
385
+
386
+ Returns:
387
+ List[google.cloud.bigquery.query._AbstractQueryParameter]:
388
+ A list of query parameters.
389
+ """
390
+ if parameters is None:
391
+ return []
392
+
393
+ if isinstance(parameters, collections_abc.Mapping):
394
+ return to_query_parameters_dict(parameters, parameter_types)
395
+ else:
396
+ return to_query_parameters_list(parameters, parameter_types)
397
+
398
+
399
+ def bigquery_scalar_type(value):
400
+ """Return a BigQuery name of the scalar type that matches the given value.
401
+
402
+ If the scalar type name could not be determined (e.g. for non-scalar
403
+ values), ``None`` is returned.
404
+
405
+ Args:
406
+ value (Any)
407
+
408
+ Returns:
409
+ Optional[str]: The BigQuery scalar type name.
410
+ """
411
+ if isinstance(value, bool):
412
+ return "BOOL"
413
+ elif isinstance(value, numbers.Integral):
414
+ return "INT64"
415
+ elif isinstance(value, numbers.Real):
416
+ return "FLOAT64"
417
+ elif isinstance(value, decimal.Decimal):
418
+ vtuple = value.as_tuple()
419
+ # NUMERIC values have precision of 38 (number of digits) and scale of 9 (number
420
+ # of fractional digits), and their max absolute value must be strictly smaller
421
+ # than 1.0E+29.
422
+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#decimal_types
423
+ if (
424
+ len(vtuple.digits) <= 38 # max precision: 38
425
+ and vtuple.exponent >= -9 # max scale: 9
426
+ and _NUMERIC_SERVER_MIN <= value <= _NUMERIC_SERVER_MAX
427
+ ):
428
+ return "NUMERIC"
429
+ else:
430
+ return "BIGNUMERIC"
431
+
432
+ elif isinstance(value, str):
433
+ return "STRING"
434
+ elif isinstance(value, bytes):
435
+ return "BYTES"
436
+ elif isinstance(value, datetime.datetime):
437
+ return "DATETIME" if value.tzinfo is None else "TIMESTAMP"
438
+ elif isinstance(value, datetime.date):
439
+ return "DATE"
440
+ elif isinstance(value, datetime.time):
441
+ return "TIME"
442
+
443
+ return None
444
+
445
+
446
+ def array_like(value):
447
+ """Determine if the given value is array-like.
448
+
449
+ Examples of array-like values (as interpreted by this function) are
450
+ sequences such as ``list`` and ``tuple``, but not strings and other
451
+ iterables such as sets.
452
+
453
+ Args:
454
+ value (Any)
455
+
456
+ Returns:
457
+ bool: ``True`` if the value is considered array-like, ``False`` otherwise.
458
+ """
459
+ return isinstance(value, collections_abc.Sequence) and not isinstance(
460
+ value, (str, bytes, bytearray)
461
+ )
462
+
463
+
464
+ def to_bq_table_rows(rows_iterable):
465
+ """Convert table rows to BigQuery table Row instances.
466
+
467
+ Args:
468
+ rows_iterable (Iterable[Mapping]):
469
+ An iterable of row data items to convert to ``Row`` instances.
470
+
471
+ Returns:
472
+ Iterable[google.cloud.bigquery.table.Row]
473
+ """
474
+
475
+ def to_table_row(row):
476
+ # NOTE: We fetch ARROW values, thus we need to convert them to Python
477
+ # objects with as_py().
478
+ values = tuple(value.as_py() for value in row.values())
479
+ keys_to_index = {key: i for i, key in enumerate(row.keys())}
480
+ return table.Row(values, keys_to_index)
481
+
482
+ return (to_table_row(row_data) for row_data in rows_iterable)
483
+
484
+
485
+ def raise_on_closed(
486
+ exc_msg, exc_class=exceptions.ProgrammingError, closed_attr_name="_closed"
487
+ ):
488
+ """Make public instance methods raise an error if the instance is closed."""
489
+
490
+ def _raise_on_closed(method):
491
+ """Make a non-static method raise an error if its containing instance is closed."""
492
+
493
+ def with_closed_check(self, *args, **kwargs):
494
+ if getattr(self, closed_attr_name):
495
+ raise exc_class(exc_msg)
496
+ return method(self, *args, **kwargs)
497
+
498
+ functools.update_wrapper(with_closed_check, method)
499
+ return with_closed_check
500
+
501
+ def decorate_public_methods(klass):
502
+ """Apply ``_raise_on_closed()`` decorator to public instance methods."""
503
+ for name in dir(klass):
504
+ if name.startswith("_") and name != "__iter__":
505
+ continue
506
+
507
+ member = getattr(klass, name)
508
+ if not callable(member):
509
+ continue
510
+
511
+ # We need to check for class/static methods directly in the instance
512
+ # __dict__, not via the retrieved attribute (`member`), as the
513
+ # latter is already a callable *produced* by one of these descriptors.
514
+ if isinstance(klass.__dict__[name], (staticmethod, classmethod)):
515
+ continue
516
+
517
+ member = _raise_on_closed(member)
518
+ setattr(klass, name, member)
519
+
520
+ return klass
521
+
522
+ return decorate_public_methods