google-cloud-bigtable 2.46.0__tar.gz → 2.48.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 (267) hide show
  1. {google_cloud_bigtable-2.46.0/google_cloud_bigtable.egg-info → google_cloud_bigtable-2.48.0}/PKG-INFO +1 -1
  2. google_cloud_bigtable-2.48.0/google/cloud/bigtable/batcher.py +224 -0
  3. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/_mutate_rows.py +1 -1
  4. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/mutations_batcher.py +68 -18
  5. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_helpers.py +66 -1
  6. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/_mutate_rows.py +1 -1
  7. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/mutations_batcher.py +57 -18
  8. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/exceptions.py +14 -9
  9. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/gapic_version.py +1 -1
  10. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/table.py +12 -41
  11. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin/gapic_version.py +1 -1
  12. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/gapic_version.py +1 -1
  13. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/table.py +33 -0
  14. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/gapic_version.py +1 -1
  15. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0/google_cloud_bigtable.egg-info}/PKG-INFO +1 -1
  16. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/data/test_system_async.py +36 -0
  17. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/data/test_system_autogen.py +29 -0
  18. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/test_data_api.py +131 -0
  19. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test_mutations_batcher.py +126 -2
  20. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test_mutations_batcher.py +123 -2
  21. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test__helpers.py +88 -0
  22. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_admin_v2/test_bigtable_table_admin.py +3 -0
  23. google_cloud_bigtable-2.48.0/tests/unit/v2_client/test_batcher.py +331 -0
  24. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_table.py +2 -2
  25. google_cloud_bigtable-2.46.0/google/cloud/bigtable/batcher.py +0 -462
  26. google_cloud_bigtable-2.46.0/tests/unit/v2_client/test_batcher.py +0 -350
  27. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/LICENSE +0 -0
  28. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/MANIFEST.in +0 -0
  29. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/README.rst +0 -0
  30. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/__init__.py +0 -0
  31. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/app_profile.py +0 -0
  32. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/backup.py +0 -0
  33. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/client.py +0 -0
  34. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/cluster.py +0 -0
  35. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/column_family.py +0 -0
  36. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/__init__.py +0 -0
  37. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/__init__.py +0 -0
  38. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/_read_rows.py +0 -0
  39. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/_swappable_channel.py +0 -0
  40. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/client.py +0 -0
  41. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_async/metrics_interceptor.py +0 -0
  42. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_cross_sync/__init__.py +0 -0
  43. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_cross_sync/_decorators.py +0 -0
  44. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_cross_sync/_mapping_meta.py +0 -0
  45. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_cross_sync/cross_sync.py +0 -0
  46. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/__init__.py +0 -0
  47. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/data_model.py +0 -0
  48. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/handlers/_base.py +0 -0
  49. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/handlers/gcp_exporter.py +0 -0
  50. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/handlers/opentelemetry.py +0 -0
  51. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/metrics_controller.py +0 -0
  52. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_metrics/tracked_retry.py +0 -0
  53. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/_read_rows.py +0 -0
  54. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/_swappable_channel.py +0 -0
  55. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/client.py +0 -0
  56. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/_sync_autogen/metrics_interceptor.py +0 -0
  57. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/__init__.py +0 -0
  58. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_async/__init__.py +0 -0
  59. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_async/execute_query_iterator.py +0 -0
  60. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_byte_cursor.py +0 -0
  61. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_checksum.py +0 -0
  62. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_parameters_formatting.py +0 -0
  63. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_query_result_parsing_utils.py +0 -0
  64. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_reader.py +0 -0
  65. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/_sync_autogen/execute_query_iterator.py +0 -0
  66. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/metadata.py +0 -0
  67. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/execute_query/values.py +0 -0
  68. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/mutations.py +0 -0
  69. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/read_modify_write_rules.py +0 -0
  70. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/read_rows_query.py +0 -0
  71. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/row.py +0 -0
  72. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/data/row_filters.py +0 -0
  73. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/encryption_info.py +0 -0
  74. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/enums.py +0 -0
  75. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/error.py +0 -0
  76. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/helpers.py +0 -0
  77. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/instance.py +0 -0
  78. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/policy.py +0 -0
  79. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/py.typed +0 -0
  80. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/row.py +0 -0
  81. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/row_data.py +0 -0
  82. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/row_filters.py +0 -0
  83. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable/row_set.py +0 -0
  84. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin/__init__.py +0 -0
  85. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin/py.typed +0 -0
  86. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/__init__.py +0 -0
  87. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/_compat.py +0 -0
  88. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/gapic_metadata.json +0 -0
  89. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/__init__.py +0 -0
  90. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/services/__init__.py +0 -0
  91. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/services/bigtable_table_admin/__init__.py +0 -0
  92. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/services/bigtable_table_admin/async_client.py +0 -0
  93. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/services/bigtable_table_admin/client.py +0 -0
  94. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/__init__.py +0 -0
  95. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/async_consistency.py +0 -0
  96. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/async_restore_table.py +0 -0
  97. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/consistency.py +0 -0
  98. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/restore_table.py +0 -0
  99. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/overlay/types/wait_for_consistency_request.py +0 -0
  100. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/py.typed +0 -0
  101. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/__init__.py +0 -0
  102. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/__init__.py +0 -0
  103. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/async_client.py +0 -0
  104. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/client.py +0 -0
  105. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/pagers.py +0 -0
  106. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/__init__.py +0 -0
  107. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/base.py +0 -0
  108. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/grpc.py +0 -0
  109. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/grpc_asyncio.py +0 -0
  110. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/rest.py +0 -0
  111. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_instance_admin/transports/rest_base.py +0 -0
  112. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/__init__.py +0 -0
  113. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/async_client.py +0 -0
  114. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/client.py +0 -0
  115. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/pagers.py +0 -0
  116. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/__init__.py +0 -0
  117. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/base.py +0 -0
  118. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/grpc.py +0 -0
  119. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/grpc_asyncio.py +0 -0
  120. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/rest.py +0 -0
  121. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/services/bigtable_table_admin/transports/rest_base.py +0 -0
  122. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/__init__.py +0 -0
  123. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/bigtable_instance_admin.py +0 -0
  124. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/bigtable_table_admin.py +0 -0
  125. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/common.py +0 -0
  126. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/instance.py +0 -0
  127. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/types/types.py +0 -0
  128. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/utils/__init__.py +0 -0
  129. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_admin_v2/utils/oneof_message.py +0 -0
  130. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/__init__.py +0 -0
  131. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/_compat.py +0 -0
  132. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/gapic_metadata.json +0 -0
  133. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/py.typed +0 -0
  134. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/__init__.py +0 -0
  135. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/__init__.py +0 -0
  136. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/async_client.py +0 -0
  137. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/client.py +0 -0
  138. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/__init__.py +0 -0
  139. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/base.py +0 -0
  140. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/grpc.py +0 -0
  141. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/grpc_asyncio.py +0 -0
  142. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/rest.py +0 -0
  143. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/services/bigtable/transports/rest_base.py +0 -0
  144. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/__init__.py +0 -0
  145. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/bigtable.py +0 -0
  146. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/data.py +0 -0
  147. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/feature_flags.py +0 -0
  148. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/peer_info.py +0 -0
  149. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/request_stats.py +0 -0
  150. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/response_params.py +0 -0
  151. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/session.py +0 -0
  152. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google/cloud/bigtable_v2/types/types.py +0 -0
  153. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google_cloud_bigtable.egg-info/SOURCES.txt +0 -0
  154. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google_cloud_bigtable.egg-info/dependency_links.txt +0 -0
  155. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google_cloud_bigtable.egg-info/not-zip-safe +0 -0
  156. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google_cloud_bigtable.egg-info/requires.txt +0 -0
  157. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/google_cloud_bigtable.egg-info/top_level.txt +0 -0
  158. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/setup.cfg +0 -0
  159. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/setup.py +0 -0
  160. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/__init__.py +0 -0
  161. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/__init__.py +0 -0
  162. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/admin_overlay/__init__.py +0 -0
  163. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/admin_overlay/conftest.py +0 -0
  164. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/admin_overlay/test_system_async.py +0 -0
  165. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/admin_overlay/test_system_autogen.py +0 -0
  166. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/conftest.py +0 -0
  167. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cases/async_to_sync.yaml +0 -0
  168. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cases/cross_sync_files.yaml +0 -0
  169. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cases/rm_aio.yaml +0 -0
  170. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cases/strip_async_conditional_branches.yaml +0 -0
  171. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cases/symbol_replacer.yaml +0 -0
  172. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/cross_sync/test_cross_sync_e2e.py +0 -0
  173. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/data/__init__.py +0 -0
  174. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/data/test_metrics_async.py +0 -0
  175. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/data/test_metrics_autogen.py +0 -0
  176. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/utils.py +0 -0
  177. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/__init__.py +0 -0
  178. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/_helpers.py +0 -0
  179. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/conftest.py +0 -0
  180. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/test_instance_admin.py +0 -0
  181. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/system/v2_client/test_table_admin.py +0 -0
  182. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/__init__.py +0 -0
  183. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/my_oneof_message.py +0 -0
  184. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_admin_packaging.py +0 -0
  185. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_async_client.py +0 -0
  186. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_async_consistency.py +0 -0
  187. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_async_restore_table.py +0 -0
  188. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_client.py +0 -0
  189. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_consistency.py +0 -0
  190. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_oneof_message.py +0 -0
  191. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/admin_overlay/test_restore_table.py +0 -0
  192. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/conftest.py +0 -0
  193. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/__init__.py +0 -0
  194. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/__init__.py +0 -0
  195. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test__mutate_rows.py +0 -0
  196. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test__read_rows.py +0 -0
  197. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test__swappable_channel.py +0 -0
  198. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test_client.py +0 -0
  199. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test_metrics_interceptor.py +0 -0
  200. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_async/test_read_rows_acceptance.py +0 -0
  201. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_cross_sync/test_cross_sync.py +0 -0
  202. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_cross_sync/test_cross_sync_decorators.py +0 -0
  203. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/__init__.py +0 -0
  204. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/test_data_model.py +0 -0
  205. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/test_gcp_exporter_handler.py +0 -0
  206. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/test_metrics_controller.py +0 -0
  207. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/test_opentelemetry_handler.py +0 -0
  208. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_metrics/test_tracked_retry.py +0 -0
  209. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/__init__.py +0 -0
  210. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test__mutate_rows.py +0 -0
  211. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test__read_rows.py +0 -0
  212. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test__swappable_channel.py +0 -0
  213. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test_client.py +0 -0
  214. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test_metrics_interceptor.py +0 -0
  215. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/_sync_autogen/test_read_rows_acceptance.py +0 -0
  216. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/__init__.py +0 -0
  217. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/_async/__init__.py +0 -0
  218. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/_async/test_query_iterator.py +0 -0
  219. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/_sync_autogen/__init__.py +0 -0
  220. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/_sync_autogen/test_query_iterator.py +0 -0
  221. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/resources/README.md +0 -0
  222. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/resources/__init__.py +0 -0
  223. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/resources/descriptors.pb +0 -0
  224. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/resources/singer.proto +0 -0
  225. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/resources/singer_pb2.py +0 -0
  226. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/sql_helpers.py +0 -0
  227. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_byte_cursor.py +0 -0
  228. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_checksum.py +0 -0
  229. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_execute_query_parameters_parsing.py +0 -0
  230. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_metadata.py +0 -0
  231. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_query_result_parsing_utils.py +0 -0
  232. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/execute_query/test_query_result_row_reader.py +0 -0
  233. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/read-rows-acceptance-test.json +0 -0
  234. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_exceptions.py +0 -0
  235. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_helpers.py +0 -0
  236. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_mutations.py +0 -0
  237. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_read_modify_write_rules.py +0 -0
  238. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_read_rows_query.py +0 -0
  239. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_row.py +0 -0
  240. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_row_filters.py +0 -0
  241. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/data/test_sync_up_to_date.py +0 -0
  242. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/__init__.py +0 -0
  243. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_admin_v2/__init__.py +0 -0
  244. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_admin_v2/test_bigtable_instance_admin.py +0 -0
  245. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_admin_v2/test_compat.py +0 -0
  246. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_v2/__init__.py +0 -0
  247. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_v2/test_bigtable.py +0 -0
  248. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/gapic/bigtable_v2/test_compat.py +0 -0
  249. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/test_packaging.py +0 -0
  250. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/test_sql_routing_parameters.py +0 -0
  251. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/__init__.py +0 -0
  252. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/_testing.py +0 -0
  253. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/read-rows-acceptance-test.json +0 -0
  254. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_app_profile.py +0 -0
  255. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_backup.py +0 -0
  256. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_client.py +0 -0
  257. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_cluster.py +0 -0
  258. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_column_family.py +0 -0
  259. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_encryption_info.py +0 -0
  260. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_error.py +0 -0
  261. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_instance.py +0 -0
  262. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_policy.py +0 -0
  263. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_row.py +0 -0
  264. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_row_data.py +0 -0
  265. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_row_filters.py +0 -0
  266. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_row_merger.py +0 -0
  267. {google_cloud_bigtable-2.46.0 → google_cloud_bigtable-2.48.0}/tests/unit/v2_client/test_row_set.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-bigtable
3
- Version: 2.46.0
3
+ Version: 2.48.0
4
4
  Summary: Google Cloud Bigtable API client library
5
5
  Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-bigtable
6
6
  Author: Google LLC
@@ -0,0 +1,224 @@
1
+ # Copyright 2018 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ """User friendly container for Google Cloud Bigtable MutationBatcher."""
17
+
18
+ import atexit
19
+ import queue
20
+
21
+ from google.api_core import exceptions as core_exceptions
22
+
23
+ from google.cloud.bigtable.data.exceptions import MutationsExceptionGroup
24
+ from google.cloud.bigtable.data.mutations import RowMutationEntry
25
+
26
+ FLUSH_COUNT = 100 # after this many elements, send out the batch
27
+
28
+ MAX_MUTATION_SIZE = 20 * 1024 * 1024 # 20MB # after this many bytes, send out the batch
29
+
30
+ MAX_OUTSTANDING_BYTES = 100 * 1024 * 1024 # 100MB # max inflight byte size.
31
+
32
+ MAX_OUTSTANDING_ELEMENTS = 100000 # max inflight mutations.
33
+
34
+
35
+ class MutationsBatchError(Exception):
36
+ """Error in the batch request"""
37
+
38
+ def __init__(self, message, exc):
39
+ self.exc = exc
40
+ self.message = message
41
+ super().__init__(self.message)
42
+
43
+
44
+ class MutationsBatcher(object):
45
+ """A MutationsBatcher is used in batch cases where the number of mutations
46
+ is large or unknown. It will store :class:`DirectRow` in memory until one of the
47
+ size limits is reached, the ``flush_interval`` timer fires, or an explicit call
48
+ to :func:`flush()` is performed. When a flush event occurs, the :class:`DirectRow`
49
+ in memory will be sent to Cloud Bigtable. Batching mutations is more efficient than
50
+ sending individual requests.
51
+
52
+ This class is not suited for usage in systems where each mutation
53
+ must be guaranteed to be sent, since calling :func:`mutate()` may only
54
+ result in an in-memory change. Rows are sent to the service when a size
55
+ limit is reached, when the ``flush_interval`` timer fires, when :func:`flush()`
56
+ is called explicitly, or when the batcher is closed (:func:`close()` is also
57
+ registered to run at interpreter exit). As a result, if the process
58
+ terminates abruptly -- e.g. a crash, ``SIGKILL``, or ``os._exit`` where the
59
+ ``atexit`` handler never runs -- any :class:`DirectRow` still buffered in
60
+ memory is silently dropped and never sent, even after :func:`mutate()`
61
+ returned.
62
+
63
+ Note on thread safety: The same :class:`MutationBatcher` cannot be shared by multiple end-user threads.
64
+
65
+ .. warning::
66
+
67
+ If using ``MutationsBatcher``, please ensure you are using
68
+ ``google-cloud-bigtable >= 2.42.0``, or consider migrating to the
69
+ batcher provided by the synchronous/asynchronous data client
70
+ (:mod:`google.cloud.bigtable.data`).
71
+
72
+ :type table: class
73
+ :param table: class:`~google.cloud.bigtable.table.Table`.
74
+
75
+ :type flush_count: int
76
+ :param flush_count: (Optional) Max number of rows to flush. If it
77
+ reaches the max number of rows it calls finish_batch() to mutate the
78
+ current row batch. Default is FLUSH_COUNT (1000 rows).
79
+
80
+ :type max_row_bytes: int
81
+ :param max_row_bytes: (Optional) Max number of row mutations size to
82
+ flush. If it reaches the max number of row mutations size it calls
83
+ finish_batch() to mutate the current row batch. Default is MAX_ROW_BYTES
84
+ (5 MB).
85
+
86
+ :type flush_interval: float
87
+ :param flush_interval: (Optional) Automatically flush every flush_interval seconds.
88
+ If None or <= 0, no time-based flushing is performed. Default is 1 second.
89
+
90
+ :type batch_completed_callback: Callable[list:[`~google.rpc.status_pb2.Status`]] = None
91
+ :param batch_completed_callback: (Optional) A callable for handling responses
92
+ after the current batch is sent. The callable function expect a list of grpc
93
+ Status.
94
+ """
95
+
96
+ def __init__(
97
+ self,
98
+ table,
99
+ flush_count=FLUSH_COUNT,
100
+ max_row_bytes=MAX_MUTATION_SIZE,
101
+ flush_interval=1,
102
+ batch_completed_callback=None,
103
+ ):
104
+ self.table = table
105
+ self._batcher_kwargs = {
106
+ "flush_interval": flush_interval,
107
+ "flush_limit_mutation_count": flush_count,
108
+ "flush_limit_bytes": max_row_bytes,
109
+ "flow_control_max_mutation_count": MAX_OUTSTANDING_ELEMENTS,
110
+ "flow_control_max_bytes": MAX_OUTSTANDING_BYTES,
111
+ }
112
+ self._user_batch_completed_callback = batch_completed_callback
113
+ self._init_batcher()
114
+ atexit.register(self.close)
115
+ self._exceptions: queue.Queue = queue.Queue()
116
+
117
+ @property
118
+ def flush_count(self):
119
+ return self._batcher._flush_limit_count
120
+
121
+ @property
122
+ def max_row_bytes(self):
123
+ return self._batcher._flush_limit_bytes
124
+
125
+ def _init_batcher(self):
126
+ self._batcher = self.table._table_impl.mutations_batcher(**self._batcher_kwargs)
127
+ self._batcher._user_batch_completed_callback = (
128
+ self._user_batch_completed_callback
129
+ )
130
+
131
+ def _close_batcher(self):
132
+ try:
133
+ self._batcher.close()
134
+ except MutationsExceptionGroup as exc_group:
135
+ for error in exc_group.exceptions:
136
+ # Unpack the root cause of the FailedMutationEntryError and
137
+ # return that error to the user. In standard execution paths,
138
+ # FailedMutationEntryError always has an Exception cause;
139
+ # defensively wrap in Unknown if __cause__ is None.
140
+ if error.__cause__ is not None:
141
+ self._exceptions.put(error.__cause__)
142
+ else:
143
+ unknown_err = core_exceptions.Unknown(str(error))
144
+ unknown_err.__cause__ = error
145
+ self._exceptions.put(unknown_err)
146
+ except Exception as exc:
147
+ self._exceptions.put(exc)
148
+
149
+ def __enter__(self):
150
+ """Starting the MutationsBatcher as a context manager"""
151
+ return self
152
+
153
+ def mutate(self, row):
154
+ """Add a row to the batch. If the current batch meets one of the size
155
+ limits, the batch is sent asynchronously.
156
+
157
+ For example:
158
+
159
+ .. literalinclude:: snippets_table.py
160
+ :start-after: [START bigtable_api_batcher_mutate]
161
+ :end-before: [END bigtable_api_batcher_mutate]
162
+ :dedent: 4
163
+
164
+ :type row: class
165
+ :param row: :class:`~google.cloud.bigtable.row.DirectRow`.
166
+
167
+ :raises: One of the following:
168
+ * :exc:`~.table._BigtableRetryableError` if any row returned a transient error.
169
+ * :exc:`RuntimeError` if the number of responses doesn't match the number of rows that were retried
170
+ """
171
+ self._batcher.append(RowMutationEntry(row.row_key, row._get_mutations()))
172
+
173
+ def mutate_rows(self, rows):
174
+ """Add multiple rows to the batch. If the current batch meets one of the size
175
+ limits, the batch is sent asynchronously.
176
+
177
+ For example:
178
+
179
+ .. literalinclude:: snippets_table.py
180
+ :start-after: [START bigtable_api_batcher_mutate_rows]
181
+ :end-before: [END bigtable_api_batcher_mutate_rows]
182
+ :dedent: 4
183
+
184
+ :type rows: list:[`~google.cloud.bigtable.row.DirectRow`]
185
+ :param rows: list:[`~google.cloud.bigtable.row.DirectRow`].
186
+
187
+ :raises: One of the following:
188
+ * :exc:`~.table._BigtableRetryableError` if any row returned a transient error.
189
+ * :exc:`RuntimeError` if the number of responses doesn't match the number of rows that were retried
190
+ """
191
+ for row in rows:
192
+ self.mutate(row)
193
+
194
+ def flush(self):
195
+ """Sends the current batch to Cloud Bigtable synchronously.
196
+ For example:
197
+
198
+ .. literalinclude:: snippets_table.py
199
+ :start-after: [START bigtable_api_batcher_flush]
200
+ :end-before: [END bigtable_api_batcher_flush]
201
+ :dedent: 4
202
+
203
+ :raises:
204
+ * :exc:`~batcher.MutationsBatchError` if there's any error in the mutations.
205
+ """
206
+ self._close_batcher()
207
+ self._init_batcher()
208
+
209
+ def __exit__(self, exc_type, exc_value, exc_traceback):
210
+ """Clean up resources. Flush and shutdown the ThreadPoolExecutor."""
211
+ self.close()
212
+
213
+ def close(self):
214
+ """Clean up resources. Flush and shutdown the ThreadPoolExecutor.
215
+ Any errors will be raised.
216
+
217
+ :raises:
218
+ * :exc:`~batcher.MutationsBatchError` if there's any error in the mutations.
219
+ """
220
+ self._close_batcher()
221
+ atexit.unregister(self.close)
222
+ if self._exceptions.qsize() > 0:
223
+ exc = list(self._exceptions.queue)
224
+ raise MutationsBatchError("Errors in batch mutations.", exc=exc)
@@ -139,7 +139,7 @@ class _MutateRowsOperationAsync:
139
139
  self._handle_entry_error(idx, exc)
140
140
  finally:
141
141
  # raise exception detailing incomplete mutations
142
- all_errors: list[Exception] = []
142
+ all_errors: list[bt_exceptions.FailedMutationEntryError] = []
143
143
  for idx, exc_list in self.errors.items():
144
144
  if len(exc_list) == 0:
145
145
  raise core_exceptions.ClientError(
@@ -16,15 +16,20 @@ from __future__ import annotations
16
16
 
17
17
  import atexit
18
18
  import concurrent.futures
19
+ import inspect
20
+ import logging
19
21
  import time
20
22
  import warnings
21
23
  from collections import deque
22
- from typing import TYPE_CHECKING, Sequence, cast
24
+ from typing import TYPE_CHECKING, Any, Callable, Sequence, cast
25
+
26
+ from google.rpc import code_pb2, status_pb2
23
27
 
24
28
  from google.cloud.bigtable.data._cross_sync import CrossSync
25
29
  from google.cloud.bigtable.data._helpers import (
26
30
  TABLE_DEFAULT,
27
31
  _get_retryable_errors,
32
+ _get_statuses_from_mutations_exception_group,
28
33
  _get_timeouts,
29
34
  )
30
35
  from google.cloud.bigtable.data._metrics import ActiveOperationMetric, OperationType
@@ -54,6 +59,7 @@ __CROSS_SYNC_OUTPUT__ = "google.cloud.bigtable.data._sync_autogen.mutations_batc
54
59
 
55
60
  # used to make more readable default values
56
61
  _MB_SIZE = 1024 * 1024
62
+ _LOGGER = logging.getLogger(__name__)
57
63
 
58
64
 
59
65
  @CrossSync.convert_class(sync_name="_FlowControl", add_mapping_for_name="_FlowControl")
@@ -290,10 +296,14 @@ class MutationsBatcherAsync:
290
296
  self._exceptions_since_last_raise: int = 0
291
297
  # keep track of the first and last _exception_list_limit exceptions
292
298
  self._exception_list_limit: int = 10
293
- self._oldest_exceptions: list[Exception] = []
294
- self._newest_exceptions: deque[Exception] = deque(
299
+ self._oldest_exceptions: list[FailedMutationEntryError] = []
300
+ self._newest_exceptions: deque[FailedMutationEntryError] = deque(
295
301
  maxlen=self._exception_list_limit
296
302
  )
303
+ # only used by the shim right now.
304
+ self._user_batch_completed_callback: (
305
+ Callable[[list[status_pb2.Status]], Any] | None
306
+ ) = None
297
307
  # clean up on program exit
298
308
  atexit.register(self._on_exit)
299
309
 
@@ -377,7 +387,11 @@ class MutationsBatcherAsync:
377
387
  new_entries list of RowMutationEntry objects to flush
378
388
  """
379
389
  # flush new entries
380
- in_process_requests: list[CrossSync.Future[list[FailedMutationEntryError]]] = []
390
+ in_process_requests: list[
391
+ tuple[
392
+ CrossSync.Future[list[FailedMutationEntryError]], list[RowMutationEntry]
393
+ ]
394
+ ] = []
381
395
  async for batch, metric in self._flow_control.add_to_flow_with_metrics(
382
396
  new_entries, self._target.client._metrics
383
397
  ):
@@ -387,7 +401,7 @@ class MutationsBatcherAsync:
387
401
  metric,
388
402
  sync_executor=self._sync_rpc_executor,
389
403
  )
390
- in_process_requests.append(batch_task)
404
+ in_process_requests.append((batch_task, batch))
391
405
  # wait for all inflight requests to complete
392
406
  found_exceptions = await self._wait_for_batch_results(*in_process_requests)
393
407
  # update exception data to reflect any new errors
@@ -410,6 +424,7 @@ class MutationsBatcherAsync:
410
424
  list of FailedMutationEntryError objects for mutations that failed.
411
425
  FailedMutationEntryError objects will not contain index information
412
426
  """
427
+ statuses = [status_pb2.Status(code=code_pb2.UNKNOWN) for _ in range(len(batch))]
413
428
  try:
414
429
  operation = CrossSync._MutateRowsOperation(
415
430
  self._target.client._gapic_client,
@@ -422,16 +437,41 @@ class MutationsBatcherAsync:
422
437
  )
423
438
  await operation.start()
424
439
  except MutationsExceptionGroup as e:
440
+ statuses = _get_statuses_from_mutations_exception_group(e, len(batch))
441
+
425
442
  # strip index information from exceptions, since it is not useful in a batch context
426
443
  for subexc in e.exceptions:
427
444
  subexc.index = None
428
445
  return list(e.exceptions)
446
+ else:
447
+ statuses = [status_pb2.Status(code=code_pb2.OK) for _ in range(len(batch))]
429
448
  finally:
430
449
  # mark batch as complete in flow control
431
450
  await self._flow_control.remove_from_flow(batch)
451
+
452
+ # Call batch done callback with list of statuses.
453
+ # This is an internal callback used by the legacy synchronous shim,
454
+ # though async callbacks are awaited when running in async mode.
455
+ if self._user_batch_completed_callback:
456
+ try:
457
+ result = self._user_batch_completed_callback(statuses)
458
+ if CrossSync.is_async:
459
+ if inspect.isawaitable(result):
460
+ await result
461
+ else:
462
+ if inspect.isawaitable(result):
463
+ if inspect.iscoroutine(result):
464
+ result.close()
465
+ raise TypeError(
466
+ "_user_batch_completed_callback must be a synchronous callable"
467
+ )
468
+ except Exception as exc:
469
+ _LOGGER.warning(
470
+ f"Exception raised in user batch completion callback: {exc}"
471
+ )
432
472
  return []
433
473
 
434
- def _add_exceptions(self, excs: list[Exception]):
474
+ def _add_exceptions(self, excs: list[FailedMutationEntryError]):
435
475
  """
436
476
  Add new list of exceptions to internal store. To avoid unbounded memory,
437
477
  the batcher will store the first and last _exception_list_limit exceptions,
@@ -531,26 +571,28 @@ class MutationsBatcherAsync:
531
571
  @staticmethod
532
572
  @CrossSync.convert
533
573
  async def _wait_for_batch_results(
534
- *tasks: CrossSync.Future[list[FailedMutationEntryError]]
535
- | CrossSync.Future[None],
536
- ) -> list[Exception]:
574
+ *tasks: tuple[
575
+ CrossSync.Future[list[FailedMutationEntryError]] | CrossSync.Future[None],
576
+ list[RowMutationEntry],
577
+ ],
578
+ ) -> list[FailedMutationEntryError]:
537
579
  """
538
580
  Takes in a list of futures representing _execute_mutate_rows tasks,
539
581
  waits for them to complete, and returns a list of errors encountered.
540
582
 
541
583
  Args:
542
- *tasks: futures representing _execute_mutate_rows or _flush_internal tasks
584
+ *tasks: Tuples of futures representing _execute_mutate_rows or
585
+ _flush_internal tasks, and their associated batches
543
586
  Returns:
544
- list[Exception]:
545
- list of Exceptions encountered by any of the tasks. Errors are expected
546
- to be FailedMutationEntryError, representing a failed mutation operation.
547
- If a task fails with a different exception, it will be included in the
548
- output list. Successful tasks will not be represented in the output list.
587
+ list[FailedMutationEntryError]:
588
+ list of FailedMutationEntryError encountered by any of the tasks,
589
+ representing a failed mutation operation.
590
+ Successful tasks will not be represented in the output list.
549
591
  """
550
592
  if not tasks:
551
593
  return []
552
- exceptions: list[Exception] = []
553
- for task in tasks:
594
+ exceptions: list[FailedMutationEntryError] = []
595
+ for task, batch in tasks:
554
596
  if CrossSync.is_async:
555
597
  # futures don't need to be awaited in sync mode
556
598
  await task
@@ -563,5 +605,13 @@ class MutationsBatcherAsync:
563
605
  exc.index = None
564
606
  exceptions.extend(exc_list)
565
607
  except Exception as e:
566
- exceptions.append(e)
608
+ exceptions.extend(
609
+ [
610
+ FailedMutationEntryError(
611
+ failed_idx=None, failed_mutation_entry=entry, cause=e
612
+ )
613
+ for entry in batch
614
+ ]
615
+ )
616
+
567
617
  return exceptions
@@ -24,6 +24,7 @@ from typing import (
24
24
  TYPE_CHECKING,
25
25
  Callable,
26
26
  List,
27
+ Optional,
27
28
  Sequence,
28
29
  Tuple,
29
30
  Union,
@@ -32,8 +33,12 @@ from typing import (
32
33
  from google.api_core import exceptions as core_exceptions
33
34
  from google.api_core import retry as retries
34
35
  from google.api_core.retry import RetryFailureReason, exponential_sleep_generator
36
+ from google.rpc import code_pb2, status_pb2
35
37
 
36
- from google.cloud.bigtable.data.exceptions import RetryExceptionGroup
38
+ from google.cloud.bigtable.data.exceptions import (
39
+ MutationsExceptionGroup,
40
+ RetryExceptionGroup,
41
+ )
37
42
  from google.cloud.bigtable.data.read_rows_query import ReadRowsQuery
38
43
 
39
44
  if TYPE_CHECKING:
@@ -238,6 +243,66 @@ def _align_timeouts(operation: float, attempt: float | None) -> tuple[float, flo
238
243
  return operation, final_attempt
239
244
 
240
245
 
246
+ def _get_statuses_from_mutations_exception_group(
247
+ exc_group: MutationsExceptionGroup, batch_size: int
248
+ ) -> list[status_pb2.Status]:
249
+ """
250
+ Helper function that populates a list of Status objects with exception information from
251
+ the exception group.
252
+
253
+ Args:
254
+ exc_group: The exception group from a mutate rows operation
255
+ batch_size: How many RowMutationGroups were provided to the batch
256
+ Returns:
257
+ list[status_pb2.Status]: A list of Status proto objects
258
+ """
259
+ # We exception handle as follows:
260
+ #
261
+ # 1. Each exception in the error group is a FailedMutationEntryError, and its
262
+ # cause is either a singular exception or a RetryExceptionGroup consisting of
263
+ # multiple exceptions.
264
+ #
265
+ # 2. In the case of a singular exception, if the error does not have a gRPC status
266
+ # code, we return a status code of UNKNOWN.
267
+ #
268
+ # 3. In the case of a RetryExceptionGroup, we use terminal exception in the exception
269
+ # group and process that.
270
+ statuses = [status_pb2.Status(code=code_pb2.OK) for _ in range(batch_size)]
271
+ for error in exc_group.exceptions:
272
+ if isinstance(error.index, int) and 0 <= error.index < len(statuses):
273
+ cause = error.__cause__
274
+ if isinstance(cause, RetryExceptionGroup):
275
+ statuses[error.index] = _get_status(cause.exceptions[-1])
276
+ else:
277
+ statuses[error.index] = _get_status(cause)
278
+ return statuses
279
+
280
+
281
+ def _get_status(exc: Optional[Exception]) -> status_pb2.Status:
282
+ """
283
+ Helper function that returns a Status object corresponding to the given exception.
284
+
285
+ Args:
286
+ exc: An exception to be converted into a Status.
287
+ Returns:
288
+ status_pb2.Status: A Status proto object.
289
+ """
290
+ if (
291
+ isinstance(exc, core_exceptions.GoogleAPICallError)
292
+ and exc.grpc_status_code is not None
293
+ ):
294
+ return status_pb2.Status( # type: ignore[unreachable]
295
+ code=exc.grpc_status_code.value[0],
296
+ message=exc.message,
297
+ details=exc.details,
298
+ )
299
+
300
+ return status_pb2.Status(
301
+ code=code_pb2.UNKNOWN,
302
+ message=str(exc) if exc else "An unknown error has occurred",
303
+ )
304
+
305
+
241
306
  def _validate_timeouts(
242
307
  operation_timeout: float, attempt_timeout: float | None, allow_none: bool = False
243
308
  ):
@@ -112,7 +112,7 @@ class _MutateRowsOperation:
112
112
  for idx in incomplete_indices:
113
113
  self._handle_entry_error(idx, exc)
114
114
  finally:
115
- all_errors: list[Exception] = []
115
+ all_errors: list[bt_exceptions.FailedMutationEntryError] = []
116
116
  for idx, exc_list in self.errors.items():
117
117
  if len(exc_list) == 0:
118
118
  raise core_exceptions.ClientError(
@@ -19,15 +19,20 @@ from __future__ import annotations
19
19
 
20
20
  import atexit
21
21
  import concurrent.futures
22
+ import inspect
23
+ import logging
22
24
  import time
23
25
  import warnings
24
26
  from collections import deque
25
- from typing import TYPE_CHECKING, Sequence, cast
27
+ from typing import TYPE_CHECKING, Any, Callable, Sequence, cast
28
+
29
+ from google.rpc import code_pb2, status_pb2
26
30
 
27
31
  from google.cloud.bigtable.data._cross_sync import CrossSync
28
32
  from google.cloud.bigtable.data._helpers import (
29
33
  TABLE_DEFAULT,
30
34
  _get_retryable_errors,
35
+ _get_statuses_from_mutations_exception_group,
31
36
  _get_timeouts,
32
37
  )
33
38
  from google.cloud.bigtable.data._metrics import ActiveOperationMetric, OperationType
@@ -47,6 +52,7 @@ if TYPE_CHECKING:
47
52
  )
48
53
  from google.cloud.bigtable.data.mutations import RowMutationEntry
49
54
  _MB_SIZE = 1024 * 1024
55
+ _LOGGER = logging.getLogger(__name__)
50
56
 
51
57
 
52
58
  @CrossSync._Sync_Impl.add_mapping_decorator("_FlowControl")
@@ -255,10 +261,13 @@ class MutationsBatcher:
255
261
  self._entries_processed_since_last_raise: int = 0
256
262
  self._exceptions_since_last_raise: int = 0
257
263
  self._exception_list_limit: int = 10
258
- self._oldest_exceptions: list[Exception] = []
259
- self._newest_exceptions: deque[Exception] = deque(
264
+ self._oldest_exceptions: list[FailedMutationEntryError] = []
265
+ self._newest_exceptions: deque[FailedMutationEntryError] = deque(
260
266
  maxlen=self._exception_list_limit
261
267
  )
268
+ self._user_batch_completed_callback: (
269
+ Callable[[list[status_pb2.Status]], Any] | None
270
+ ) = None
262
271
  atexit.register(self._on_exit)
263
272
 
264
273
  def _timer_routine(self, interval: float | None) -> None:
@@ -326,7 +335,10 @@ class MutationsBatcher:
326
335
  Args:
327
336
  new_entries list of RowMutationEntry objects to flush"""
328
337
  in_process_requests: list[
329
- CrossSync._Sync_Impl.Future[list[FailedMutationEntryError]]
338
+ tuple[
339
+ CrossSync._Sync_Impl.Future[list[FailedMutationEntryError]],
340
+ list[RowMutationEntry],
341
+ ]
330
342
  ] = []
331
343
  for batch, metric in self._flow_control.add_to_flow_with_metrics(
332
344
  new_entries, self._target.client._metrics
@@ -337,7 +349,7 @@ class MutationsBatcher:
337
349
  metric,
338
350
  sync_executor=self._sync_rpc_executor,
339
351
  )
340
- in_process_requests.append(batch_task)
352
+ in_process_requests.append((batch_task, batch))
341
353
  found_exceptions = self._wait_for_batch_results(*in_process_requests)
342
354
  self._entries_processed_since_last_raise += len(new_entries)
343
355
  self._add_exceptions(found_exceptions)
@@ -355,6 +367,7 @@ class MutationsBatcher:
355
367
  list[FailedMutationEntryError]:
356
368
  list of FailedMutationEntryError objects for mutations that failed.
357
369
  FailedMutationEntryError objects will not contain index information"""
370
+ statuses = [status_pb2.Status(code=code_pb2.UNKNOWN) for _ in range(len(batch))]
358
371
  try:
359
372
  operation = CrossSync._Sync_Impl._MutateRowsOperation(
360
373
  self._target.client._gapic_client,
@@ -367,14 +380,30 @@ class MutationsBatcher:
367
380
  )
368
381
  operation.start()
369
382
  except MutationsExceptionGroup as e:
383
+ statuses = _get_statuses_from_mutations_exception_group(e, len(batch))
370
384
  for subexc in e.exceptions:
371
385
  subexc.index = None
372
386
  return list(e.exceptions)
387
+ else:
388
+ statuses = [status_pb2.Status(code=code_pb2.OK) for _ in range(len(batch))]
373
389
  finally:
374
390
  self._flow_control.remove_from_flow(batch)
391
+ if self._user_batch_completed_callback:
392
+ try:
393
+ result = self._user_batch_completed_callback(statuses)
394
+ if inspect.isawaitable(result):
395
+ if inspect.iscoroutine(result):
396
+ result.close()
397
+ raise TypeError(
398
+ "_user_batch_completed_callback must be a synchronous callable"
399
+ )
400
+ except Exception as exc:
401
+ _LOGGER.warning(
402
+ f"Exception raised in user batch completion callback: {exc}"
403
+ )
375
404
  return []
376
405
 
377
- def _add_exceptions(self, excs: list[Exception]):
406
+ def _add_exceptions(self, excs: list[FailedMutationEntryError]):
378
407
  """Add new list of exceptions to internal store. To avoid unbounded memory,
379
408
  the batcher will store the first and last _exception_list_limit exceptions,
380
409
  and discard any in between.
@@ -453,24 +482,27 @@ class MutationsBatcher:
453
482
 
454
483
  @staticmethod
455
484
  def _wait_for_batch_results(
456
- *tasks: CrossSync._Sync_Impl.Future[list[FailedMutationEntryError]]
457
- | CrossSync._Sync_Impl.Future[None],
458
- ) -> list[Exception]:
485
+ *tasks: tuple[
486
+ CrossSync._Sync_Impl.Future[list[FailedMutationEntryError]]
487
+ | CrossSync._Sync_Impl.Future[None],
488
+ list[RowMutationEntry],
489
+ ],
490
+ ) -> list[FailedMutationEntryError]:
459
491
  """Takes in a list of futures representing _execute_mutate_rows tasks,
460
492
  waits for them to complete, and returns a list of errors encountered.
461
493
 
462
494
  Args:
463
- *tasks: futures representing _execute_mutate_rows or _flush_internal tasks
495
+ *tasks: Tuples of futures representing _execute_mutate_rows or
496
+ _flush_internal tasks, and their associated batches
464
497
  Returns:
465
- list[Exception]:
466
- list of Exceptions encountered by any of the tasks. Errors are expected
467
- to be FailedMutationEntryError, representing a failed mutation operation.
468
- If a task fails with a different exception, it will be included in the
469
- output list. Successful tasks will not be represented in the output list."""
498
+ list[FailedMutationEntryError]:
499
+ list of FailedMutationEntryError encountered by any of the tasks,
500
+ representing a failed mutation operation.
501
+ Successful tasks will not be represented in the output list."""
470
502
  if not tasks:
471
503
  return []
472
- exceptions: list[Exception] = []
473
- for task in tasks:
504
+ exceptions: list[FailedMutationEntryError] = []
505
+ for task, batch in tasks:
474
506
  try:
475
507
  exc_list = task.result()
476
508
  if exc_list:
@@ -478,5 +510,12 @@ class MutationsBatcher:
478
510
  exc.index = None
479
511
  exceptions.extend(exc_list)
480
512
  except Exception as e:
481
- exceptions.append(e)
513
+ exceptions.extend(
514
+ [
515
+ FailedMutationEntryError(
516
+ failed_idx=None, failed_mutation_entry=entry, cause=e
517
+ )
518
+ for entry in batch
519
+ ]
520
+ )
482
521
  return exceptions