google-cloud-spanner 3.50.1__tar.gz → 3.51.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.51.0}/PKG-INFO +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/connection.py +21 -9
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/parse_utils.py +8 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/_helpers.py +131 -47
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/_opentelemetry_tracing.py +29 -2
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/batch.py +14 -2
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/client.py +21 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/database.py +13 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/gapic_version.py +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/pool.py +7 -2
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/session.py +28 -3
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/snapshot.py +100 -14
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/streamed.py +55 -10
- google_cloud_spanner-3.51.0/google/cloud/spanner_v1/testing/mock_database_admin.py +38 -0
- google_cloud_spanner-3.51.0/google/cloud/spanner_v1/testing/mock_spanner.py +216 -0
- google_cloud_spanner-3.51.0/google/cloud/spanner_v1/testing/spanner_database_admin_pb2_grpc.py +1267 -0
- google_cloud_spanner-3.51.0/google/cloud/spanner_v1/testing/spanner_pb2_grpc.py +882 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/transaction.py +38 -6
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0/google_cloud_spanner.egg-info}/PKG-INFO +1 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google_cloud_spanner.egg-info/SOURCES.txt +9 -0
- google_cloud_spanner-3.51.0/tests/mockserver_tests/mock_server_test_base.py +139 -0
- google_cloud_spanner-3.51.0/tests/mockserver_tests/test_basics.py +87 -0
- google_cloud_spanner-3.51.0/tests/system/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_dbapi.py +45 -2
- google_cloud_spanner-3.51.0/tests/system/test_observability_options.py +134 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_session_api.py +26 -16
- google_cloud_spanner-3.51.0/tests/system/utils/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_connection.py +31 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_parse_utils.py +2 -1
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_pool.py +29 -3
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/LICENSE +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/MANIFEST.in +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/README.rst +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.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.51.0}/google/cloud/spanner_admin_database_v1/services/database_admin/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.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.51.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.51.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.51.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.51.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.51.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.51.0}/google/cloud/spanner_admin_database_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/types/backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/types/backup_schedule.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/types/common.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.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.51.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.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.51.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.51.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.51.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.51.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.51.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.51.0}/google/cloud/spanner_admin_instance_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/types/common.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/_helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/batch_dml_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/checksum.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/client_side_statement_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/client_side_statement_parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/cursor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/exceptions.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/parsed_statement.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/partition_helper.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/transaction_helper.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_dbapi/version.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/data_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/gapic_metadata.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/instance.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/keyset.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/merged_result_set.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/param_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/py.typed +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/async_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/pagers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/grpc.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/rest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/services/spanner/transports/rest_base.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/table.py +0 -0
- {google_cloud_spanner-3.50.1/tests/system → google_cloud_spanner-3.51.0/google/cloud/spanner_v1/testing}/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/testing/database_test.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/testing/interceptors.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/commit_response.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/keys.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/mutation.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/query_plan.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/result_set.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/transaction.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/types/type.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google_cloud_spanner.egg-info/dependency_links.txt +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google_cloud_spanner.egg-info/not-zip-safe +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google_cloud_spanner.egg-info/requires.txt +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google_cloud_spanner.egg-info/top_level.txt +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/setup.cfg +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/setup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/_fixtures.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/_helpers.py +0 -0
- {google_cloud_spanner-3.50.1/tests/system/utils → google_cloud_spanner-3.51.0/tests/mockserver_tests}/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/_helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/_sample_data.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/conftest.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_backup_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_database_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_instance_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_streaming_chunking.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/test_table_api.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/testdata/descriptors.pb +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/testdata/singer.proto +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/testdata/singer_pb2.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/utils/clear_streaming.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/utils/populate_streaming.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/utils/scrub_instances.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/system/utils/streaming_utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_admin_database_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_admin_instance_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_v1/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/gapic/spanner_v1/test_spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/__init__.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test__helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_batch_dml_executor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_checksum.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_connect.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_cursor.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_globals.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_parser.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_transaction_helper.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/spanner_dbapi/test_utils.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/streaming-read-acceptance-test.json +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test__helpers.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test__opentelemetry_tracing.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_backup.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_batch.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_client.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_database.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_datatypes.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_instance.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_keyset.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_packaging.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_param_types.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_session.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_snapshot.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_spanner.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_streamed.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_table.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/test_transaction.py +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/testdata/singer.proto +0 -0
- {google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/tests/unit/testdata/singer_pb2.py +0 -0
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.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 = []
|
|
@@ -117,6 +119,7 @@ class Connection:
|
|
|
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."
|
|
@@ -270,7 +277,7 @@ class Connection:
|
|
|
270
277
|
Args:
|
|
271
278
|
value (dict): Staleness type and value.
|
|
272
279
|
"""
|
|
273
|
-
if self._spanner_transaction_started:
|
|
280
|
+
if self._spanner_transaction_started and value != self._staleness:
|
|
274
281
|
raise ValueError(
|
|
275
282
|
"`staleness` option can't be changed while a transaction is in progress. "
|
|
276
283
|
"Commit or rollback the current transaction and try again."
|
|
@@ -398,9 +405,10 @@ class Connection:
|
|
|
398
405
|
if self.database is None:
|
|
399
406
|
raise ValueError("Database needs to be passed for this operation")
|
|
400
407
|
if not self._client_transaction_started:
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
408
|
+
if not self._ignore_transaction_warnings:
|
|
409
|
+
warnings.warn(
|
|
410
|
+
CLIENT_TRANSACTION_NOT_STARTED_WARNING, UserWarning, stacklevel=2
|
|
411
|
+
)
|
|
404
412
|
return
|
|
405
413
|
|
|
406
414
|
self.run_prior_DDL_statements()
|
|
@@ -418,9 +426,10 @@ class Connection:
|
|
|
418
426
|
This is a no-op if there is no active client transaction.
|
|
419
427
|
"""
|
|
420
428
|
if not self._client_transaction_started:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
429
|
+
if not self._ignore_transaction_warnings:
|
|
430
|
+
warnings.warn(
|
|
431
|
+
CLIENT_TRANSACTION_NOT_STARTED_WARNING, UserWarning, stacklevel=2
|
|
432
|
+
)
|
|
424
433
|
return
|
|
425
434
|
try:
|
|
426
435
|
if self._spanner_transaction_started and not self._read_only:
|
|
@@ -654,6 +663,7 @@ def connect(
|
|
|
654
663
|
user_agent=None,
|
|
655
664
|
client=None,
|
|
656
665
|
route_to_leader_enabled=True,
|
|
666
|
+
**kwargs,
|
|
657
667
|
):
|
|
658
668
|
"""Creates a connection to a Google Cloud Spanner database.
|
|
659
669
|
|
|
@@ -696,6 +706,8 @@ def connect(
|
|
|
696
706
|
disable leader aware routing. Disabling leader aware routing would
|
|
697
707
|
route all requests in RW/PDML transactions to the closest region.
|
|
698
708
|
|
|
709
|
+
**kwargs: Initial value for connection variables.
|
|
710
|
+
|
|
699
711
|
|
|
700
712
|
:rtype: :class:`google.cloud.spanner_dbapi.connection.Connection`
|
|
701
713
|
:returns: Connection object associated with the given Google Cloud Spanner
|
|
@@ -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,
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/_helpers.py
RENAMED
|
@@ -266,66 +266,69 @@ def _parse_value_pb(value_pb, field_type, field_name, column_info=None):
|
|
|
266
266
|
:returns: value extracted from value_pb
|
|
267
267
|
:raises ValueError: if unknown type is passed
|
|
268
268
|
"""
|
|
269
|
+
decoder = _get_type_decoder(field_type, field_name, column_info)
|
|
270
|
+
return _parse_nullable(value_pb, decoder)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _get_type_decoder(field_type, field_name, column_info=None):
|
|
274
|
+
"""Returns a function that converts a Value protobuf to cell data.
|
|
275
|
+
|
|
276
|
+
:type field_type: :class:`~google.cloud.spanner_v1.types.Type`
|
|
277
|
+
:param field_type: type code for the value
|
|
278
|
+
|
|
279
|
+
:type field_name: str
|
|
280
|
+
:param field_name: column name
|
|
281
|
+
|
|
282
|
+
:type column_info: dict
|
|
283
|
+
:param column_info: (Optional) dict of column name and column information.
|
|
284
|
+
An object where column names as keys and custom objects as corresponding
|
|
285
|
+
values for deserialization. It's specifically useful for data types like
|
|
286
|
+
protobuf where deserialization logic is on user-specific code. When provided,
|
|
287
|
+
the custom object enables deserialization of backend-received column data.
|
|
288
|
+
If not provided, data remains serialized as bytes for Proto Messages and
|
|
289
|
+
integer for Proto Enums.
|
|
290
|
+
|
|
291
|
+
:rtype: a function that takes a single protobuf value as an input argument
|
|
292
|
+
:returns: a function that can be used to extract a value from a protobuf value
|
|
293
|
+
:raises ValueError: if unknown type is passed
|
|
294
|
+
"""
|
|
295
|
+
|
|
269
296
|
type_code = field_type.code
|
|
270
|
-
if value_pb.HasField("null_value"):
|
|
271
|
-
return None
|
|
272
297
|
if type_code == TypeCode.STRING:
|
|
273
|
-
return
|
|
298
|
+
return _parse_string
|
|
274
299
|
elif type_code == TypeCode.BYTES:
|
|
275
|
-
return
|
|
300
|
+
return _parse_bytes
|
|
276
301
|
elif type_code == TypeCode.BOOL:
|
|
277
|
-
return
|
|
302
|
+
return _parse_bool
|
|
278
303
|
elif type_code == TypeCode.INT64:
|
|
279
|
-
return
|
|
304
|
+
return _parse_int64
|
|
280
305
|
elif type_code == TypeCode.FLOAT64:
|
|
281
|
-
|
|
282
|
-
return float(value_pb.string_value)
|
|
283
|
-
else:
|
|
284
|
-
return value_pb.number_value
|
|
306
|
+
return _parse_float
|
|
285
307
|
elif type_code == TypeCode.FLOAT32:
|
|
286
|
-
|
|
287
|
-
return float(value_pb.string_value)
|
|
288
|
-
else:
|
|
289
|
-
return value_pb.number_value
|
|
308
|
+
return _parse_float
|
|
290
309
|
elif type_code == TypeCode.DATE:
|
|
291
|
-
return
|
|
310
|
+
return _parse_date
|
|
292
311
|
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
|
-
]
|
|
312
|
+
return _parse_timestamp
|
|
309
313
|
elif type_code == TypeCode.NUMERIC:
|
|
310
|
-
return
|
|
314
|
+
return _parse_numeric
|
|
311
315
|
elif type_code == TypeCode.JSON:
|
|
312
|
-
return
|
|
316
|
+
return _parse_json
|
|
313
317
|
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
|
|
318
|
+
return lambda value_pb: _parse_proto(value_pb, column_info, field_name)
|
|
322
319
|
elif type_code == TypeCode.ENUM:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return
|
|
320
|
+
return lambda value_pb: _parse_proto_enum(value_pb, column_info, field_name)
|
|
321
|
+
elif type_code == TypeCode.ARRAY:
|
|
322
|
+
element_decoder = _get_type_decoder(
|
|
323
|
+
field_type.array_element_type, field_name, column_info
|
|
324
|
+
)
|
|
325
|
+
return lambda value_pb: _parse_array(value_pb, element_decoder)
|
|
326
|
+
elif type_code == TypeCode.STRUCT:
|
|
327
|
+
element_decoders = [
|
|
328
|
+
_get_type_decoder(item_field.type_, field_name, column_info)
|
|
329
|
+
for item_field in field_type.struct_type.fields
|
|
330
|
+
]
|
|
331
|
+
return lambda value_pb: _parse_struct(value_pb, element_decoders)
|
|
329
332
|
else:
|
|
330
333
|
raise ValueError("Unknown type: %s" % (field_type,))
|
|
331
334
|
|
|
@@ -351,6 +354,87 @@ def _parse_list_value_pbs(rows, row_type):
|
|
|
351
354
|
return result
|
|
352
355
|
|
|
353
356
|
|
|
357
|
+
def _parse_string(value_pb) -> str:
|
|
358
|
+
return value_pb.string_value
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _parse_bytes(value_pb):
|
|
362
|
+
return value_pb.string_value.encode("utf8")
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _parse_bool(value_pb) -> bool:
|
|
366
|
+
return value_pb.bool_value
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _parse_int64(value_pb) -> int:
|
|
370
|
+
return int(value_pb.string_value)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def _parse_float(value_pb) -> float:
|
|
374
|
+
if value_pb.HasField("string_value"):
|
|
375
|
+
return float(value_pb.string_value)
|
|
376
|
+
else:
|
|
377
|
+
return value_pb.number_value
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def _parse_date(value_pb):
|
|
381
|
+
return _date_from_iso8601_date(value_pb.string_value)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _parse_timestamp(value_pb):
|
|
385
|
+
DatetimeWithNanoseconds = datetime_helpers.DatetimeWithNanoseconds
|
|
386
|
+
return DatetimeWithNanoseconds.from_rfc3339(value_pb.string_value)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def _parse_numeric(value_pb):
|
|
390
|
+
return decimal.Decimal(value_pb.string_value)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _parse_json(value_pb):
|
|
394
|
+
return JsonObject.from_str(value_pb.string_value)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def _parse_proto(value_pb, column_info, field_name):
|
|
398
|
+
bytes_value = base64.b64decode(value_pb.string_value)
|
|
399
|
+
if column_info is not None and column_info.get(field_name) is not None:
|
|
400
|
+
default_proto_message = column_info.get(field_name)
|
|
401
|
+
if isinstance(default_proto_message, Message):
|
|
402
|
+
proto_message = type(default_proto_message)()
|
|
403
|
+
proto_message.ParseFromString(bytes_value)
|
|
404
|
+
return proto_message
|
|
405
|
+
return bytes_value
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _parse_proto_enum(value_pb, column_info, field_name):
|
|
409
|
+
int_value = int(value_pb.string_value)
|
|
410
|
+
if column_info is not None and column_info.get(field_name) is not None:
|
|
411
|
+
proto_enum = column_info.get(field_name)
|
|
412
|
+
if isinstance(proto_enum, EnumTypeWrapper):
|
|
413
|
+
return proto_enum.Name(int_value)
|
|
414
|
+
return int_value
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _parse_array(value_pb, element_decoder) -> []:
|
|
418
|
+
return [
|
|
419
|
+
_parse_nullable(item_pb, element_decoder)
|
|
420
|
+
for item_pb in value_pb.list_value.values
|
|
421
|
+
]
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _parse_struct(value_pb, element_decoders):
|
|
425
|
+
return [
|
|
426
|
+
_parse_nullable(item_pb, element_decoders[i])
|
|
427
|
+
for (i, item_pb) in enumerate(value_pb.list_value.values)
|
|
428
|
+
]
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _parse_nullable(value_pb, decoder):
|
|
432
|
+
if value_pb.HasField("null_value"):
|
|
433
|
+
return None
|
|
434
|
+
else:
|
|
435
|
+
return decoder(value_pb)
|
|
436
|
+
|
|
437
|
+
|
|
354
438
|
class _SessionWrapper(object):
|
|
355
439
|
"""Base class for objects wrapping a session.
|
|
356
440
|
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"""Manages OpenTelemetry trace creation and handling"""
|
|
16
16
|
|
|
17
17
|
from contextlib import contextmanager
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
import os
|
|
18
20
|
|
|
19
21
|
from google.cloud.spanner_v1 import SpannerClient
|
|
20
22
|
from google.cloud.spanner_v1 import gapic_version
|
|
@@ -33,6 +35,9 @@ except ImportError:
|
|
|
33
35
|
|
|
34
36
|
TRACER_NAME = "cloud.google.com/python/spanner"
|
|
35
37
|
TRACER_VERSION = gapic_version.__version__
|
|
38
|
+
extended_tracing_globally_disabled = (
|
|
39
|
+
os.getenv("SPANNER_ENABLE_EXTENDED_TRACING", "").lower() == "false"
|
|
40
|
+
)
|
|
36
41
|
|
|
37
42
|
|
|
38
43
|
def get_tracer(tracer_provider=None):
|
|
@@ -51,13 +56,29 @@ def get_tracer(tracer_provider=None):
|
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
@contextmanager
|
|
54
|
-
def trace_call(name, session, extra_attributes=None):
|
|
59
|
+
def trace_call(name, session, extra_attributes=None, observability_options=None):
|
|
60
|
+
if session:
|
|
61
|
+
session._last_use_time = datetime.now()
|
|
62
|
+
|
|
55
63
|
if not HAS_OPENTELEMETRY_INSTALLED or not session:
|
|
56
64
|
# Empty context manager. Users will have to check if the generated value is None or a span
|
|
57
65
|
yield None
|
|
58
66
|
return
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
tracer_provider = None
|
|
69
|
+
|
|
70
|
+
# By default enable_extended_tracing=True because in a bid to minimize
|
|
71
|
+
# breaking changes and preserve legacy behavior, we are keeping it turned
|
|
72
|
+
# on by default.
|
|
73
|
+
enable_extended_tracing = True
|
|
74
|
+
|
|
75
|
+
if isinstance(observability_options, dict): # Avoid false positives with mock.Mock
|
|
76
|
+
tracer_provider = observability_options.get("tracer_provider", None)
|
|
77
|
+
enable_extended_tracing = observability_options.get(
|
|
78
|
+
"enable_extended_tracing", enable_extended_tracing
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
tracer = get_tracer(tracer_provider)
|
|
61
82
|
|
|
62
83
|
# Set base attributes that we know for every trace created
|
|
63
84
|
attributes = {
|
|
@@ -72,6 +93,12 @@ def trace_call(name, session, extra_attributes=None):
|
|
|
72
93
|
if extra_attributes:
|
|
73
94
|
attributes.update(extra_attributes)
|
|
74
95
|
|
|
96
|
+
if extended_tracing_globally_disabled:
|
|
97
|
+
enable_extended_tracing = False
|
|
98
|
+
|
|
99
|
+
if not enable_extended_tracing:
|
|
100
|
+
attributes.pop("db.statement", False)
|
|
101
|
+
|
|
75
102
|
with tracer.start_as_current_span(
|
|
76
103
|
name, kind=trace.SpanKind.CLIENT, attributes=attributes
|
|
77
104
|
) as span:
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/batch.py
RENAMED
|
@@ -205,7 +205,13 @@ class Batch(_BatchBase):
|
|
|
205
205
|
max_commit_delay=max_commit_delay,
|
|
206
206
|
request_options=request_options,
|
|
207
207
|
)
|
|
208
|
-
|
|
208
|
+
observability_options = getattr(database, "observability_options", None)
|
|
209
|
+
with trace_call(
|
|
210
|
+
"CloudSpanner.Commit",
|
|
211
|
+
self._session,
|
|
212
|
+
trace_attributes,
|
|
213
|
+
observability_options=observability_options,
|
|
214
|
+
):
|
|
209
215
|
method = functools.partial(
|
|
210
216
|
api.commit,
|
|
211
217
|
request=request,
|
|
@@ -318,7 +324,13 @@ class MutationGroups(_SessionWrapper):
|
|
|
318
324
|
request_options=request_options,
|
|
319
325
|
exclude_txn_from_change_streams=exclude_txn_from_change_streams,
|
|
320
326
|
)
|
|
321
|
-
|
|
327
|
+
observability_options = getattr(database, "observability_options", None)
|
|
328
|
+
with trace_call(
|
|
329
|
+
"CloudSpanner.BatchWrite",
|
|
330
|
+
self._session,
|
|
331
|
+
trace_attributes,
|
|
332
|
+
observability_options=observability_options,
|
|
333
|
+
):
|
|
322
334
|
method = functools.partial(
|
|
323
335
|
api.batch_write,
|
|
324
336
|
request=request,
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/client.py
RENAMED
|
@@ -126,6 +126,16 @@ class Client(ClientWithProject):
|
|
|
126
126
|
for all ReadRequests and ExecuteSqlRequests that indicates which replicas
|
|
127
127
|
or regions should be used for non-transactional reads or queries.
|
|
128
128
|
|
|
129
|
+
:type observability_options: dict (str -> any) or None
|
|
130
|
+
:param observability_options: (Optional) the configuration to control
|
|
131
|
+
the tracer's behavior.
|
|
132
|
+
tracer_provider is the injected tracer provider
|
|
133
|
+
enable_extended_tracing: :type:boolean when set to true will allow for
|
|
134
|
+
spans that issue SQL statements to be annotated with SQL.
|
|
135
|
+
Default `True`, please set it to `False` to turn it off
|
|
136
|
+
or you can use the environment variable `SPANNER_ENABLE_EXTENDED_TRACING=<boolean>`
|
|
137
|
+
to control it.
|
|
138
|
+
|
|
129
139
|
:raises: :class:`ValueError <exceptions.ValueError>` if both ``read_only``
|
|
130
140
|
and ``admin`` are :data:`True`
|
|
131
141
|
"""
|
|
@@ -146,6 +156,7 @@ class Client(ClientWithProject):
|
|
|
146
156
|
query_options=None,
|
|
147
157
|
route_to_leader_enabled=True,
|
|
148
158
|
directed_read_options=None,
|
|
159
|
+
observability_options=None,
|
|
149
160
|
):
|
|
150
161
|
self._emulator_host = _get_spanner_emulator_host()
|
|
151
162
|
|
|
@@ -187,6 +198,7 @@ class Client(ClientWithProject):
|
|
|
187
198
|
|
|
188
199
|
self._route_to_leader_enabled = route_to_leader_enabled
|
|
189
200
|
self._directed_read_options = directed_read_options
|
|
201
|
+
self._observability_options = observability_options
|
|
190
202
|
|
|
191
203
|
@property
|
|
192
204
|
def credentials(self):
|
|
@@ -268,6 +280,15 @@ class Client(ClientWithProject):
|
|
|
268
280
|
"""
|
|
269
281
|
return self._route_to_leader_enabled
|
|
270
282
|
|
|
283
|
+
@property
|
|
284
|
+
def observability_options(self):
|
|
285
|
+
"""Getter for observability_options.
|
|
286
|
+
|
|
287
|
+
:rtype: dict
|
|
288
|
+
:returns: The configured observability_options if set.
|
|
289
|
+
"""
|
|
290
|
+
return self._observability_options
|
|
291
|
+
|
|
271
292
|
@property
|
|
272
293
|
def directed_read_options(self):
|
|
273
294
|
"""Getter for directed_read_options.
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/database.py
RENAMED
|
@@ -142,7 +142,7 @@ class Database(object):
|
|
|
142
142
|
statements in 'ddl_statements' above.
|
|
143
143
|
"""
|
|
144
144
|
|
|
145
|
-
_spanner_api = None
|
|
145
|
+
_spanner_api: SpannerClient = None
|
|
146
146
|
|
|
147
147
|
def __init__(
|
|
148
148
|
self,
|
|
@@ -718,6 +718,7 @@ class Database(object):
|
|
|
718
718
|
method=method,
|
|
719
719
|
request=request,
|
|
720
720
|
transaction_selector=txn_selector,
|
|
721
|
+
observability_options=self.observability_options,
|
|
721
722
|
)
|
|
722
723
|
|
|
723
724
|
result_set = StreamedResultSet(iterator)
|
|
@@ -1106,6 +1107,17 @@ class Database(object):
|
|
|
1106
1107
|
response = api.set_iam_policy(request=request, metadata=metadata)
|
|
1107
1108
|
return response
|
|
1108
1109
|
|
|
1110
|
+
@property
|
|
1111
|
+
def observability_options(self):
|
|
1112
|
+
"""
|
|
1113
|
+
Returns the observability options that you set when creating
|
|
1114
|
+
the SpannerClient.
|
|
1115
|
+
"""
|
|
1116
|
+
if not (self._instance and self._instance._client):
|
|
1117
|
+
return None
|
|
1118
|
+
|
|
1119
|
+
return getattr(self._instance._client, "observability_options", None)
|
|
1120
|
+
|
|
1109
1121
|
|
|
1110
1122
|
class BatchCheckout(object):
|
|
1111
1123
|
"""Context manager for using a batch from a database.
|
|
@@ -145,7 +145,8 @@ class FixedSizePool(AbstractSessionPool):
|
|
|
145
145
|
- Pre-allocates / creates a fixed number of sessions.
|
|
146
146
|
|
|
147
147
|
- "Pings" existing sessions via :meth:`session.exists` before returning
|
|
148
|
-
|
|
148
|
+
sessions that have not been used for more than 55 minutes and replaces
|
|
149
|
+
expired sessions.
|
|
149
150
|
|
|
150
151
|
- Blocks, with a timeout, when :meth:`get` is called on an empty pool.
|
|
151
152
|
Raises after timing out.
|
|
@@ -171,6 +172,7 @@ class FixedSizePool(AbstractSessionPool):
|
|
|
171
172
|
|
|
172
173
|
DEFAULT_SIZE = 10
|
|
173
174
|
DEFAULT_TIMEOUT = 10
|
|
175
|
+
DEFAULT_MAX_AGE_MINUTES = 55
|
|
174
176
|
|
|
175
177
|
def __init__(
|
|
176
178
|
self,
|
|
@@ -178,11 +180,13 @@ class FixedSizePool(AbstractSessionPool):
|
|
|
178
180
|
default_timeout=DEFAULT_TIMEOUT,
|
|
179
181
|
labels=None,
|
|
180
182
|
database_role=None,
|
|
183
|
+
max_age_minutes=DEFAULT_MAX_AGE_MINUTES,
|
|
181
184
|
):
|
|
182
185
|
super(FixedSizePool, self).__init__(labels=labels, database_role=database_role)
|
|
183
186
|
self.size = size
|
|
184
187
|
self.default_timeout = default_timeout
|
|
185
188
|
self._sessions = queue.LifoQueue(size)
|
|
189
|
+
self._max_age = datetime.timedelta(minutes=max_age_minutes)
|
|
186
190
|
|
|
187
191
|
def bind(self, database):
|
|
188
192
|
"""Associate the pool with a database.
|
|
@@ -230,8 +234,9 @@ class FixedSizePool(AbstractSessionPool):
|
|
|
230
234
|
timeout = self.default_timeout
|
|
231
235
|
|
|
232
236
|
session = self._sessions.get(block=True, timeout=timeout)
|
|
237
|
+
age = _NOW() - session.last_use_time
|
|
233
238
|
|
|
234
|
-
if not session.exists():
|
|
239
|
+
if age >= self._max_age and not session.exists():
|
|
235
240
|
session = self._database.session()
|
|
236
241
|
session.create()
|
|
237
242
|
|
{google_cloud_spanner-3.50.1 → google_cloud_spanner-3.51.0}/google/cloud/spanner_v1/session.py
RENAMED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from functools import total_ordering
|
|
18
18
|
import random
|
|
19
19
|
import time
|
|
20
|
+
from datetime import datetime
|
|
20
21
|
|
|
21
22
|
from google.api_core.exceptions import Aborted
|
|
22
23
|
from google.api_core.exceptions import GoogleAPICallError
|
|
@@ -69,6 +70,7 @@ class Session(object):
|
|
|
69
70
|
labels = {}
|
|
70
71
|
self._labels = labels
|
|
71
72
|
self._database_role = database_role
|
|
73
|
+
self._last_use_time = datetime.utcnow()
|
|
72
74
|
|
|
73
75
|
def __lt__(self, other):
|
|
74
76
|
return self._session_id < other._session_id
|
|
@@ -78,6 +80,14 @@ class Session(object):
|
|
|
78
80
|
"""Read-only ID, set by the back-end during :meth:`create`."""
|
|
79
81
|
return self._session_id
|
|
80
82
|
|
|
83
|
+
@property
|
|
84
|
+
def last_use_time(self):
|
|
85
|
+
""" "Approximate last use time of this session
|
|
86
|
+
|
|
87
|
+
:rtype: datetime
|
|
88
|
+
:returns: the approximate last use time of this session"""
|
|
89
|
+
return self._last_use_time
|
|
90
|
+
|
|
81
91
|
@property
|
|
82
92
|
def database_role(self):
|
|
83
93
|
"""User-assigned database-role for the session.
|
|
@@ -142,7 +152,13 @@ class Session(object):
|
|
|
142
152
|
if self._labels:
|
|
143
153
|
request.session.labels = self._labels
|
|
144
154
|
|
|
145
|
-
|
|
155
|
+
observability_options = getattr(self._database, "observability_options", None)
|
|
156
|
+
with trace_call(
|
|
157
|
+
"CloudSpanner.CreateSession",
|
|
158
|
+
self,
|
|
159
|
+
self._labels,
|
|
160
|
+
observability_options=observability_options,
|
|
161
|
+
):
|
|
146
162
|
session_pb = api.create_session(
|
|
147
163
|
request=request,
|
|
148
164
|
metadata=metadata,
|
|
@@ -169,7 +185,10 @@ class Session(object):
|
|
|
169
185
|
)
|
|
170
186
|
)
|
|
171
187
|
|
|
172
|
-
|
|
188
|
+
observability_options = getattr(self._database, "observability_options", None)
|
|
189
|
+
with trace_call(
|
|
190
|
+
"CloudSpanner.GetSession", self, observability_options=observability_options
|
|
191
|
+
) as span:
|
|
173
192
|
try:
|
|
174
193
|
api.get_session(name=self.name, metadata=metadata)
|
|
175
194
|
if span:
|
|
@@ -194,7 +213,12 @@ class Session(object):
|
|
|
194
213
|
raise ValueError("Session ID not set by back-end")
|
|
195
214
|
api = self._database.spanner_api
|
|
196
215
|
metadata = _metadata_with_prefix(self._database.name)
|
|
197
|
-
|
|
216
|
+
observability_options = getattr(self._database, "observability_options", None)
|
|
217
|
+
with trace_call(
|
|
218
|
+
"CloudSpanner.DeleteSession",
|
|
219
|
+
self,
|
|
220
|
+
observability_options=observability_options,
|
|
221
|
+
):
|
|
198
222
|
api.delete_session(name=self.name, metadata=metadata)
|
|
199
223
|
|
|
200
224
|
def ping(self):
|
|
@@ -208,6 +232,7 @@ class Session(object):
|
|
|
208
232
|
metadata = _metadata_with_prefix(self._database.name)
|
|
209
233
|
request = ExecuteSqlRequest(session=self.name, sql="SELECT 1")
|
|
210
234
|
api.execute_sql(request=request, metadata=metadata)
|
|
235
|
+
self._last_use_time = datetime.now()
|
|
211
236
|
|
|
212
237
|
def snapshot(self, **kw):
|
|
213
238
|
"""Create a snapshot to perform a set of reads with shared staleness.
|