google-cloud-spanner 3.51.0__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.
Files changed (196) hide show
  1. {google_cloud_spanner-3.51.0/google_cloud_spanner.egg-info → google_cloud_spanner-3.52.0}/PKG-INFO +2 -1
  2. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/gapic_version.py +1 -1
  3. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/gapic_version.py +1 -1
  4. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/connection.py +32 -3
  5. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/cursor.py +39 -3
  6. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parse_utils.py +1 -1
  7. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/transaction_helper.py +1 -1
  8. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/_helpers.py +123 -0
  9. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/_opentelemetry_tracing.py +37 -5
  10. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/batch.py +25 -5
  11. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/database.py +176 -108
  12. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/gapic_version.py +1 -1
  13. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/merged_result_set.py +12 -0
  14. google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/constants.py +63 -0
  15. google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_exporter.py +392 -0
  16. google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_tracer.py +558 -0
  17. google_cloud_spanner-3.52.0/google/cloud/spanner_v1/metrics/metrics_tracer_factory.py +309 -0
  18. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/pool.py +192 -26
  19. google_cloud_spanner-3.52.0/google/cloud/spanner_v1/request_id_header.py +42 -0
  20. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/session.py +124 -97
  21. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/snapshot.py +20 -11
  22. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/mock_spanner.py +62 -14
  23. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/transaction.py +65 -39
  24. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0/google_cloud_spanner.egg-info}/PKG-INFO +2 -1
  25. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/SOURCES.txt +11 -0
  26. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/requires.txt +1 -0
  27. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/setup.py +1 -0
  28. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/_helpers.py +61 -4
  29. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/mockserver_tests/mock_server_test_base.py +52 -0
  30. google_cloud_spanner-3.52.0/tests/mockserver_tests/test_aborted_transaction.py +143 -0
  31. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/mockserver_tests/test_basics.py +22 -0
  32. google_cloud_spanner-3.52.0/tests/mockserver_tests/test_tags.py +206 -0
  33. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/_helpers.py +18 -0
  34. google_cloud_spanner-3.52.0/tests/system/test_observability_options.py +454 -0
  35. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_session_api.py +73 -38
  36. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_parse_utils.py +5 -0
  37. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test__helpers.py +60 -0
  38. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test__opentelemetry_tracing.py +73 -0
  39. google_cloud_spanner-3.52.0/tests/unit/test_atomic_counter.py +78 -0
  40. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_batch.py +54 -7
  41. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_database.py +12 -5
  42. google_cloud_spanner-3.52.0/tests/unit/test_metric_exporter.py +488 -0
  43. google_cloud_spanner-3.52.0/tests/unit/test_metrics_tracer.py +224 -0
  44. google_cloud_spanner-3.52.0/tests/unit/test_metrics_tracer_factory.py +59 -0
  45. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_pool.py +404 -184
  46. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_session.py +56 -5
  47. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_snapshot.py +40 -22
  48. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_spanner.py +4 -0
  49. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_transaction.py +99 -10
  50. google_cloud_spanner-3.51.0/tests/system/test_observability_options.py +0 -134
  51. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/LICENSE +0 -0
  52. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/MANIFEST.in +0 -0
  53. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/README.rst +0 -0
  54. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner.py +0 -0
  55. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/__init__.py +0 -0
  56. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/gapic_metadata.json +0 -0
  57. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/py.typed +0 -0
  58. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/__init__.py +0 -0
  59. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +0 -0
  60. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +0 -0
  61. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/client.py +0 -0
  62. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +0 -0
  63. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +0 -0
  64. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +0 -0
  65. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +0 -0
  66. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +0 -0
  67. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +0 -0
  68. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest_base.py +0 -0
  69. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/__init__.py +0 -0
  70. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/backup.py +0 -0
  71. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/backup_schedule.py +0 -0
  72. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/common.py +0 -0
  73. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +0 -0
  74. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/__init__.py +0 -0
  75. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/gapic_metadata.json +0 -0
  76. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/py.typed +0 -0
  77. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/__init__.py +0 -0
  78. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +0 -0
  79. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +0 -0
  80. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +0 -0
  81. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +0 -0
  82. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +0 -0
  83. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +0 -0
  84. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +0 -0
  85. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +0 -0
  86. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +0 -0
  87. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest_base.py +0 -0
  88. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/__init__.py +0 -0
  89. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/common.py +0 -0
  90. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +0 -0
  91. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/__init__.py +0 -0
  92. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/_helpers.py +0 -0
  93. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/batch_dml_executor.py +0 -0
  94. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/checksum.py +0 -0
  95. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/client_side_statement_executor.py +0 -0
  96. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/client_side_statement_parser.py +0 -0
  97. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/exceptions.py +0 -0
  98. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parsed_statement.py +0 -0
  99. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/parser.py +0 -0
  100. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/partition_helper.py +0 -0
  101. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/types.py +0 -0
  102. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/utils.py +0 -0
  103. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_dbapi/version.py +0 -0
  104. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/__init__.py +0 -0
  105. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/backup.py +0 -0
  106. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/client.py +0 -0
  107. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/data_types.py +0 -0
  108. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/gapic_metadata.json +0 -0
  109. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/instance.py +0 -0
  110. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/keyset.py +0 -0
  111. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/param_types.py +0 -0
  112. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/py.typed +0 -0
  113. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/__init__.py +0 -0
  114. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/__init__.py +0 -0
  115. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/async_client.py +0 -0
  116. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/client.py +0 -0
  117. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/pagers.py +0 -0
  118. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/__init__.py +0 -0
  119. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/base.py +0 -0
  120. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/grpc.py +0 -0
  121. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +0 -0
  122. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/rest.py +0 -0
  123. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/services/spanner/transports/rest_base.py +0 -0
  124. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/streamed.py +0 -0
  125. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/table.py +0 -0
  126. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/__init__.py +0 -0
  127. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/database_test.py +0 -0
  128. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/interceptors.py +0 -0
  129. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/mock_database_admin.py +0 -0
  130. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/spanner_database_admin_pb2_grpc.py +0 -0
  131. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/testing/spanner_pb2_grpc.py +0 -0
  132. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/__init__.py +0 -0
  133. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/commit_response.py +0 -0
  134. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/keys.py +0 -0
  135. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/mutation.py +0 -0
  136. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/query_plan.py +0 -0
  137. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/result_set.py +0 -0
  138. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/spanner.py +0 -0
  139. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/transaction.py +0 -0
  140. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google/cloud/spanner_v1/types/type.py +0 -0
  141. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/dependency_links.txt +0 -0
  142. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/not-zip-safe +0 -0
  143. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/google_cloud_spanner.egg-info/top_level.txt +0 -0
  144. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/setup.cfg +0 -0
  145. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/__init__.py +0 -0
  146. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/_fixtures.py +0 -0
  147. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/mockserver_tests/__init__.py +0 -0
  148. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/__init__.py +0 -0
  149. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/_sample_data.py +0 -0
  150. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/conftest.py +0 -0
  151. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_backup_api.py +0 -0
  152. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_database_api.py +0 -0
  153. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_dbapi.py +0 -0
  154. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_instance_api.py +0 -0
  155. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_streaming_chunking.py +0 -0
  156. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/test_table_api.py +0 -0
  157. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/testdata/descriptors.pb +0 -0
  158. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/testdata/singer.proto +0 -0
  159. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/testdata/singer_pb2.py +0 -0
  160. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/utils/__init__.py +0 -0
  161. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/utils/clear_streaming.py +0 -0
  162. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/utils/populate_streaming.py +0 -0
  163. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/utils/scrub_instances.py +0 -0
  164. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/system/utils/streaming_utils.py +0 -0
  165. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/__init__.py +0 -0
  166. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/__init__.py +0 -0
  167. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_database_v1/__init__.py +0 -0
  168. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py +0 -0
  169. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_instance_v1/__init__.py +0 -0
  170. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py +0 -0
  171. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_v1/__init__.py +0 -0
  172. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/gapic/spanner_v1/test_spanner.py +0 -0
  173. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/__init__.py +0 -0
  174. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test__helpers.py +0 -0
  175. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_batch_dml_executor.py +0 -0
  176. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_checksum.py +0 -0
  177. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_connect.py +0 -0
  178. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_connection.py +0 -0
  179. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_cursor.py +0 -0
  180. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_globals.py +0 -0
  181. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_parser.py +0 -0
  182. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_transaction_helper.py +0 -0
  183. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_types.py +0 -0
  184. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/spanner_dbapi/test_utils.py +0 -0
  185. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/streaming-read-acceptance-test.json +0 -0
  186. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_backup.py +0 -0
  187. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_client.py +0 -0
  188. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_datatypes.py +0 -0
  189. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_instance.py +0 -0
  190. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_keyset.py +0 -0
  191. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_packaging.py +0 -0
  192. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_param_types.py +0 -0
  193. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_streamed.py +0 -0
  194. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/test_table.py +0 -0
  195. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/testdata/singer.proto +0 -0
  196. {google_cloud_spanner-3.51.0 → google_cloud_spanner-3.52.0}/tests/unit/testdata/singer_pb2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-cloud-spanner
3
- Version: 3.51.0
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
 
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "3.51.0" # {x-release-please-version}
16
+ __version__ = "3.52.0" # {x-release-please-version}
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "3.51.0" # {x-release-please-version}
16
+ __version__ = "3.52.0" # {x-release-please-version}
@@ -113,7 +113,7 @@ class Connection:
113
113
  self.request_priority = None
114
114
  self._transaction_begin_marked = False
115
115
  # whether transaction started at Spanner. This means that we had
116
- # made atleast one call to Spanner.
116
+ # made at least one call to Spanner.
117
117
  self._spanner_transaction_started = False
118
118
  self._batch_mode = BatchMode.NONE
119
119
  self._batch_dml_executor: BatchDmlExecutor = None
@@ -261,6 +261,28 @@ class Connection:
261
261
  self.request_priority = None
262
262
  return req_opts
263
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
+
264
286
  @property
265
287
  def staleness(self):
266
288
  """Current read staleness option value of this `Connection`.
@@ -340,6 +362,8 @@ class Connection:
340
362
  if not self.read_only and self._client_transaction_started:
341
363
  if not self._spanner_transaction_started:
342
364
  self._transaction = self._session_checkout().transaction()
365
+ self._transaction.transaction_tag = self.transaction_tag
366
+ self.transaction_tag = None
343
367
  self._snapshot = None
344
368
  self._spanner_transaction_started = True
345
369
  self._transaction.begin()
@@ -458,7 +482,9 @@ class Connection:
458
482
 
459
483
  return self.database.update_ddl(ddl_statements).result()
460
484
 
461
- def run_statement(self, statement: Statement):
485
+ def run_statement(
486
+ self, statement: Statement, request_options: RequestOptions = None
487
+ ):
462
488
  """Run single SQL statement in begun transaction.
463
489
 
464
490
  This method is never used in autocommit mode. In
@@ -472,6 +498,9 @@ class Connection:
472
498
  :param retried: (Optional) Retry the SQL statement if statement
473
499
  execution failed. Defaults to false.
474
500
 
501
+ :type request_options: :class:`RequestOptions`
502
+ :param request_options: Request options to use for this statement.
503
+
475
504
  :rtype: :class:`google.cloud.spanner_v1.streamed.StreamedResultSet`,
476
505
  :class:`google.cloud.spanner_dbapi.checksum.ResultsChecksum`
477
506
  :returns: Streamed result set of the statement and a
@@ -482,7 +511,7 @@ class Connection:
482
511
  statement.sql,
483
512
  statement.params,
484
513
  param_types=statement.param_types,
485
- request_options=self.request_options,
514
+ request_options=request_options or self.request_options,
486
515
  )
487
516
 
488
517
  @check_not_closed
@@ -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.connection.request_options,
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(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.connection.request_options,
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.
@@ -155,7 +155,7 @@ STMT_UPDATING = "UPDATING"
155
155
  STMT_INSERT = "INSERT"
156
156
 
157
157
  # Heuristic for identifying statements that don't need to be run as updates.
158
- RE_NON_UPDATE = re.compile(r"^\W*(SELECT)", re.IGNORECASE)
158
+ RE_NON_UPDATE = re.compile(r"^\W*(SELECT|GRAPH|FROM)", re.IGNORECASE)
159
159
 
160
160
  RE_WITH = re.compile(r"^\s*(WITH)", re.IGNORECASE)
161
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.session import _get_retry_delay
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
@@ -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 = (
@@ -458,11 +464,29 @@ def _metadata_with_prefix(prefix, **kw):
458
464
  return [("google-cloud-resource-prefix", prefix)]
459
465
 
460
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
+
461
484
  def _retry(
462
485
  func,
463
486
  retry_count=5,
464
487
  delay=2,
465
488
  allowed_exceptions=None,
489
+ beforeNextRetry=None,
466
490
  ):
467
491
  """
468
492
  Retry a function with a specified number of retries, delay between retries, and list of allowed exceptions.
@@ -479,6 +503,9 @@ def _retry(
479
503
  """
480
504
  retries = 0
481
505
  while retries <= retry_count:
506
+ if retries > 0 and beforeNextRetry:
507
+ beforeNextRetry(retries, delay)
508
+
482
509
  try:
483
510
  return func()
484
511
  except Exception as exc:
@@ -521,3 +548,99 @@ def _metadata_with_leader_aware_routing(value, **kw):
521
548
  List[Tuple[str, str]]: RPC metadata with leader aware routing header
522
549
  """
523
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)
@@ -56,11 +56,11 @@ def get_tracer(tracer_provider=None):
56
56
 
57
57
 
58
58
  @contextmanager
59
- def trace_call(name, session, extra_attributes=None, observability_options=None):
59
+ def trace_call(name, session=None, extra_attributes=None, observability_options=None):
60
60
  if session:
61
61
  session._last_use_time = datetime.now()
62
62
 
63
- if not HAS_OPENTELEMETRY_INSTALLED or not session:
63
+ if not (HAS_OPENTELEMETRY_INSTALLED and name):
64
64
  # Empty context manager. Users will have to check if the generated value is None or a span
65
65
  yield None
66
66
  return
@@ -72,11 +72,16 @@ def trace_call(name, session, extra_attributes=None, observability_options=None)
72
72
  # on by default.
73
73
  enable_extended_tracing = True
74
74
 
75
+ db_name = ""
76
+ if session and getattr(session, "_database", None):
77
+ db_name = session._database.name
78
+
75
79
  if isinstance(observability_options, dict): # Avoid false positives with mock.Mock
76
80
  tracer_provider = observability_options.get("tracer_provider", None)
77
81
  enable_extended_tracing = observability_options.get(
78
82
  "enable_extended_tracing", enable_extended_tracing
79
83
  )
84
+ db_name = observability_options.get("db_name", db_name)
80
85
 
81
86
  tracer = get_tracer(tracer_provider)
82
87
 
@@ -84,10 +89,14 @@ def trace_call(name, session, extra_attributes=None, observability_options=None)
84
89
  attributes = {
85
90
  "db.type": "spanner",
86
91
  "db.url": SpannerClient.DEFAULT_ENDPOINT,
87
- "db.instance": session._database.name,
92
+ "db.instance": db_name,
88
93
  "net.host.name": SpannerClient.DEFAULT_ENDPOINT,
89
94
  OTEL_SCOPE_NAME: TRACER_NAME,
90
95
  OTEL_SCOPE_VERSION: TRACER_VERSION,
96
+ # Standard GCP attributes for OTel, attributes are used for internal purpose and are subjected to change
97
+ "gcp.client.service": "spanner",
98
+ "gcp.client.version": TRACER_VERSION,
99
+ "gcp.client.repo": "googleapis/python-spanner",
91
100
  }
92
101
 
93
102
  if extra_attributes:
@@ -106,7 +115,30 @@ def trace_call(name, session, extra_attributes=None, observability_options=None)
106
115
  yield span
107
116
  except Exception as error:
108
117
  span.set_status(Status(StatusCode.ERROR, str(error)))
109
- span.record_exception(error)
118
+ # OpenTelemetry-Python imposes invoking span.record_exception on __exit__
119
+ # on any exception. We should file a bug later on with them to only
120
+ # invoke .record_exception if not already invoked, hence we should not
121
+ # invoke .record_exception on our own else we shall have 2 exceptions.
110
122
  raise
111
123
  else:
112
- span.set_status(Status(StatusCode.OK))
124
+ # All spans still have set_status available even if for example
125
+ # NonRecordingSpan doesn't have "_status".
126
+ absent_span_status = getattr(span, "_status", None) is None
127
+ if absent_span_status or span._status.status_code == StatusCode.UNSET:
128
+ # OpenTelemetry-Python only allows a status change
129
+ # if the current code is UNSET or ERROR. At the end
130
+ # of the generator's consumption, only set it to OK
131
+ # it wasn't previously set otherwise.
132
+ # https://github.com/googleapis/python-spanner/issues/1246
133
+ span.set_status(Status(StatusCode.OK))
134
+
135
+
136
+ def get_current_span():
137
+ if not HAS_OPENTELEMETRY_INSTALLED:
138
+ return None
139
+ return trace.get_current_span()
140
+
141
+
142
+ def add_span_event(span, event_name, event_attributes=None):
143
+ if span:
144
+ span.add_event(event_name, event_attributes)
@@ -29,8 +29,12 @@ from google.cloud.spanner_v1._helpers import (
29
29
  from google.cloud.spanner_v1._opentelemetry_tracing import trace_call
30
30
  from google.cloud.spanner_v1 import RequestOptions
31
31
  from google.cloud.spanner_v1._helpers import _retry
32
+ from google.cloud.spanner_v1._helpers import _retry_on_aborted_exception
32
33
  from google.cloud.spanner_v1._helpers import _check_rst_stream_error
33
34
  from google.api_core.exceptions import InternalServerError
35
+ import time
36
+
37
+ DEFAULT_RETRY_TIMEOUT_SECS = 30
34
38
 
35
39
 
36
40
  class _BatchBase(_SessionWrapper):
@@ -70,6 +74,8 @@ class _BatchBase(_SessionWrapper):
70
74
  :param values: Values to be modified.
71
75
  """
72
76
  self._mutations.append(Mutation(insert=_make_write_pb(table, columns, values)))
77
+ # TODO: Decide if we should add a span event per mutation:
78
+ # https://github.com/googleapis/python-spanner/issues/1269
73
79
 
74
80
  def update(self, table, columns, values):
75
81
  """Update one or more existing table rows.
@@ -84,6 +90,8 @@ class _BatchBase(_SessionWrapper):
84
90
  :param values: Values to be modified.
85
91
  """
86
92
  self._mutations.append(Mutation(update=_make_write_pb(table, columns, values)))
93
+ # TODO: Decide if we should add a span event per mutation:
94
+ # https://github.com/googleapis/python-spanner/issues/1269
87
95
 
88
96
  def insert_or_update(self, table, columns, values):
89
97
  """Insert/update one or more table rows.
@@ -100,6 +108,8 @@ class _BatchBase(_SessionWrapper):
100
108
  self._mutations.append(
101
109
  Mutation(insert_or_update=_make_write_pb(table, columns, values))
102
110
  )
111
+ # TODO: Decide if we should add a span event per mutation:
112
+ # https://github.com/googleapis/python-spanner/issues/1269
103
113
 
104
114
  def replace(self, table, columns, values):
105
115
  """Replace one or more table rows.
@@ -114,6 +124,8 @@ class _BatchBase(_SessionWrapper):
114
124
  :param values: Values to be modified.
115
125
  """
116
126
  self._mutations.append(Mutation(replace=_make_write_pb(table, columns, values)))
127
+ # TODO: Decide if we should add a span event per mutation:
128
+ # https://github.com/googleapis/python-spanner/issues/1269
117
129
 
118
130
  def delete(self, table, keyset):
119
131
  """Delete one or more table rows.
@@ -126,6 +138,8 @@ class _BatchBase(_SessionWrapper):
126
138
  """
127
139
  delete = Mutation.Delete(table=table, key_set=keyset._to_pb())
128
140
  self._mutations.append(Mutation(delete=delete))
141
+ # TODO: Decide if we should add a span event per mutation:
142
+ # https://github.com/googleapis/python-spanner/issues/1269
129
143
 
130
144
 
131
145
  class Batch(_BatchBase):
@@ -152,6 +166,7 @@ class Batch(_BatchBase):
152
166
  request_options=None,
153
167
  max_commit_delay=None,
154
168
  exclude_txn_from_change_streams=False,
169
+ **kwargs,
155
170
  ):
156
171
  """Commit mutations to the database.
157
172
 
@@ -207,7 +222,7 @@ class Batch(_BatchBase):
207
222
  )
208
223
  observability_options = getattr(database, "observability_options", None)
209
224
  with trace_call(
210
- "CloudSpanner.Commit",
225
+ f"CloudSpanner.{type(self).__name__}.commit",
211
226
  self._session,
212
227
  trace_attributes,
213
228
  observability_options=observability_options,
@@ -217,9 +232,12 @@ class Batch(_BatchBase):
217
232
  request=request,
218
233
  metadata=metadata,
219
234
  )
220
- response = _retry(
235
+ deadline = time.time() + kwargs.get(
236
+ "timeout_secs", DEFAULT_RETRY_TIMEOUT_SECS
237
+ )
238
+ response = _retry_on_aborted_exception(
221
239
  method,
222
- allowed_exceptions={InternalServerError: _check_rst_stream_error},
240
+ deadline=deadline,
223
241
  )
224
242
  self.committed = response.commit_timestamp
225
243
  self.commit_stats = response.commit_stats
@@ -326,7 +344,7 @@ class MutationGroups(_SessionWrapper):
326
344
  )
327
345
  observability_options = getattr(database, "observability_options", None)
328
346
  with trace_call(
329
- "CloudSpanner.BatchWrite",
347
+ "CloudSpanner.batch_write",
330
348
  self._session,
331
349
  trace_attributes,
332
350
  observability_options=observability_options,
@@ -338,7 +356,9 @@ class MutationGroups(_SessionWrapper):
338
356
  )
339
357
  response = _retry(
340
358
  method,
341
- allowed_exceptions={InternalServerError: _check_rst_stream_error},
359
+ allowed_exceptions={
360
+ InternalServerError: _check_rst_stream_error,
361
+ },
342
362
  )
343
363
  self.committed = True
344
364
  return response