google-cloud-spanner 3.50.1__tar.gz → 3.52.0__tar.gz
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.
- {google_cloud_spanner-3.50.1/google_cloud_spanner.egg-info → google_cloud_spanner-3.52.0}/PKG-INFO +2 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/connection.py +53 -12
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/cursor.py +39 -3
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parse_utils.py +9 -2
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/transaction_helper.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/_helpers.py +254 -47
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/_opentelemetry_tracing.py +144 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/batch.py +37 -5
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/client.py +21 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/database.py +187 -107
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/merged_result_set.py +12 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/constants.py +63 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_exporter.py +392 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_tracer.py +558 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_tracer_factory.py +309 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/pool.py +197 -26
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/request_id_header.py +42 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/session.py +152 -100
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/snapshot.py +114 -19
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/streamed.py +55 -10
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/testing/mock_database_admin.py +38 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/testing/mock_spanner.py +264 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/testing/spanner_database_admin_pb2_grpc.py +1267 -0
- google_cloud_spanner-3.52.0/google/cloud/spanner_v1/testing/spanner_pb2_grpc.py +882 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/transaction.py +95 -37
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0/google_cloud_spanner.egg-info}/PKG-INFO +2 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/SOURCES.txt +20 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/requires.txt +1 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/setup.py +1 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/_helpers.py +61 -4
- google_cloud_spanner-3.52.0/tests/mockserver_tests/mock_server_test_base.py +191 -0
- google_cloud_spanner-3.52.0/tests/mockserver_tests/test_aborted_transaction.py +143 -0
- google_cloud_spanner-3.52.0/tests/mockserver_tests/test_basics.py +109 -0
- google_cloud_spanner-3.52.0/tests/mockserver_tests/test_tags.py +206 -0
- google_cloud_spanner-3.52.0/tests/system/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/_helpers.py +18 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_dbapi.py +45 -2
- google_cloud_spanner-3.52.0/tests/system/test_observability_options.py +454 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_session_api.py +99 -54
- google_cloud_spanner-3.52.0/tests/system/utils/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_connection.py +31 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_parse_utils.py +7 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test__helpers.py +60 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test__opentelemetry_tracing.py +73 -0
- google_cloud_spanner-3.52.0/tests/unit/test_atomic_counter.py +78 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_batch.py +54 -7
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_database.py +12 -5
- google_cloud_spanner-3.52.0/tests/unit/test_metric_exporter.py +488 -0
- google_cloud_spanner-3.52.0/tests/unit/test_metrics_tracer.py +224 -0
- google_cloud_spanner-3.52.0/tests/unit/test_metrics_tracer_factory.py +59 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_pool.py +433 -187
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_session.py +56 -5
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_snapshot.py +40 -22
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_spanner.py +4 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_transaction.py +99 -10
- google_cloud_spanner-3.50.1/google/cloud/spanner_v1/_opentelemetry_tracing.py +0 -85
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/LICENSE +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/MANIFEST.in +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/README.rst +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest_base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/backup_schedule.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/common.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest_base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/common.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/_helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/batch_dml_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/checksum.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/client_side_statement_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/client_side_statement_parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/exceptions.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parsed_statement.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/partition_helper.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/version.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/data_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/instance.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/keyset.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/param_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/async_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/grpc.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/rest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/rest_base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/table.py +0 -0
- {google_cloud_spanner-3.50.1/tests/system → google_cloud_spanner-3.52.0/google/cloud/spanner_v1/testing}/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/database_test.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/interceptors.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/commit_response.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/keys.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/mutation.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/query_plan.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/result_set.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/transaction.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/type.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/dependency_links.txt +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/not-zip-safe +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/top_level.txt +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/setup.cfg +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/_fixtures.py +0 -0
- {google_cloud_spanner-3.50.1/tests/system/utils → google_cloud_spanner-3.52.0/tests/mockserver_tests}/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/_sample_data.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/conftest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_backup_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_database_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_instance_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_streaming_chunking.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/test_table_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/testdata/descriptors.pb +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/testdata/singer.proto +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/testdata/singer_pb2.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/utils/clear_streaming.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/utils/populate_streaming.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/utils/scrub_instances.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/system/utils/streaming_utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_database_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_instance_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_v1/test_spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test__helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_batch_dml_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_checksum.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_connect.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_cursor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_globals.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_transaction_helper.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/streaming-read-acceptance-test.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_datatypes.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_instance.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_keyset.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_packaging.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_param_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_streamed.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/test_table.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/testdata/singer.proto +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/tests/unit/testdata/singer_pb2.py +0 -0
{google_cloud_spanner-3.50.1/google_cloud_spanner.egg-info → google_cloud_spanner-3.52.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: google-cloud-spanner
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.52.0
|
|
4
4
|
Summary: Google Cloud Spanner API client library
|
|
5
5
|
Home-page: https://github.com/googleapis/python-spanner
|
|
6
6
|
Author: Google LLC
|
|
@@ -34,6 +34,7 @@ Provides-Extra: tracing
|
|
|
34
34
|
Requires-Dist: opentelemetry-api>=1.22.0; extra == "tracing"
|
|
35
35
|
Requires-Dist: opentelemetry-sdk>=1.22.0; extra == "tracing"
|
|
36
36
|
Requires-Dist: opentelemetry-semantic-conventions>=0.43b0; extra == "tracing"
|
|
37
|
+
Requires-Dist: google-cloud-monitoring>=2.16.0; extra == "tracing"
|
|
37
38
|
Provides-Extra: libcst
|
|
38
39
|
Requires-Dist: libcst>=0.2.5; extra == "libcst"
|
|
39
40
|
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/connection.py
RENAMED
|
@@ -89,9 +89,11 @@ class Connection:
|
|
|
89
89
|
committed by other transactions since the start of the read-only transaction. Commit or rolling back
|
|
90
90
|
the read-only transaction is semantically the same, and only indicates that the read-only transaction
|
|
91
91
|
should end a that a new one should be started when the next statement is executed.
|
|
92
|
+
|
|
93
|
+
**kwargs: Initial value for connection variables.
|
|
92
94
|
"""
|
|
93
95
|
|
|
94
|
-
def __init__(self, instance, database=None, read_only=False):
|
|
96
|
+
def __init__(self, instance, database=None, read_only=False, **kwargs):
|
|
95
97
|
self._instance = instance
|
|
96
98
|
self._database = database
|
|
97
99
|
self._ddl_statements = []
|
|
@@ -111,12 +113,13 @@ class Connection:
|
|
|
111
113
|
self.request_priority = None
|
|
112
114
|
self._transaction_begin_marked = False
|
|
113
115
|
# whether transaction started at Spanner. This means that we had
|
|
114
|
-
# made
|
|
116
|
+
# made at least one call to Spanner.
|
|
115
117
|
self._spanner_transaction_started = False
|
|
116
118
|
self._batch_mode = BatchMode.NONE
|
|
117
119
|
self._batch_dml_executor: BatchDmlExecutor = None
|
|
118
120
|
self._transaction_helper = TransactionRetryHelper(self)
|
|
119
121
|
self._autocommit_dml_mode: AutocommitDmlMode = AutocommitDmlMode.TRANSACTIONAL
|
|
122
|
+
self._connection_variables = kwargs
|
|
120
123
|
|
|
121
124
|
@property
|
|
122
125
|
def spanner_client(self):
|
|
@@ -206,6 +209,10 @@ class Connection:
|
|
|
206
209
|
"""
|
|
207
210
|
return (not self._autocommit) or self._transaction_begin_marked
|
|
208
211
|
|
|
212
|
+
@property
|
|
213
|
+
def _ignore_transaction_warnings(self):
|
|
214
|
+
return self._connection_variables.get("ignore_transaction_warnings", False)
|
|
215
|
+
|
|
209
216
|
@property
|
|
210
217
|
def instance(self):
|
|
211
218
|
"""Instance to which this connection relates.
|
|
@@ -232,7 +239,7 @@ class Connection:
|
|
|
232
239
|
Args:
|
|
233
240
|
value (bool): True for ReadOnly mode, False for ReadWrite.
|
|
234
241
|
"""
|
|
235
|
-
if self._spanner_transaction_started:
|
|
242
|
+
if self._read_only != value and self._spanner_transaction_started:
|
|
236
243
|
raise ValueError(
|
|
237
244
|
"Connection read/write mode can't be changed while a transaction is in progress. "
|
|
238
245
|
"Commit or rollback the current transaction and try again."
|
|
@@ -254,6 +261,28 @@ class Connection:
|
|
|
254
261
|
self.request_priority = None
|
|
255
262
|
return req_opts
|
|
256
263
|
|
|
264
|
+
@property
|
|
265
|
+
def transaction_tag(self):
|
|
266
|
+
"""The transaction tag that will be applied to the next read/write
|
|
267
|
+
transaction on this `Connection`. This property is automatically cleared
|
|
268
|
+
when a new transaction is started.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
str: The transaction tag that will be applied to the next read/write transaction.
|
|
272
|
+
"""
|
|
273
|
+
return self._connection_variables.get("transaction_tag", None)
|
|
274
|
+
|
|
275
|
+
@transaction_tag.setter
|
|
276
|
+
def transaction_tag(self, value):
|
|
277
|
+
"""Sets the transaction tag for the next read/write transaction on this
|
|
278
|
+
`Connection`. This property is automatically cleared when a new transaction
|
|
279
|
+
is started.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
value (str): The transaction tag for the next read/write transaction.
|
|
283
|
+
"""
|
|
284
|
+
self._connection_variables["transaction_tag"] = value
|
|
285
|
+
|
|
257
286
|
@property
|
|
258
287
|
def staleness(self):
|
|
259
288
|
"""Current read staleness option value of this `Connection`.
|
|
@@ -270,7 +299,7 @@ class Connection:
|
|
|
270
299
|
Args:
|
|
271
300
|
value (dict): Staleness type and value.
|
|
272
301
|
"""
|
|
273
|
-
if self._spanner_transaction_started:
|
|
302
|
+
if self._spanner_transaction_started and value != self._staleness:
|
|
274
303
|
raise ValueError(
|
|
275
304
|
"`staleness` option can't be changed while a transaction is in progress. "
|
|
276
305
|
"Commit or rollback the current transaction and try again."
|
|
@@ -333,6 +362,8 @@ class Connection:
|
|
|
333
362
|
if not self.read_only and self._client_transaction_started:
|
|
334
363
|
if not self._spanner_transaction_started:
|
|
335
364
|
self._transaction = self._session_checkout().transaction()
|
|
365
|
+
self._transaction.transaction_tag = self.transaction_tag
|
|
366
|
+
self.transaction_tag = None
|
|
336
367
|
self._snapshot = None
|
|
337
368
|
self._spanner_transaction_started = True
|
|
338
369
|
self._transaction.begin()
|
|
@@ -398,9 +429,10 @@ class Connection:
|
|
|
398
429
|
if self.database is None:
|
|
399
430
|
raise ValueError("Database needs to be passed for this operation")
|
|
400
431
|
if not self._client_transaction_started:
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
432
|
+
if not self._ignore_transaction_warnings:
|
|
433
|
+
warnings.warn(
|
|
434
|
+
CLIENT_TRANSACTION_NOT_STARTED_WARNING, UserWarning, stacklevel=2
|
|
435
|
+
)
|
|
404
436
|
return
|
|
405
437
|
|
|
406
438
|
self.run_prior_DDL_statements()
|
|
@@ -418,9 +450,10 @@ class Connection:
|
|
|
418
450
|
This is a no-op if there is no active client transaction.
|
|
419
451
|
"""
|
|
420
452
|
if not self._client_transaction_started:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
453
|
+
if not self._ignore_transaction_warnings:
|
|
454
|
+
warnings.warn(
|
|
455
|
+
CLIENT_TRANSACTION_NOT_STARTED_WARNING, UserWarning, stacklevel=2
|
|
456
|
+
)
|
|
424
457
|
return
|
|
425
458
|
try:
|
|
426
459
|
if self._spanner_transaction_started and not self._read_only:
|
|
@@ -449,7 +482,9 @@ class Connection:
|
|
|
449
482
|
|
|
450
483
|
return self.database.update_ddl(ddl_statements).result()
|
|
451
484
|
|
|
452
|
-
def run_statement(
|
|
485
|
+
def run_statement(
|
|
486
|
+
self, statement: Statement, request_options: RequestOptions = None
|
|
487
|
+
):
|
|
453
488
|
"""Run single SQL statement in begun transaction.
|
|
454
489
|
|
|
455
490
|
This method is never used in autocommit mode. In
|
|
@@ -463,6 +498,9 @@ class Connection:
|
|
|
463
498
|
:param retried: (Optional) Retry the SQL statement if statement
|
|
464
499
|
execution failed. Defaults to false.
|
|
465
500
|
|
|
501
|
+
:type request_options: :class:`RequestOptions`
|
|
502
|
+
:param request_options: Request options to use for this statement.
|
|
503
|
+
|
|
466
504
|
:rtype: :class:`google.cloud.spanner_v1.streamed.StreamedResultSet`,
|
|
467
505
|
:class:`google.cloud.spanner_dbapi.checksum.ResultsChecksum`
|
|
468
506
|
:returns: Streamed result set of the statement and a
|
|
@@ -473,7 +511,7 @@ class Connection:
|
|
|
473
511
|
statement.sql,
|
|
474
512
|
statement.params,
|
|
475
513
|
param_types=statement.param_types,
|
|
476
|
-
request_options=self.request_options,
|
|
514
|
+
request_options=request_options or self.request_options,
|
|
477
515
|
)
|
|
478
516
|
|
|
479
517
|
@check_not_closed
|
|
@@ -654,6 +692,7 @@ def connect(
|
|
|
654
692
|
user_agent=None,
|
|
655
693
|
client=None,
|
|
656
694
|
route_to_leader_enabled=True,
|
|
695
|
+
**kwargs,
|
|
657
696
|
):
|
|
658
697
|
"""Creates a connection to a Google Cloud Spanner database.
|
|
659
698
|
|
|
@@ -696,6 +735,8 @@ def connect(
|
|
|
696
735
|
disable leader aware routing. Disabling leader aware routing would
|
|
697
736
|
route all requests in RW/PDML transactions to the closest region.
|
|
698
737
|
|
|
738
|
+
**kwargs: Initial value for connection variables.
|
|
739
|
+
|
|
699
740
|
|
|
700
741
|
:rtype: :class:`google.cloud.spanner_dbapi.connection.Connection`
|
|
701
742
|
:returns: Connection object associated with the given Google Cloud Spanner
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/cursor.py
RENAMED
|
@@ -50,6 +50,7 @@ from google.cloud.spanner_dbapi.parsed_statement import (
|
|
|
50
50
|
from google.cloud.spanner_dbapi.transaction_helper import CursorStatementType
|
|
51
51
|
from google.cloud.spanner_dbapi.utils import PeekIterator
|
|
52
52
|
from google.cloud.spanner_dbapi.utils import StreamedManyResultSets
|
|
53
|
+
from google.cloud.spanner_v1 import RequestOptions
|
|
53
54
|
from google.cloud.spanner_v1.merged_result_set import MergedResultSet
|
|
54
55
|
|
|
55
56
|
ColumnDetails = namedtuple("column_details", ["null_ok", "spanner_type"])
|
|
@@ -97,6 +98,39 @@ class Cursor(object):
|
|
|
97
98
|
self._parsed_statement: ParsedStatement = None
|
|
98
99
|
self._in_retry_mode = False
|
|
99
100
|
self._batch_dml_rows_count = None
|
|
101
|
+
self._request_tag = None
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def request_tag(self):
|
|
105
|
+
"""The request tag that will be applied to the next statement on this
|
|
106
|
+
cursor. This property is automatically cleared when a statement is
|
|
107
|
+
executed.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
str: The request tag that will be applied to the next statement on
|
|
111
|
+
this cursor.
|
|
112
|
+
"""
|
|
113
|
+
return self._request_tag
|
|
114
|
+
|
|
115
|
+
@request_tag.setter
|
|
116
|
+
def request_tag(self, value):
|
|
117
|
+
"""Sets the request tag for the next statement on this cursor. This
|
|
118
|
+
property is automatically cleared when a statement is executed.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
value (str): The request tag for the statement.
|
|
122
|
+
"""
|
|
123
|
+
self._request_tag = value
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def request_options(self):
|
|
127
|
+
options = self.connection.request_options
|
|
128
|
+
if self._request_tag:
|
|
129
|
+
if not options:
|
|
130
|
+
options = RequestOptions()
|
|
131
|
+
options.request_tag = self._request_tag
|
|
132
|
+
self._request_tag = None
|
|
133
|
+
return options
|
|
100
134
|
|
|
101
135
|
@property
|
|
102
136
|
def is_closed(self):
|
|
@@ -284,7 +318,7 @@ class Cursor(object):
|
|
|
284
318
|
sql,
|
|
285
319
|
params=args,
|
|
286
320
|
param_types=self._parsed_statement.statement.param_types,
|
|
287
|
-
request_options=self.
|
|
321
|
+
request_options=self.request_options,
|
|
288
322
|
)
|
|
289
323
|
self._result_set = None
|
|
290
324
|
else:
|
|
@@ -318,7 +352,9 @@ class Cursor(object):
|
|
|
318
352
|
if self.connection._client_transaction_started:
|
|
319
353
|
while True:
|
|
320
354
|
try:
|
|
321
|
-
self._result_set = self.connection.run_statement(
|
|
355
|
+
self._result_set = self.connection.run_statement(
|
|
356
|
+
statement, self.request_options
|
|
357
|
+
)
|
|
322
358
|
self._itr = PeekIterator(self._result_set)
|
|
323
359
|
return
|
|
324
360
|
except Aborted:
|
|
@@ -478,7 +514,7 @@ class Cursor(object):
|
|
|
478
514
|
sql,
|
|
479
515
|
params,
|
|
480
516
|
get_param_types(params),
|
|
481
|
-
request_options=self.
|
|
517
|
+
request_options=self.request_options,
|
|
482
518
|
)
|
|
483
519
|
# Read the first element so that the StreamedResultSet can
|
|
484
520
|
# return the metadata after a DQL statement.
|
|
@@ -29,12 +29,19 @@ from .parsed_statement import ParsedStatement, StatementType, Statement
|
|
|
29
29
|
from .types import DateStr, TimestampStr
|
|
30
30
|
from .utils import sanitize_literals_for_upload
|
|
31
31
|
|
|
32
|
+
# Note: This mapping deliberately does not contain a value for float.
|
|
33
|
+
# The reason for that is that it is better to just let Spanner determine
|
|
34
|
+
# the parameter type instead of specifying one explicitly. The reason for
|
|
35
|
+
# this is that if the client specifies FLOAT64, and the actual column that
|
|
36
|
+
# the parameter is used for is of type FLOAT32, then Spanner will return an
|
|
37
|
+
# error. If however the client does not specify a type, then Spanner will
|
|
38
|
+
# automatically choose the appropriate type based on the column where the
|
|
39
|
+
# value will be inserted/updated or that it will be compared with.
|
|
32
40
|
TYPES_MAP = {
|
|
33
41
|
bool: spanner.param_types.BOOL,
|
|
34
42
|
bytes: spanner.param_types.BYTES,
|
|
35
43
|
str: spanner.param_types.STRING,
|
|
36
44
|
int: spanner.param_types.INT64,
|
|
37
|
-
float: spanner.param_types.FLOAT64,
|
|
38
45
|
datetime.datetime: spanner.param_types.TIMESTAMP,
|
|
39
46
|
datetime.date: spanner.param_types.DATE,
|
|
40
47
|
DateStr: spanner.param_types.DATE,
|
|
@@ -148,7 +155,7 @@ STMT_UPDATING = "UPDATING"
|
|
|
148
155
|
STMT_INSERT = "INSERT"
|
|
149
156
|
|
|
150
157
|
# Heuristic for identifying statements that don't need to be run as updates.
|
|
151
|
-
RE_NON_UPDATE = re.compile(r"^\W*(SELECT)", re.IGNORECASE)
|
|
158
|
+
RE_NON_UPDATE = re.compile(r"^\W*(SELECT|GRAPH|FROM)", re.IGNORECASE)
|
|
152
159
|
|
|
153
160
|
RE_WITH = re.compile(r"^\s*(WITH)", re.IGNORECASE)
|
|
154
161
|
|
|
@@ -20,7 +20,7 @@ import time
|
|
|
20
20
|
|
|
21
21
|
from google.cloud.spanner_dbapi.batch_dml_executor import BatchMode
|
|
22
22
|
from google.cloud.spanner_dbapi.exceptions import RetryAborted
|
|
23
|
-
from google.cloud.spanner_v1.
|
|
23
|
+
from google.cloud.spanner_v1._helpers import _get_retry_delay
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
26
|
from google.cloud.spanner_dbapi import Connection, Cursor
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/_helpers.py
RENAMED
|
@@ -19,6 +19,7 @@ import decimal
|
|
|
19
19
|
import math
|
|
20
20
|
import time
|
|
21
21
|
import base64
|
|
22
|
+
import threading
|
|
22
23
|
|
|
23
24
|
from google.protobuf.struct_pb2 import ListValue
|
|
24
25
|
from google.protobuf.struct_pb2 import Value
|
|
@@ -26,10 +27,15 @@ from google.protobuf.message import Message
|
|
|
26
27
|
from google.protobuf.internal.enum_type_wrapper import EnumTypeWrapper
|
|
27
28
|
|
|
28
29
|
from google.api_core import datetime_helpers
|
|
30
|
+
from google.api_core.exceptions import Aborted
|
|
29
31
|
from google.cloud._helpers import _date_from_iso8601_date
|
|
30
32
|
from google.cloud.spanner_v1 import TypeCode
|
|
31
33
|
from google.cloud.spanner_v1 import ExecuteSqlRequest
|
|
32
34
|
from google.cloud.spanner_v1 import JsonObject
|
|
35
|
+
from google.cloud.spanner_v1.request_id_header import with_request_id
|
|
36
|
+
from google.rpc.error_details_pb2 import RetryInfo
|
|
37
|
+
|
|
38
|
+
import random
|
|
33
39
|
|
|
34
40
|
# Validation error messages
|
|
35
41
|
NUMERIC_MAX_SCALE_ERR_MSG = (
|
|
@@ -266,66 +272,69 @@ def _parse_value_pb(value_pb, field_type, field_name, column_info=None):
|
|
|
266
272
|
:returns: value extracted from value_pb
|
|
267
273
|
:raises ValueError: if unknown type is passed
|
|
268
274
|
"""
|
|
275
|
+
decoder = _get_type_decoder(field_type, field_name, column_info)
|
|
276
|
+
return _parse_nullable(value_pb, decoder)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _get_type_decoder(field_type, field_name, column_info=None):
|
|
280
|
+
"""Returns a function that converts a Value protobuf to cell data.
|
|
281
|
+
|
|
282
|
+
:type field_type: :class:`~google.cloud.spanner_v1.types.Type`
|
|
283
|
+
:param field_type: type code for the value
|
|
284
|
+
|
|
285
|
+
:type field_name: str
|
|
286
|
+
:param field_name: column name
|
|
287
|
+
|
|
288
|
+
:type column_info: dict
|
|
289
|
+
:param column_info: (Optional) dict of column name and column information.
|
|
290
|
+
An object where column names as keys and custom objects as corresponding
|
|
291
|
+
values for deserialization. It's specifically useful for data types like
|
|
292
|
+
protobuf where deserialization logic is on user-specific code. When provided,
|
|
293
|
+
the custom object enables deserialization of backend-received column data.
|
|
294
|
+
If not provided, data remains serialized as bytes for Proto Messages and
|
|
295
|
+
integer for Proto Enums.
|
|
296
|
+
|
|
297
|
+
:rtype: a function that takes a single protobuf value as an input argument
|
|
298
|
+
:returns: a function that can be used to extract a value from a protobuf value
|
|
299
|
+
:raises ValueError: if unknown type is passed
|
|
300
|
+
"""
|
|
301
|
+
|
|
269
302
|
type_code = field_type.code
|
|
270
|
-
if value_pb.HasField("null_value"):
|
|
271
|
-
return None
|
|
272
303
|
if type_code == TypeCode.STRING:
|
|
273
|
-
return
|
|
304
|
+
return _parse_string
|
|
274
305
|
elif type_code == TypeCode.BYTES:
|
|
275
|
-
return
|
|
306
|
+
return _parse_bytes
|
|
276
307
|
elif type_code == TypeCode.BOOL:
|
|
277
|
-
return
|
|
308
|
+
return _parse_bool
|
|
278
309
|
elif type_code == TypeCode.INT64:
|
|
279
|
-
return
|
|
310
|
+
return _parse_int64
|
|
280
311
|
elif type_code == TypeCode.FLOAT64:
|
|
281
|
-
|
|
282
|
-
return float(value_pb.string_value)
|
|
283
|
-
else:
|
|
284
|
-
return value_pb.number_value
|
|
312
|
+
return _parse_float
|
|
285
313
|
elif type_code == TypeCode.FLOAT32:
|
|
286
|
-
|
|
287
|
-
return float(value_pb.string_value)
|
|
288
|
-
else:
|
|
289
|
-
return value_pb.number_value
|
|
314
|
+
return _parse_float
|
|
290
315
|
elif type_code == TypeCode.DATE:
|
|
291
|
-
return
|
|
316
|
+
return _parse_date
|
|
292
317
|
elif type_code == TypeCode.TIMESTAMP:
|
|
293
|
-
|
|
294
|
-
return DatetimeWithNanoseconds.from_rfc3339(value_pb.string_value)
|
|
295
|
-
elif type_code == TypeCode.ARRAY:
|
|
296
|
-
return [
|
|
297
|
-
_parse_value_pb(
|
|
298
|
-
item_pb, field_type.array_element_type, field_name, column_info
|
|
299
|
-
)
|
|
300
|
-
for item_pb in value_pb.list_value.values
|
|
301
|
-
]
|
|
302
|
-
elif type_code == TypeCode.STRUCT:
|
|
303
|
-
return [
|
|
304
|
-
_parse_value_pb(
|
|
305
|
-
item_pb, field_type.struct_type.fields[i].type_, field_name, column_info
|
|
306
|
-
)
|
|
307
|
-
for (i, item_pb) in enumerate(value_pb.list_value.values)
|
|
308
|
-
]
|
|
318
|
+
return _parse_timestamp
|
|
309
319
|
elif type_code == TypeCode.NUMERIC:
|
|
310
|
-
return
|
|
320
|
+
return _parse_numeric
|
|
311
321
|
elif type_code == TypeCode.JSON:
|
|
312
|
-
return
|
|
322
|
+
return _parse_json
|
|
313
323
|
elif type_code == TypeCode.PROTO:
|
|
314
|
-
|
|
315
|
-
if column_info is not None and column_info.get(field_name) is not None:
|
|
316
|
-
default_proto_message = column_info.get(field_name)
|
|
317
|
-
if isinstance(default_proto_message, Message):
|
|
318
|
-
proto_message = type(default_proto_message)()
|
|
319
|
-
proto_message.ParseFromString(bytes_value)
|
|
320
|
-
return proto_message
|
|
321
|
-
return bytes_value
|
|
324
|
+
return lambda value_pb: _parse_proto(value_pb, column_info, field_name)
|
|
322
325
|
elif type_code == TypeCode.ENUM:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return
|
|
326
|
+
return lambda value_pb: _parse_proto_enum(value_pb, column_info, field_name)
|
|
327
|
+
elif type_code == TypeCode.ARRAY:
|
|
328
|
+
element_decoder = _get_type_decoder(
|
|
329
|
+
field_type.array_element_type, field_name, column_info
|
|
330
|
+
)
|
|
331
|
+
return lambda value_pb: _parse_array(value_pb, element_decoder)
|
|
332
|
+
elif type_code == TypeCode.STRUCT:
|
|
333
|
+
element_decoders = [
|
|
334
|
+
_get_type_decoder(item_field.type_, field_name, column_info)
|
|
335
|
+
for item_field in field_type.struct_type.fields
|
|
336
|
+
]
|
|
337
|
+
return lambda value_pb: _parse_struct(value_pb, element_decoders)
|
|
329
338
|
else:
|
|
330
339
|
raise ValueError("Unknown type: %s" % (field_type,))
|
|
331
340
|
|
|
@@ -351,6 +360,87 @@ def _parse_list_value_pbs(rows, row_type):
|
|
|
351
360
|
return result
|
|
352
361
|
|
|
353
362
|
|
|
363
|
+
def _parse_string(value_pb) -> str:
|
|
364
|
+
return value_pb.string_value
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _parse_bytes(value_pb):
|
|
368
|
+
return value_pb.string_value.encode("utf8")
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _parse_bool(value_pb) -> bool:
|
|
372
|
+
return value_pb.bool_value
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _parse_int64(value_pb) -> int:
|
|
376
|
+
return int(value_pb.string_value)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _parse_float(value_pb) -> float:
|
|
380
|
+
if value_pb.HasField("string_value"):
|
|
381
|
+
return float(value_pb.string_value)
|
|
382
|
+
else:
|
|
383
|
+
return value_pb.number_value
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _parse_date(value_pb):
|
|
387
|
+
return _date_from_iso8601_date(value_pb.string_value)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def _parse_timestamp(value_pb):
|
|
391
|
+
DatetimeWithNanoseconds = datetime_helpers.DatetimeWithNanoseconds
|
|
392
|
+
return DatetimeWithNanoseconds.from_rfc3339(value_pb.string_value)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _parse_numeric(value_pb):
|
|
396
|
+
return decimal.Decimal(value_pb.string_value)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def _parse_json(value_pb):
|
|
400
|
+
return JsonObject.from_str(value_pb.string_value)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _parse_proto(value_pb, column_info, field_name):
|
|
404
|
+
bytes_value = base64.b64decode(value_pb.string_value)
|
|
405
|
+
if column_info is not None and column_info.get(field_name) is not None:
|
|
406
|
+
default_proto_message = column_info.get(field_name)
|
|
407
|
+
if isinstance(default_proto_message, Message):
|
|
408
|
+
proto_message = type(default_proto_message)()
|
|
409
|
+
proto_message.ParseFromString(bytes_value)
|
|
410
|
+
return proto_message
|
|
411
|
+
return bytes_value
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _parse_proto_enum(value_pb, column_info, field_name):
|
|
415
|
+
int_value = int(value_pb.string_value)
|
|
416
|
+
if column_info is not None and column_info.get(field_name) is not None:
|
|
417
|
+
proto_enum = column_info.get(field_name)
|
|
418
|
+
if isinstance(proto_enum, EnumTypeWrapper):
|
|
419
|
+
return proto_enum.Name(int_value)
|
|
420
|
+
return int_value
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _parse_array(value_pb, element_decoder) -> []:
|
|
424
|
+
return [
|
|
425
|
+
_parse_nullable(item_pb, element_decoder)
|
|
426
|
+
for item_pb in value_pb.list_value.values
|
|
427
|
+
]
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def _parse_struct(value_pb, element_decoders):
|
|
431
|
+
return [
|
|
432
|
+
_parse_nullable(item_pb, element_decoders[i])
|
|
433
|
+
for (i, item_pb) in enumerate(value_pb.list_value.values)
|
|
434
|
+
]
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def _parse_nullable(value_pb, decoder):
|
|
438
|
+
if value_pb.HasField("null_value"):
|
|
439
|
+
return None
|
|
440
|
+
else:
|
|
441
|
+
return decoder(value_pb)
|
|
442
|
+
|
|
443
|
+
|
|
354
444
|
class _SessionWrapper(object):
|
|
355
445
|
"""Base class for objects wrapping a session.
|
|
356
446
|
|
|
@@ -374,11 +464,29 @@ def _metadata_with_prefix(prefix, **kw):
|
|
|
374
464
|
return [("google-cloud-resource-prefix", prefix)]
|
|
375
465
|
|
|
376
466
|
|
|
467
|
+
def _retry_on_aborted_exception(
|
|
468
|
+
func,
|
|
469
|
+
deadline,
|
|
470
|
+
):
|
|
471
|
+
"""
|
|
472
|
+
Handles retry logic for Aborted exceptions, considering the deadline.
|
|
473
|
+
"""
|
|
474
|
+
attempts = 0
|
|
475
|
+
while True:
|
|
476
|
+
try:
|
|
477
|
+
attempts += 1
|
|
478
|
+
return func()
|
|
479
|
+
except Aborted as exc:
|
|
480
|
+
_delay_until_retry(exc, deadline=deadline, attempts=attempts)
|
|
481
|
+
continue
|
|
482
|
+
|
|
483
|
+
|
|
377
484
|
def _retry(
|
|
378
485
|
func,
|
|
379
486
|
retry_count=5,
|
|
380
487
|
delay=2,
|
|
381
488
|
allowed_exceptions=None,
|
|
489
|
+
beforeNextRetry=None,
|
|
382
490
|
):
|
|
383
491
|
"""
|
|
384
492
|
Retry a function with a specified number of retries, delay between retries, and list of allowed exceptions.
|
|
@@ -395,6 +503,9 @@ def _retry(
|
|
|
395
503
|
"""
|
|
396
504
|
retries = 0
|
|
397
505
|
while retries <= retry_count:
|
|
506
|
+
if retries > 0 and beforeNextRetry:
|
|
507
|
+
beforeNextRetry(retries, delay)
|
|
508
|
+
|
|
398
509
|
try:
|
|
399
510
|
return func()
|
|
400
511
|
except Exception as exc:
|
|
@@ -437,3 +548,99 @@ def _metadata_with_leader_aware_routing(value, **kw):
|
|
|
437
548
|
List[Tuple[str, str]]: RPC metadata with leader aware routing header
|
|
438
549
|
"""
|
|
439
550
|
return ("x-goog-spanner-route-to-leader", str(value).lower())
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def _delay_until_retry(exc, deadline, attempts):
|
|
554
|
+
"""Helper for :meth:`Session.run_in_transaction`.
|
|
555
|
+
|
|
556
|
+
Detect retryable abort, and impose server-supplied delay.
|
|
557
|
+
|
|
558
|
+
:type exc: :class:`google.api_core.exceptions.Aborted`
|
|
559
|
+
:param exc: exception for aborted transaction
|
|
560
|
+
|
|
561
|
+
:type deadline: float
|
|
562
|
+
:param deadline: maximum timestamp to continue retrying the transaction.
|
|
563
|
+
|
|
564
|
+
:type attempts: int
|
|
565
|
+
:param attempts: number of call retries
|
|
566
|
+
"""
|
|
567
|
+
|
|
568
|
+
cause = exc.errors[0]
|
|
569
|
+
now = time.time()
|
|
570
|
+
if now >= deadline:
|
|
571
|
+
raise
|
|
572
|
+
|
|
573
|
+
delay = _get_retry_delay(cause, attempts)
|
|
574
|
+
if delay is not None:
|
|
575
|
+
if now + delay > deadline:
|
|
576
|
+
raise
|
|
577
|
+
|
|
578
|
+
time.sleep(delay)
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def _get_retry_delay(cause, attempts):
|
|
582
|
+
"""Helper for :func:`_delay_until_retry`.
|
|
583
|
+
|
|
584
|
+
:type exc: :class:`grpc.Call`
|
|
585
|
+
:param exc: exception for aborted transaction
|
|
586
|
+
|
|
587
|
+
:rtype: float
|
|
588
|
+
:returns: seconds to wait before retrying the transaction.
|
|
589
|
+
|
|
590
|
+
:type attempts: int
|
|
591
|
+
:param attempts: number of call retries
|
|
592
|
+
"""
|
|
593
|
+
if hasattr(cause, "trailing_metadata"):
|
|
594
|
+
metadata = dict(cause.trailing_metadata())
|
|
595
|
+
else:
|
|
596
|
+
metadata = {}
|
|
597
|
+
retry_info_pb = metadata.get("google.rpc.retryinfo-bin")
|
|
598
|
+
if retry_info_pb is not None:
|
|
599
|
+
retry_info = RetryInfo()
|
|
600
|
+
retry_info.ParseFromString(retry_info_pb)
|
|
601
|
+
nanos = retry_info.retry_delay.nanos
|
|
602
|
+
return retry_info.retry_delay.seconds + nanos / 1.0e9
|
|
603
|
+
|
|
604
|
+
return 2**attempts + random.random()
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
class AtomicCounter:
|
|
608
|
+
def __init__(self, start_value=0):
|
|
609
|
+
self.__lock = threading.Lock()
|
|
610
|
+
self.__value = start_value
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def value(self):
|
|
614
|
+
with self.__lock:
|
|
615
|
+
return self.__value
|
|
616
|
+
|
|
617
|
+
def increment(self, n=1):
|
|
618
|
+
with self.__lock:
|
|
619
|
+
self.__value += n
|
|
620
|
+
return self.__value
|
|
621
|
+
|
|
622
|
+
def __iadd__(self, n):
|
|
623
|
+
"""
|
|
624
|
+
Defines the inplace += operator result.
|
|
625
|
+
"""
|
|
626
|
+
with self.__lock:
|
|
627
|
+
self.__value += n
|
|
628
|
+
return self
|
|
629
|
+
|
|
630
|
+
def __add__(self, n):
|
|
631
|
+
"""
|
|
632
|
+
Defines the result of invoking: value = AtomicCounter + addable
|
|
633
|
+
"""
|
|
634
|
+
with self.__lock:
|
|
635
|
+
n += self.__value
|
|
636
|
+
return n
|
|
637
|
+
|
|
638
|
+
def __radd__(self, n):
|
|
639
|
+
"""
|
|
640
|
+
Defines the result of invoking: value = addable + AtomicCounter
|
|
641
|
+
"""
|
|
642
|
+
return self.__add__(n)
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def _metadata_with_request_id(*args, **kwargs):
|
|
646
|
+
return with_request_id(*args, **kwargs)
|